From 3372e480d8393b7b5f9dcea425f71d37db7af1a1 Mon Sep 17 00:00:00 2001 From: overweight Date: Fri, 30 Apr 2021 05:23:09 -0400 Subject: [PATCH 1/2] delete unused patches --- ...0017-fix-capsh-drop-but-ping-success.patch | 0 ...e-etc-resolv.conf-symlink-at-runtime.patch | 0 ...-pids-until-the-processes-have-been-.patch | 0 ...-make-sure-to-unwatch-all-PIDs-once-.patch | 0 ...ware-of-delegated-cgroup-controllers.patch | 99 -- ...r-instance-aware-of-delegated-cgroup.patch | 163 --- ...t-allocate-max-length-to-read-proc-P.patch | 107 -- ...rdata-pointer-inheritance-from-varli.patch | 160 --- ...wer-most-info-messages-to-debug-leve.patch | 76 - ...dd-unit-files-to-dump-the-unit-fragm.patch | 93 -- ...drop-unit-caches-only-based-on-mtime.patch | 289 ---- ...id1-use-a-cache-for-all-unit-aliases.patch | 1226 ----------------- ...it-file-add-a-function-to-validate-u.patch | 177 --- systemd.spec | 13 +- 14 files changed, 8 insertions(+), 2395 deletions(-) rename fix-capsh-drop-but-ping-success.patch => 0017-fix-capsh-drop-but-ping-success.patch (100%) rename 0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch => 0018-resolved-create-etc-resolv.conf-symlink-at-runtime.patch (100%) rename core-serialize-u-pids-until-the-processes-have-been-.patch => 0019-core-serialize-u-pids-until-the-processes-have-been-.patch (100%) rename scope-on-unified-make-sure-to-unwatch-all-PIDs-once-.patch => 0020-scope-on-unified-make-sure-to-unwatch-all-PIDs-once-.patch (100%) delete mode 100644 backport-RFC-Make-user-instance-aware-of-delegated-cgroup-controllers.patch delete mode 100644 backport-core-Make-user-instance-aware-of-delegated-cgroup.patch delete mode 100644 backport-process-util-dont-allocate-max-length-to-read-proc-P.patch delete mode 100644 backport-varlink-make-userdata-pointer-inheritance-from-varli.patch delete mode 100644 backport-xdg-autostart-Lower-most-info-messages-to-debug-leve.patch delete mode 100644 revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch delete mode 100644 revert-pid1-drop-unit-caches-only-based-on-mtime.patch delete mode 100644 revert-pid1-use-a-cache-for-all-unit-aliases.patch delete mode 100644 revert-shared-unit-file-add-a-function-to-validate-u.patch diff --git a/fix-capsh-drop-but-ping-success.patch b/0017-fix-capsh-drop-but-ping-success.patch similarity index 100% rename from fix-capsh-drop-but-ping-success.patch rename to 0017-fix-capsh-drop-but-ping-success.patch diff --git a/0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch b/0018-resolved-create-etc-resolv.conf-symlink-at-runtime.patch similarity index 100% rename from 0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch rename to 0018-resolved-create-etc-resolv.conf-symlink-at-runtime.patch diff --git a/core-serialize-u-pids-until-the-processes-have-been-.patch b/0019-core-serialize-u-pids-until-the-processes-have-been-.patch similarity index 100% rename from core-serialize-u-pids-until-the-processes-have-been-.patch rename to 0019-core-serialize-u-pids-until-the-processes-have-been-.patch diff --git a/scope-on-unified-make-sure-to-unwatch-all-PIDs-once-.patch b/0020-scope-on-unified-make-sure-to-unwatch-all-PIDs-once-.patch similarity index 100% rename from scope-on-unified-make-sure-to-unwatch-all-PIDs-once-.patch rename to 0020-scope-on-unified-make-sure-to-unwatch-all-PIDs-once-.patch diff --git a/backport-RFC-Make-user-instance-aware-of-delegated-cgroup-controllers.patch b/backport-RFC-Make-user-instance-aware-of-delegated-cgroup-controllers.patch deleted file mode 100644 index b8f46e48..00000000 --- a/backport-RFC-Make-user-instance-aware-of-delegated-cgroup-controllers.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 81504017f462db1ef4ce2c1f617535f261fe01cc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20Koutn=C3=BD?= -Date: Tue, 26 Jan 2021 17:07:00 +0100 -Subject: [PATCH] cgroup: Simplify cg_get_path_and_check - -The function controller_is_accessible() doesn't do really much in case -of the unified hierarchy. Move common parts into cg_get_path_and_check -and make controller check v1 specific. This is refactoring only. ---- - src/basic/cgroup-util.c | 56 ++++++++++++++++------------------------- - 1 file changed, 22 insertions(+), 34 deletions(-) - -diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c -index bb20a12294d..fcab1775bd5 100644 ---- a/src/basic/cgroup-util.c -+++ b/src/basic/cgroup-util.c -@@ -527,41 +527,16 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch - return 0; - } - --static int controller_is_accessible(const char *controller) { -- int r; -+static int controller_is_v1_accessible(const char *controller) { -+ const char *cc, *dn; - - assert(controller); - -- /* Checks whether a specific controller is accessible, -- * i.e. its hierarchy mounted. In the unified hierarchy all -- * controllers are considered accessible, except for the named -- * hierarchies */ -- -- if (!cg_controller_is_valid(controller)) -- return -EINVAL; -- -- r = cg_all_unified(); -- if (r < 0) -- return r; -- if (r > 0) { -- /* We don't support named hierarchies if we are using -- * the unified hierarchy. */ -- -- if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) -- return 0; -- -- if (startswith(controller, "name=")) -- return -EOPNOTSUPP; -- -- } else { -- const char *cc, *dn; -- -- dn = controller_to_dirname(controller); -- cc = strjoina("/sys/fs/cgroup/", dn); -+ dn = controller_to_dirname(controller); -+ cc = strjoina("/sys/fs/cgroup/", dn); - -- if (laccess(cc, F_OK) < 0) -- return -errno; -- } -+ if (laccess(cc, F_OK) < 0) -+ return -errno; - - return 0; - } -@@ -572,10 +547,23 @@ int cg_get_path_and_check(const char *controller, const char *path, const char * - assert(controller); - assert(fs); - -- /* Check if the specified controller is actually accessible */ -- r = controller_is_accessible(controller); -+ if (!cg_controller_is_valid(controller)) -+ return -EINVAL; -+ -+ r = cg_all_unified(); - if (r < 0) - return r; -+ if (r > 0) { -+ /* In the unified hierarchy all controllers are considered accessible, -+ * except for the named hierarchies */ -+ if (startswith(controller, "name=")) -+ return -EOPNOTSUPP; -+ } else { -+ /* Check if the specified controller is actually accessible */ -+ r = controller_is_v1_accessible(controller); -+ if (r < 0) -+ return r; -+ } - - return cg_get_path(controller, path, suffix, fs); - } -@@ -1909,7 +1897,7 @@ int cg_mask_supported(CGroupMask *ret) { - continue; - - n = cgroup_controller_to_string(c); -- if (controller_is_accessible(n) >= 0) -+ if (controller_is_v1_accessible(n) >= 0) - mask |= bit; - } - } diff --git a/backport-core-Make-user-instance-aware-of-delegated-cgroup.patch b/backport-core-Make-user-instance-aware-of-delegated-cgroup.patch deleted file mode 100644 index b181fa76..00000000 --- a/backport-core-Make-user-instance-aware-of-delegated-cgroup.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 0fa7b50053695a3012af71c719dd86c12ab10fc6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michal=20Koutn=C3=BD?= -Date: Tue, 26 Jan 2021 19:15:45 +0100 -Subject: [PATCH] core: Make (user) instance aware of delegated cgroup - controllers - -systemd user instance assumed same controllers are available to it as to -PID 1. That is not true generally, in v1 (legacy, hybrid) we don't delegate any -controllers to anyone and in v2 (unified) we may delegate only subset of -controllers. -The user instance would fail silently when the controller cgroup cannot -be created or the controller cannot be enabled on the unified hierarchy. - -The changes in 7b63961415 ("cgroup: Swap cgroup v1 deletion and -migration") caused some attempts of operating on non-delegated -controllers to be logged. - -Make the user instance first check what controllers are availble to it -and narrow operations only to these controllers. The original checks are -kept in place. - -Note that daemon-reexec needs to be invoked in order to update the set -of unabled controllers after a change. - -Fixes: #18047 -Fixes: #17862 ---- - src/basic/cgroup-util.c | 41 +++++++++++++++++++++++++++-------------- - src/basic/cgroup-util.h | 1 + - src/core/cgroup.c | 2 +- - 3 files changed, 29 insertions(+), 15 deletions(-) - -diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c -index 19c0a9d..7ef30f2 100644 ---- a/src/basic/cgroup-util.c -+++ b/src/basic/cgroup-util.c -@@ -527,15 +527,21 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch - return 0; - } - --static int controller_is_v1_accessible(const char *controller) { -- const char *cc, *dn; -+static int controller_is_v1_accessible(const char *root, const char *controller) { -+ const char *cpath, *dn; - - assert(controller); - - dn = controller_to_dirname(controller); -- cc = strjoina("/sys/fs/cgroup/", dn); -- -- if (laccess(cc, F_OK) < 0) -+ cpath = strjoina("/sys/fs/cgroup/", dn); -+ if (root) -+ /* Also check that: -+ * - possible subcgroup is created at root, -+ * - we can modify the hierarchy. -+ * "Leak" cpath on stack */ -+ cpath = strjoina(cpath, root, "/cgroup.procs"); -+ -+ if (laccess(cpath, root ? W_OK : F_OK) < 0) - return -errno; - - return 0; -@@ -560,7 +566,7 @@ int cg_get_path_and_check(const char *controller, const char *path, const char * - return -EOPNOTSUPP; - } else { - /* Check if the specified controller is actually accessible */ -- r = controller_is_v1_accessible(controller); -+ r = controller_is_v1_accessible(NULL, controller); - if (r < 0) - return r; - } -@@ -1829,7 +1835,7 @@ int cg_mask_from_string(const char *value, CGroupMask *ret) { - return 0; - } - --int cg_mask_supported(CGroupMask *ret) { -+int cg_mask_supported_subtree(const char *root, CGroupMask *ret) { - CGroupMask mask; - int r; - -@@ -1841,16 +1847,12 @@ int cg_mask_supported(CGroupMask *ret) { - if (r < 0) - return r; - if (r > 0) { -- _cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL; -+ _cleanup_free_ char *controllers = NULL, *path = NULL; - - /* In the unified hierarchy we can read the supported - * and accessible controllers from a the top-level - * cgroup attribute */ - -- r = cg_get_root_path(&root); -- if (r < 0) -- return r; -- - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path); - if (r < 0) - return r; -@@ -1869,7 +1871,7 @@ int cg_mask_supported(CGroupMask *ret) { - } else { - CGroupController c; - -- /* In the legacy hierarchy, we check which hierarchies are mounted. */ -+ /* In the legacy hierarchy, we check which hierarchies are accessible. */ - - mask = 0; - for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { -@@ -1880,7 +1882,7 @@ int cg_mask_supported(CGroupMask *ret) { - continue; - - n = cgroup_controller_to_string(c); -- if (controller_is_v1_accessible(n) >= 0) -+ if (controller_is_v1_accessible(root, n) >= 0) - mask |= bit; - } - } -@@ -1889,6 +1891,17 @@ int cg_mask_supported(CGroupMask *ret) { - return 0; - } - -+int cg_mask_supported(CGroupMask *ret) { -+ _cleanup_free_ char *root = NULL; -+ int r; -+ -+ r = cg_get_root_path(&root); -+ if (r < 0) -+ return r; -+ -+ return cg_mask_supported_subtree(root, ret); -+} -+ - int cg_kernel_controllers(Set **ret) { - _cleanup_set_free_free_ Set *controllers = NULL; - _cleanup_fclose_ FILE *f = NULL; -diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h -index 2b88571..2b3b068 100644 ---- a/src/basic/cgroup-util.h -+++ b/src/basic/cgroup-util.h -@@ -254,6 +254,7 @@ int cg_slice_to_path(const char *unit, char **ret); - typedef const char* (*cg_migrate_callback_t)(CGroupMask mask, void *userdata); - - int cg_mask_supported(CGroupMask *ret); -+int cg_mask_supported_subtree(const char *root, CGroupMask *ret); - int cg_mask_from_string(const char *s, CGroupMask *ret); - int cg_mask_to_string(CGroupMask mask, char **ret); - -diff --git a/src/core/cgroup.c b/src/core/cgroup.c -index 8b97d15..57b4974 100644 ---- a/src/core/cgroup.c -+++ b/src/core/cgroup.c -@@ -3010,7 +3010,7 @@ int manager_setup_cgroup(Manager *m) { - (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1"); - - /* 8. Figure out which controllers are supported */ -- r = cg_mask_supported(&m->cgroup_supported); -+ r = cg_mask_supported_subtree(m->cgroup_root, &m->cgroup_supported); - if (r < 0) - return log_error_errno(r, "Failed to determine supported controllers: %m"); - --- -2.23.0 - diff --git a/backport-process-util-dont-allocate-max-length-to-read-proc-P.patch b/backport-process-util-dont-allocate-max-length-to-read-proc-P.patch deleted file mode 100644 index a910eb0d..00000000 --- a/backport-process-util-dont-allocate-max-length-to-read-proc-P.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 7b7a060e83d6c7de8705904d71978ba4664f0a65 Mon Sep 17 00:00:00 2001 -From: Anita Zhang -Date: Tue, 23 Mar 2021 00:49:28 -0700 -Subject: [PATCH] process-util: dont allocate max length to read - /proc/PID/cmdline - -Alternative title: Replace get_process_cmdline()'s fopen()/fread() with -read_full_virtual_file(). - -When RLIMIT_STACK is set to infinity:infinity, _SC_ARG_MAX will -return 4611686018427387903 (depending on the system, but definitely -something larger than most systems have). It's impractical to allocate this -in one go when most cmdlines are much shorter than that. - -Instead use read_full_virtual_file() which seems to increase the buffer -depending on the size of the contents. ---- - src/basic/process-util.c | 28 +++------------------------- - src/test/test-process-util.c | 5 +++++ - 2 files changed, 8 insertions(+), 25 deletions(-) - -diff --git a/src/basic/process-util.c b/src/basic/process-util.c -index 264ecc276b..7d4301eadb 100644 ---- a/src/basic/process-util.c -+++ b/src/basic/process-util.c -@@ -124,14 +124,10 @@ int get_process_comm(pid_t pid, char **ret) { - } - - int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line) { -- _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *t = NULL, *ans = NULL; - const char *p; -- int r; - size_t k; -- -- /* This is supposed to be a safety guard against runaway command lines. */ -- size_t max_length = sc_arg_max(); -+ int r; - - assert(line); - assert(pid >= 0); -@@ -147,36 +143,18 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags - * comm_fallback is false). Returns 0 and sets *line otherwise. */ - - p = procfs_file_alloca(pid, "cmdline"); -- r = fopen_unlocked(p, "re", &f); -+ r = read_full_virtual_file(p, &t, &k); - if (r == -ENOENT) - return -ESRCH; - if (r < 0) - return r; - -- /* We assume that each four-byte character uses one or two columns. If we ever check for combining -- * characters, this assumption will need to be adjusted. */ -- if ((size_t) 4 * max_columns + 1 < max_columns) -- max_length = MIN(max_length, (size_t) 4 * max_columns + 1); -- -- t = new(char, max_length); -- if (!t) -- return -ENOMEM; -- -- k = fread(t, 1, max_length, f); - if (k > 0) { - /* Arguments are separated by NULs. Let's replace those with spaces. */ - for (size_t i = 0; i < k - 1; i++) - if (t[i] == '\0') - t[i] = ' '; -- -- t[k] = '\0'; /* Normally, t[k] is already NUL, so this is just a guard in case of short read */ - } else { -- /* We only treat getting nothing as an error. We *could* also get an error after reading some -- * data, but we ignore that case, as such an error is rather unlikely and we prefer to get -- * some data rather than none. */ -- if (ferror(f)) -- return -errno; -- - if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK)) - return -ENOENT; - -@@ -187,7 +165,7 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags - if (r < 0) - return r; - -- mfree(t); -+ free(t); - t = strjoin("[", t2, "]"); - if (!t) - return -ENOMEM; -diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c -index 0ebef530a0..5ca654e193 100644 ---- a/src/test/test-process-util.c -+++ b/src/test/test-process-util.c -@@ -236,6 +236,11 @@ static void test_get_process_cmdline_harder(void) { - return; - } - -+ /* Set RLIMIT_STACK to infinity to test we don't try to allocate unncessarily large values to read -+ * the cmdline. */ -+ if (setrlimit(RLIMIT_STACK, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0) -+ log_warning("Testing without RLIMIT_STACK=infinity"); -+ - assert_se(unlink(path) >= 0); - - assert_se(prctl(PR_SET_NAME, "testa") >= 0); --- -2.23.0 - diff --git a/backport-varlink-make-userdata-pointer-inheritance-from-varli.patch b/backport-varlink-make-userdata-pointer-inheritance-from-varli.patch deleted file mode 100644 index fd0c489b..00000000 --- a/backport-varlink-make-userdata-pointer-inheritance-from-varli.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 9807fdc1da8e037ddedfa4e2c6d2728b6e60051e Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Wed, 20 Jan 2021 19:15:55 +0100 -Subject: [PATCH] varlink: make 'userdata' pointer inheritance from varlink - server to connection optional - -@keszybz's right on -https://github.com/systemd/systemd/pull/18248#issuecomment-760798473: -swapping out the userdata pointer of a live varlink connection is iffy. - -Let's fix this by making the userdata inheritance from VarlinkServer -object to the Varlink connection object optional: we want it for most -cases, but not all, i.e. all those cases where the calls implemented as -varlink methods are stateless and can be answered synchronously. For the -other cases (i.e. where we want per-connection objects that wrap the -asynchronous operation as it goes on) let's not do such inheritance but -initialize the userdata pointer only once we have it. THis means the -original manager object must be manually retrieved from the -VarlinkServer object, which in turn needs to be requested from the -Varlink connection object. - -The userdata inheritance is now controlled by the -VARLINK_INHERIT_USERDATA flag passed at VarlinkServer construction. - -Alternative-to: #18248 ---- - src/core/core-varlink.c | 2 +- - src/home/homed-manager.c | 2 +- - src/journal/journald-server.c | 2 +- - src/machine/machined-varlink.c | 2 +- - src/resolve/resolved-varlink.c | 8 ++++++-- - src/shared/varlink.c | 4 +++- - src/shared/varlink.h | 9 +++++---- - 7 files changed, 18 insertions(+), 11 deletions(-) - -diff --git a/src/core/core-varlink.c b/src/core/core-varlink.c -index dd6c11ab4d..d695106658 100644 ---- a/src/core/core-varlink.c -+++ b/src/core/core-varlink.c -@@ -432,7 +432,7 @@ int manager_varlink_init(Manager *m) { - if (!MANAGER_IS_SYSTEM(m)) - return 0; - -- r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID); -+ r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA); - if (r < 0) - return log_error_errno(r, "Failed to allocate varlink server object: %m"); - -diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c -index 365ea4d234..91cabd5cef 100644 ---- a/src/home/homed-manager.c -+++ b/src/home/homed-manager.c -@@ -956,7 +956,7 @@ static int manager_bind_varlink(Manager *m) { - assert(m); - assert(!m->varlink_server); - -- r = varlink_server_new(&m->varlink_server, VARLINK_SERVER_ACCOUNT_UID); -+ r = varlink_server_new(&m->varlink_server, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA); - if (r < 0) - return log_error_errno(r, "Failed to allocate varlink server object: %m"); - -diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c -index 10ebc3e22e..5cad374083 100644 ---- a/src/journal/journald-server.c -+++ b/src/journal/journald-server.c -@@ -2033,7 +2033,7 @@ static int server_open_varlink(Server *s, const char *socket, int fd) { - - assert(s); - -- r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY); -+ r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_INHERIT_USERDATA); - if (r < 0) - return r; - -diff --git a/src/machine/machined-varlink.c b/src/machine/machined-varlink.c -index 2d6c1991a4..009d283acc 100644 ---- a/src/machine/machined-varlink.c -+++ b/src/machine/machined-varlink.c -@@ -388,7 +388,7 @@ int manager_varlink_init(Manager *m) { - if (m->varlink_server) - return 0; - -- r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID); -+ r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA); - if (r < 0) - return log_error_errno(r, "Failed to allocate varlink server object: %m"); - -diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c -index 70d6f9056d..2fb9d38dfa 100644 ---- a/src/resolve/resolved-varlink.c -+++ b/src/resolve/resolved-varlink.c -@@ -269,11 +269,13 @@ static int vl_method_resolve_hostname(Varlink *link, JsonVariant *parameters, Va - _cleanup_(lookup_parameters_destroy) LookupParameters p = { - .family = AF_UNSPEC, - }; -- Manager *m = userdata; - DnsQuery *q; -+ Manager *m; - int r; - - assert(link); -+ -+ m = varlink_server_get_userdata(varlink_get_server(link)); - assert(m); - - if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) -@@ -447,11 +449,13 @@ static int vl_method_resolve_address(Varlink *link, JsonVariant *parameters, Var - _cleanup_(lookup_parameters_destroy) LookupParameters p = { - .family = AF_UNSPEC, - }; -- Manager *m = userdata; - DnsQuery *q; -+ Manager *m; - int r; - - assert(link); -+ -+ m = varlink_server_get_userdata(varlink_get_server(link)); - assert(m); - - if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) -diff --git a/src/shared/varlink.c b/src/shared/varlink.c -index 274709abd5..24865fa07e 100644 ---- a/src/shared/varlink.c -+++ b/src/shared/varlink.c -@@ -2137,7 +2137,9 @@ int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret) - return r; - - v->fd = fd; -- v->userdata = server->userdata; -+ if (server->flags & VARLINK_SERVER_INHERIT_USERDATA) -+ v->userdata = server->userdata; -+ - if (ucred_acquired) { - v->ucred = ucred; - v->ucred_acquired = true; -diff --git a/src/shared/varlink.h b/src/shared/varlink.h -index 7ea1f9113f..66a1ff630e 100644 ---- a/src/shared/varlink.h -+++ b/src/shared/varlink.h -@@ -41,11 +41,12 @@ typedef enum VarlinkMethodFlags { - } VarlinkMethodFlags; - - typedef enum VarlinkServerFlags { -- VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */ -- VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */ -- VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */ -+ VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */ -+ VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */ -+ VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */ -+ VARLINK_SERVER_INHERIT_USERDATA = 1 << 3, /* Initialize Varlink connection userdata from VarlinkServer userdata */ - -- _VARLINK_SERVER_FLAGS_ALL = (1 << 3) - 1, -+ _VARLINK_SERVER_FLAGS_ALL = (1 << 4) - 1, - } VarlinkServerFlags; - - typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata); --- -2.23.0 - diff --git a/backport-xdg-autostart-Lower-most-info-messages-to-debug-leve.patch b/backport-xdg-autostart-Lower-most-info-messages-to-debug-leve.patch deleted file mode 100644 index 91e0c2f4..00000000 --- a/backport-xdg-autostart-Lower-most-info-messages-to-debug-leve.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 47c1db6730b8a81b01e8505a648624fa6ad0bbd7 Mon Sep 17 00:00:00 2001 -From: Benjamin Berg -Date: Mon, 12 Oct 2020 11:02:26 +0200 -Subject: [PATCH] xdg-autostart: Lower most info messages to debug level - -It is expected for numerous autostart files to not be convertible to -corresponding units. The information is only useful for someone -debugging why a file might not be started, but it is not generally -useful for users in most situations. - -As such, lower the warnings. Anyone wondering why an application is not -started will easily notice that the unit is not generated. From there it -will be somewhat harder to figure out why, but the overall trade-off is -still improved. - -Fixes: #17305 ---- - src/xdg-autostart-generator/xdg-autostart-service.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/xdg-autostart-generator/xdg-autostart-service.c b/src/xdg-autostart-generator/xdg-autostart-service.c -index c6f39f2..6324c50 100644 ---- a/src/xdg-autostart-generator/xdg-autostart-service.c -+++ b/src/xdg-autostart-generator/xdg-autostart-service.c -@@ -483,7 +483,7 @@ static int xdg_autostart_generate_desktop_condition( - - r = find_binary(test_binary, &gnome_autostart_condition_path); - if (r < 0) { -- log_full_errno(r == -ENOENT ? LOG_INFO : LOG_WARNING, r, -+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, - "%s not found: %m", test_binary); - fprintf(f, "# ExecCondition using %s skipped due to missing binary.\n", test_binary); - return r; -@@ -514,18 +514,18 @@ int xdg_autostart_service_generate_unit( - - /* Nothing to do for hidden services. */ - if (service->hidden) { -- log_info("Not generating service for XDG autostart %s, it is hidden.", service->name); -+ log_debug("Not generating service for XDG autostart %s, it is hidden.", service->name); - return 0; - } - - if (service->systemd_skip) { -- log_info("Not generating service for XDG autostart %s, should be skipped by generator.", service->name); -+ log_debug("Not generating service for XDG autostart %s, should be skipped by generator.", service->name); - return 0; - } - - /* Nothing to do if type is not Application. */ - if (!streq_ptr(service->type, "Application")) { -- log_info("Not generating service for XDG autostart %s, only Type=Application is supported.", service->name); -+ log_debug("Not generating service for XDG autostart %s, only Type=Application is supported.", service->name); - return 0; - } - -@@ -541,7 +541,7 @@ int xdg_autostart_service_generate_unit( - if (service->try_exec) { - r = find_binary(service->try_exec, NULL); - if (r < 0) { -- log_full_errno(r == -ENOENT ? LOG_INFO : LOG_WARNING, r, -+ log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, - "Not generating service for XDG autostart %s, could not find TryExec= binary %s: %m", - service->name, service->try_exec); - return 0; -@@ -558,7 +558,7 @@ int xdg_autostart_service_generate_unit( - - if (service->gnome_autostart_phase) { - /* There is no explicit value for the "Application" phase. */ -- log_info("Not generating service for XDG autostart %s, startup phases are not supported.", -+ log_debug("Not generating service for XDG autostart %s, startup phases are not supported.", - service->name); - return 0; - } --- -2.23.0 - diff --git a/revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch b/revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch deleted file mode 100644 index 65c5162e..00000000 --- a/revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch +++ /dev/null @@ -1,93 +0,0 @@ -From e67cd21d7d174cdafd12beca4cfb6e19e61f6fb5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Mon, 8 Jul 2019 17:33:25 +0200 -Subject: [PATCH] analyze: add "unit-files" to dump the unit fragment map - -I'm not convinced that this is useful enough to be included... But it is -certainly nice when debugging. - -revert analyze add unit files to dump the unit fragment map ---- - src/analyze/analyze.c | 50 -------------------------------------------------- - 1 file changed, 50 deletions(-) - -diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c -index 322be1a..6de26f4 100644 ---- a/src/analyze/analyze.c -+++ b/src/analyze/analyze.c -@@ -1546,53 +1546,6 @@ static int get_or_set_log_target(int argc, char *argv[], void *userdata) { - return (argc == 1) ? get_log_target(argc, argv, userdata) : set_log_target(argc, argv, userdata); - } - --static bool strv_fnmatch_strv_or_empty(char* const* patterns, char **strv, int flags) { -- char **s; -- STRV_FOREACH(s, strv) -- if (strv_fnmatch_or_empty(patterns, *s, flags)) -- return true; -- -- return false; --} -- --static int do_unit_files(int argc, char *argv[], void *userdata) { -- _cleanup_(lookup_paths_free) LookupPaths lp = {}; -- _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; -- _cleanup_hashmap_free_ Hashmap *unit_names = NULL; -- char **patterns = strv_skip(argv, 1); -- Iterator i; -- const char *k, *dst; -- char **v; -- int r; -- -- r = lookup_paths_init(&lp, arg_scope, 0, NULL); -- if (r < 0) -- return log_error_errno(r, "lookup_paths_init() failed: %m"); -- -- r = unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL); -- if (r < 0) -- return log_error_errno(r, "unit_file_build_name_map() failed: %m"); -- -- HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) { -- if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && -- !strv_fnmatch_or_empty(patterns, dst, FNM_NOESCAPE)) -- continue; -- -- printf("ids: %s → %s\n", k, dst); -- } -- -- HASHMAP_FOREACH_KEY(v, k, unit_names, i) { -- if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && -- !strv_fnmatch_strv_or_empty(patterns, v, FNM_NOESCAPE)) -- continue; -- -- _cleanup_free_ char *j = strv_join(v, ", "); -- printf("aliases: %s ← %s\n", k, j); -- } -- -- return 0; --} -- - static int dump_unit_paths(int argc, char *argv[], void *userdata) { - _cleanup_(lookup_paths_free) LookupPaths paths = {}; - int r; -@@ -2263,7 +2216,6 @@ static int help(int argc, char *argv[], void *userdata) { - " log-target [TARGET] Get/set logging target for manager\n" - " dump Output state serialization of service manager\n" - " cat-config Show configuration file and drop-ins\n" -- " unit-files List files and symlinks for units\n" - " unit-paths List load directories for units\n" - " exit-status [STATUS...] List exit status definitions\n" - " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n" -@@ -2467,10 +2419,8 @@ static int run(int argc, char *argv[]) { - { "get-log-level", VERB_ANY, 1, 0, get_log_level }, - { "set-log-target", 2, 2, 0, set_log_target }, - { "get-log-target", VERB_ANY, 1, 0, get_log_target }, -- - { "dump", VERB_ANY, 1, 0, dump }, - { "cat-config", 2, VERB_ANY, 0, cat_config }, -- { "unit-files", VERB_ANY, VERB_ANY, 0, do_unit_files }, - { "unit-paths", 1, 1, 0, dump_unit_paths }, - { "exit-status", VERB_ANY, VERB_ANY, 0, dump_exit_status }, - { "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters }, --- -1.8.3.1 - diff --git a/revert-pid1-drop-unit-caches-only-based-on-mtime.patch b/revert-pid1-drop-unit-caches-only-based-on-mtime.patch deleted file mode 100644 index e12236a7..00000000 --- a/revert-pid1-drop-unit-caches-only-based-on-mtime.patch +++ /dev/null @@ -1,289 +0,0 @@ -From 91e0ee5f16321656ed6f827742ecbeb2b36027f2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Wed, 10 Jul 2019 18:01:13 +0200 -Subject: [PATCH] pid1: drop unit caches only based on mtime - -v2: -- do not watch mtime of transient and generated dirs - - We'd reload the map after every transient unit we created, which we don't - need to do, since we create those units ourselves and know their fragment - path. - -revert pid1 drop unit caches only based on mtime ---- - src/analyze/analyze.c | 2 +- - src/core/load-fragment.c | 9 -------- - src/core/manager.c | 14 ++++++++++-- - src/core/manager.h | 1 - - src/shared/unit-file.c | 57 +---------------------------------------------- - src/shared/unit-file.h | 2 -- - src/systemctl/systemctl.c | 2 +- - src/test/test-unit-file.c | 13 +---------- - 8 files changed, 16 insertions(+), 84 deletions(-) - -diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c -index 4d81026..322be1a 100644 ---- a/src/analyze/analyze.c -+++ b/src/analyze/analyze.c -@@ -1569,7 +1569,7 @@ static int do_unit_files(int argc, char *argv[], void *userdata) { - if (r < 0) - return log_error_errno(r, "lookup_paths_init() failed: %m"); - -- r = unit_file_build_name_map(&lp, NULL, &unit_ids, &unit_names, NULL); -+ r = unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL); - if (r < 0) - return log_error_errno(r, "unit_file_build_name_map() failed: %m"); - -diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c -index 8eaf8b3..9821a92 100644 ---- a/src/core/load-fragment.c -+++ b/src/core/load-fragment.c -@@ -4605,15 +4605,6 @@ int unit_load_fragment(Unit *u) { - return 0; - } - -- /* Possibly rebuild the fragment map to catch new units */ -- r = unit_file_build_name_map(&u->manager->lookup_paths, -- &u->manager->unit_cache_mtime, -- &u->manager->unit_id_map, -- &u->manager->unit_name_map, -- &u->manager->unit_path_cache); -- if (r < 0) -- log_error_errno(r, "Failed to rebuild name map: %m"); -- - r = unit_file_find_fragment(u->manager->unit_id_map, - u->manager->unit_name_map, - u->id, -diff --git a/src/core/manager.c b/src/core/manager.c -index 5efcf45..8b1ce70 100644 ---- a/src/core/manager.c -+++ b/src/core/manager.c -@@ -693,7 +693,6 @@ static void manager_free_unit_name_maps(Manager *m) { - m->unit_id_map = hashmap_free(m->unit_id_map); - m->unit_name_map = hashmap_free(m->unit_name_map); - m->unit_path_cache = set_free_free(m->unit_path_cache); -- m->unit_cache_mtime = 0; - } - - static int manager_setup_run_queue(Manager *m) { -@@ -1642,6 +1641,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { - - lookup_paths_log(&m->lookup_paths); - -+ manager_free_unit_name_maps(m); -+ r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); -+ if (r < 0) -+ return log_error_errno(r, "Failed to build name map: %m"); -+ - { - /* This block is (optionally) done with the reloading counter bumped */ - _cleanup_(manager_reloading_stopp) Manager *reloading = NULL; -@@ -2858,6 +2862,10 @@ int manager_loop(Manager *m) { - assert(m); - assert(m->objective == MANAGER_OK); /* Ensure manager_startup() has been called */ - -+ /* Release the path and unit name caches */ -+ manager_free_unit_name_maps(m); -+ // FIXME: once this happens, we cannot load any more units -+ - manager_check_finished(m); - - /* There might still be some zombies hanging around from before we were exec()'ed. Let's reap them. */ -@@ -3531,8 +3539,10 @@ int manager_reload(Manager *m) { - - lookup_paths_log(&m->lookup_paths); - -- /* We flushed out generated files, for which we don't watch mtime, so we should flush the old map. */ - manager_free_unit_name_maps(m); -+ r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); -+ if (r < 0) -+ log_warning_errno(r, "Failed to build name map: %m"); - - /* First, enumerate what we can from kernel and suchlike */ - manager_enumerate_perpetual(m); -diff --git a/src/core/manager.h b/src/core/manager.h -index 815c5ec..9ca82ac 100644 ---- a/src/core/manager.h -+++ b/src/core/manager.h -@@ -223,7 +223,6 @@ struct Manager { - Hashmap *unit_id_map; - Hashmap *unit_name_map; - Set *unit_path_cache; -- usec_t unit_cache_mtime; - - char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */ - char **client_environment; /* Environment variables created by clients through the bus API */ -diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c -index 4a5f23e..bad92a3 100644 ---- a/src/shared/unit-file.c -+++ b/src/shared/unit-file.c -@@ -152,47 +152,8 @@ static int unit_ids_map_get( - return -ELOOP; - } - --static bool lookup_paths_mtime_exclude(const LookupPaths *lp, const char *path) { -- /* Paths that are under our exclusive control. Users shall not alter those directly. */ -- -- return streq_ptr(path, lp->generator) || -- streq_ptr(path, lp->generator_early) || -- streq_ptr(path, lp->generator_late) || -- streq_ptr(path, lp->transient) || -- streq_ptr(path, lp->persistent_control) || -- streq_ptr(path, lp->runtime_control); --} -- --static bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime) { -- char **dir; -- -- STRV_FOREACH(dir, (char**) lp->search_path) { -- struct stat st; -- -- if (lookup_paths_mtime_exclude(lp, *dir)) -- continue; -- -- /* Determine the latest lookup path modification time */ -- if (stat(*dir, &st) < 0) { -- if (errno == ENOENT) -- continue; -- -- log_debug_errno(errno, "Failed to stat %s, ignoring: %m", *dir); -- continue; -- } -- -- if (timespec_load(&st.st_mtim) > mtime) { -- log_debug_errno(errno, "Unit dir %s has changed, need to update cache.", *dir); -- return false; -- } -- } -- -- return true; --} -- - int unit_file_build_name_map( - const LookupPaths *lp, -- usec_t *cache_mtime, - Hashmap **ret_unit_ids_map, - Hashmap **ret_unit_names_map, - Set **ret_path_cache) { -@@ -210,12 +171,6 @@ int unit_file_build_name_map( - _cleanup_set_free_free_ Set *paths = NULL; - char **dir; - int r; -- usec_t mtime = 0; -- -- /* Before doing anything, check if the mtime that was passed is still valid. If -- * yes, do nothing. If *cache_time == 0, always build the cache. */ -- if (cache_mtime && *cache_mtime > 0 && lookup_paths_mtime_good(lp, *cache_mtime)) -- return 0; - - if (ret_path_cache) { - paths = set_new(&path_hash_ops); -@@ -226,7 +181,6 @@ int unit_file_build_name_map( - STRV_FOREACH(dir, (char**) lp->search_path) { - struct dirent *de; - _cleanup_closedir_ DIR *d = NULL; -- struct stat st; - - d = opendir(*dir); - if (!d) { -@@ -235,13 +189,6 @@ int unit_file_build_name_map( - continue; - } - -- /* Determine the latest lookup path modification time */ -- if (fstat(dirfd(d), &st) < 0) -- return log_error_errno(errno, "Failed to fstat %s: %m", *dir); -- -- if (!lookup_paths_mtime_exclude(lp, *dir)) -- mtime = MAX(mtime, timespec_load(&st.st_mtim)); -- - FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { - char *filename; - _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; -@@ -378,14 +325,12 @@ int unit_file_build_name_map( - basename(dst), src); - } - -- if (cache_mtime) -- *cache_mtime = mtime; - *ret_unit_ids_map = TAKE_PTR(ids); - *ret_unit_names_map = TAKE_PTR(names); - if (ret_path_cache) - *ret_path_cache = TAKE_PTR(paths); - -- return 1; -+ return 0; - } - - int unit_file_find_fragment( -diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h -index 54cc787..52e17f7 100644 ---- a/src/shared/unit-file.h -+++ b/src/shared/unit-file.h -@@ -4,7 +4,6 @@ - #include - - #include "hashmap.h" --#include "time-util.h" - #include "unit-name.h" - - typedef enum UnitFileState UnitFileState; -@@ -43,7 +42,6 @@ int unit_validate_alias_symlink_and_warn(const char *filename, const char *targe - - int unit_file_build_name_map( - const LookupPaths *lp, -- usec_t *ret_time, - Hashmap **ret_unit_ids_map, - Hashmap **ret_unit_names_map, - Set **ret_path_cache); -diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c -index dcf76be..69063ee 100644 ---- a/src/systemctl/systemctl.c -+++ b/src/systemctl/systemctl.c -@@ -2594,7 +2594,7 @@ static int unit_find_paths( - _cleanup_set_free_free_ Set *names = NULL; - - if (!cached_name_map) { -- r = unit_file_build_name_map(lp, NULL, &cached_id_map, &cached_name_map, NULL); -+ r = unit_file_build_name_map(lp, &cached_id_map, &cached_name_map, NULL); - if (r < 0) - return r; - } -diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c -index 8bc5bf6..988ac15 100644 ---- a/src/test/test-unit-file.c -+++ b/src/test/test-unit-file.c -@@ -32,12 +32,10 @@ static void test_unit_file_build_name_map(char **ids) { - Iterator i; - const char *k, *dst; - char **v; -- usec_t mtime = 0; -- int r; - - assert_se(lookup_paths_init(&lp, UNIT_FILE_SYSTEM, 0, NULL) >= 0); - -- assert_se(unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL) == 1); -+ assert_se(unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL) == 0); - - HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) - log_info("ids: %s → %s", k, dst); -@@ -47,15 +45,6 @@ static void test_unit_file_build_name_map(char **ids) { - log_info("aliases: %s ← %s", k, j); - } - -- char buf[FORMAT_TIMESTAMP_MAX]; -- log_debug("Last modification time: %s", format_timestamp(buf, sizeof buf, mtime)); -- -- r = unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL); -- assert_se(IN_SET(r, 0, 1)); -- if (r == 0) -- log_debug("Cache rebuild skipped based on mtime."); -- -- - char **id; - STRV_FOREACH(id, ids) { - const char *fragment, *name; --- -1.8.3.1 - diff --git a/revert-pid1-use-a-cache-for-all-unit-aliases.patch b/revert-pid1-use-a-cache-for-all-unit-aliases.patch deleted file mode 100644 index 7dc96a5a..00000000 --- a/revert-pid1-use-a-cache-for-all-unit-aliases.patch +++ /dev/null @@ -1,1226 +0,0 @@ -From e8630e695232bdfcd16b55f3faafb4329c961104 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Thu, 18 Jul 2019 13:11:28 +0200 -Subject: [PATCH] pid1: use a cache for all unit aliases - -This reworks how we load units from disk. Instead of chasing symlinks every -time we are asked to load a unit by name, we slurp all symlinks from disk -and build two hashmaps: -1. from unit name to either alias target, or fragment on disk - (if an alias, we put just the target name in the hashmap, if a fragment - we put an absolute path, so we can distinguish both). -2. from a unit name to all aliases - -Reading all this data can be pretty costly (40 ms) on my machine, so we keep it -around for reuse. - -The advantage is that we can reliably know what all the aliases of a given unit -are. This means we can reliably load dropins under all names. This fixes #11972. - -revert pid1 use a cache for all unit aliases ---- - src/core/load-fragment.c | 350 +++++++++++++++++++++++++++-------- - src/core/manager.c | 73 ++++++-- - src/core/manager.h | 2 - - src/core/unit.c | 3 - - src/shared/unit-file.c | 362 ------------------------------------- - src/shared/unit-file.h | 15 -- - src/systemctl/systemctl.c | 47 +++-- - src/test/test-unit-file.c | 40 ---- - test/TEST-15-DROPIN/test-dropin.sh | 33 ++-- - 9 files changed, 378 insertions(+), 547 deletions(-) - -diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c -index 9821a92..9dd86e8 100644 ---- a/src/core/load-fragment.c -+++ b/src/core/load-fragment.c -@@ -4553,48 +4553,251 @@ int config_parse_ip_filter_bpf_progs( - return 0; - } - -+#define FOLLOW_MAX 8 -+ -+static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { -+ char *id = NULL; -+ unsigned c = 0; -+ int fd, r; -+ FILE *f; -+ -+ assert(filename); -+ assert(*filename); -+ assert(_f); -+ assert(names); -+ -+ /* This will update the filename pointer if the loaded file is -+ * reached by a symlink. The old string will be freed. */ -+ -+ for (;;) { -+ char *target, *name; -+ -+ if (c++ >= FOLLOW_MAX) -+ return -ELOOP; -+ -+ path_simplify(*filename, false); -+ -+ /* Add the file name we are currently looking at to -+ * the names of this unit, but only if it is a valid -+ * unit name. */ -+ name = basename(*filename); -+ if (unit_name_is_valid(name, UNIT_NAME_ANY)) { -+ -+ id = set_get(names, name); -+ if (!id) { -+ id = strdup(name); -+ if (!id) -+ return -ENOMEM; -+ -+ r = set_consume(names, id); -+ if (r < 0) -+ return r; -+ } -+ } -+ -+ /* Try to open the file name, but don't if its a symlink */ -+ fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); -+ if (fd >= 0) -+ break; -+ -+ if (errno != ELOOP) -+ return -errno; -+ -+ /* Hmm, so this is a symlink. Let's read the name, and follow it manually */ -+ r = readlink_and_make_absolute(*filename, &target); -+ if (r < 0) -+ return r; -+ -+ free_and_replace(*filename, target); -+ } -+ -+ f = fdopen(fd, "r"); -+ if (!f) { -+ safe_close(fd); -+ return -errno; -+ } -+ -+ *_f = f; -+ *_final = id; -+ -+ return 0; -+} -+ - static int merge_by_names(Unit **u, Set *names, const char *id) { - char *k; - int r; - - assert(u); - assert(*u); -+ assert(names); - -- /* Let's try to add in all names that are aliases of this unit */ -+ /* Let's try to add in all symlink names we found */ - while ((k = set_steal_first(names))) { -- _cleanup_free_ _unused_ char *free_k = k; - -- /* First try to merge in the other name into our unit */ -+ /* First try to merge in the other name into our -+ * unit */ - r = unit_merge_by_name(*u, k); - if (r < 0) { - Unit *other; - -- /* Hmm, we couldn't merge the other unit into ours? Then let's try it the other way -- * round. */ -+ /* Hmm, we couldn't merge the other unit into -+ * ours? Then let's try it the other way -+ * round */ - -- other = manager_get_unit((*u)->manager, k); -- if (!other) -- return r; /* return previous failure */ -+ /* If the symlink name we are looking at is unit template, then -+ we must search for instance of this template */ -+ if (unit_name_is_valid(k, UNIT_NAME_TEMPLATE) && (*u)->instance) { -+ _cleanup_free_ char *instance = NULL; - -- r = unit_merge(other, *u); -- if (r < 0) -- return r; -+ r = unit_name_replace_instance(k, (*u)->instance, &instance); -+ if (r < 0) -+ return r; - -- *u = other; -- return merge_by_names(u, names, NULL); -+ other = manager_get_unit((*u)->manager, instance); -+ } else -+ other = manager_get_unit((*u)->manager, k); -+ -+ free(k); -+ -+ if (other) { -+ r = unit_merge(other, *u); -+ if (r >= 0) { -+ *u = other; -+ return merge_by_names(u, names, NULL); -+ } -+ } -+ -+ return r; - } - -- if (streq_ptr(id, k)) -+ if (id == k) - unit_choose_id(*u, id); -+ -+ free(k); -+ } -+ -+ return 0; -+} -+ -+static int load_from_path(Unit *u, const char *path) { -+ _cleanup_set_free_free_ Set *symlink_names = NULL; -+ _cleanup_fclose_ FILE *f = NULL; -+ _cleanup_free_ char *filename = NULL; -+ char *id = NULL; -+ Unit *merged; -+ struct stat st; -+ int r; -+ -+ assert(u); -+ assert(path); -+ -+ symlink_names = set_new(&string_hash_ops); -+ if (!symlink_names) -+ return -ENOMEM; -+ -+ if (path_is_absolute(path)) { -+ -+ filename = strdup(path); -+ if (!filename) -+ return -ENOMEM; -+ -+ r = open_follow(&filename, &f, symlink_names, &id); -+ if (r < 0) { -+ filename = mfree(filename); -+ if (r != -ENOENT) -+ return r; -+ } -+ -+ } else { -+ char **p; -+ -+ STRV_FOREACH(p, u->manager->lookup_paths.search_path) { -+ -+ /* Instead of opening the path right away, we manually -+ * follow all symlinks and add their name to our unit -+ * name set while doing so */ -+ filename = path_make_absolute(path, *p); -+ if (!filename) -+ return -ENOMEM; -+ -+ if (u->manager->unit_path_cache && -+ !set_get(u->manager->unit_path_cache, filename)) -+ r = -ENOENT; -+ else -+ r = open_follow(&filename, &f, symlink_names, &id); -+ if (r >= 0) -+ break; -+ -+ /* ENOENT means that the file is missing or is a dangling symlink. -+ * ENOTDIR means that one of paths we expect to be is a directory -+ * is not a directory, we should just ignore that. -+ * EACCES means that the directory or file permissions are wrong. -+ */ -+ if (r == -EACCES) -+ log_debug_errno(r, "Cannot access \"%s\": %m", filename); -+ else if (!IN_SET(r, -ENOENT, -ENOTDIR)) -+ return r; -+ -+ filename = mfree(filename); -+ /* Empty the symlink names for the next run */ -+ set_clear_free(symlink_names); -+ } -+ } -+ -+ if (!filename) -+ /* Hmm, no suitable file found? */ -+ return 0; -+ -+ if (!unit_type_may_alias(u->type) && set_size(symlink_names) > 1) { -+ log_unit_warning(u, "Unit type of %s does not support alias names, refusing loading via symlink.", u->id); -+ return -ELOOP; -+ } -+ -+ merged = u; -+ r = merge_by_names(&merged, symlink_names, id); -+ if (r < 0) -+ return r; -+ -+ if (merged != u) { -+ u->load_state = UNIT_MERGED; -+ return 0; -+ } -+ -+ if (fstat(fileno(f), &st) < 0) -+ return -errno; -+ -+ if (null_or_empty(&st)) { -+ u->load_state = UNIT_MASKED; -+ u->fragment_mtime = 0; -+ } else { -+ u->load_state = UNIT_LOADED; -+ u->fragment_mtime = timespec_load(&st.st_mtim); -+ -+ /* Now, parse the file contents */ -+ r = config_parse(u->id, filename, f, -+ UNIT_VTABLE(u)->sections, -+ config_item_perf_lookup, load_fragment_gperf_lookup, -+ CONFIG_PARSE_ALLOW_INCLUDE, u); -+ if (r < 0) -+ return r; -+ } -+ -+ free_and_replace(u->fragment_path, filename); -+ -+ if (u->source_path) { -+ if (stat(u->source_path, &st) >= 0) -+ u->source_mtime = timespec_load(&st.st_mtim); -+ else -+ u->source_mtime = 0; - } - - return 0; - } - - int unit_load_fragment(Unit *u) { -- const char *fragment; -- _cleanup_set_free_free_ Set *names = NULL; - int r; -+ Iterator i; -+ const char *t; - - assert(u); - assert(u->load_state == UNIT_STUB); -@@ -4605,79 +4808,78 @@ int unit_load_fragment(Unit *u) { - return 0; - } - -- r = unit_file_find_fragment(u->manager->unit_id_map, -- u->manager->unit_name_map, -- u->id, -- &fragment, -- &names); -- if (r < 0 && r != -ENOENT) -+ /* First, try to find the unit under its id. We always look -+ * for unit files in the default directories, to make it easy -+ * to override things by placing things in /etc/systemd/system */ -+ r = load_from_path(u, u->id); -+ if (r < 0) - return r; - -- if (fragment) { -- /* Open the file, check if this is a mask, otherwise read. */ -- _cleanup_fclose_ FILE *f = NULL; -- struct stat st; -+ /* Try to find an alias we can load this with */ -+ if (u->load_state == UNIT_STUB) { -+ SET_FOREACH(t, u->names, i) { - -- /* Try to open the file name. A symlink is OK, for example for linked files or masks. We -- * expect that all symlinks within the lookup paths have been already resolved, but we don't -- * verify this here. */ -- f = fopen(fragment, "re"); -- if (!f) -- return log_unit_notice_errno(u, errno, "Failed to open %s: %m", fragment); -+ if (t == u->id) -+ continue; - -- if (fstat(fileno(f), &st) < 0) -- return -errno; -+ r = load_from_path(u, t); -+ if (r < 0) -+ return r; - -- r = free_and_strdup(&u->fragment_path, fragment); -+ if (u->load_state != UNIT_STUB) -+ break; -+ } -+ } -+ -+ /* And now, try looking for it under the suggested (originally linked) path */ -+ if (u->load_state == UNIT_STUB && u->fragment_path) { -+ -+ r = load_from_path(u, u->fragment_path); - if (r < 0) - return r; - -- if (null_or_empty(&st)) { -- u->load_state = UNIT_MASKED; -- u->fragment_mtime = 0; -- } else { -- u->load_state = UNIT_LOADED; -- u->fragment_mtime = timespec_load(&st.st_mtim); -- -- /* Now, parse the file contents */ -- r = config_parse(u->id, fragment, f, -- UNIT_VTABLE(u)->sections, -- config_item_perf_lookup, load_fragment_gperf_lookup, -- CONFIG_PARSE_ALLOW_INCLUDE, u); -- if (r == -ENOEXEC) -- log_unit_notice_errno(u, r, "Unit configuration has fatal error, unit will not be started."); -- if (r < 0) -- return r; -- } -+ if (u->load_state == UNIT_STUB) -+ /* Hmm, this didn't work? Then let's get rid -+ * of the fragment path stored for us, so that -+ * we don't point to an invalid location. */ -+ u->fragment_path = mfree(u->fragment_path); - } - -- /* We do the merge dance here because for some unit types, the unit might have aliases which are not -- * declared in the file system. In particular, this is true (and frequent) for device and swap units. -- */ -- Unit *merged; -- const char *id = u->id; -- _cleanup_free_ char *free_id = NULL; -+ /* Look for a template */ -+ if (u->load_state == UNIT_STUB && u->instance) { -+ _cleanup_free_ char *k = NULL; - -- if (fragment) { -- id = basename(fragment); -- if (unit_name_is_valid(id, UNIT_NAME_TEMPLATE)) { -- assert(u->instance); /* If we're not trying to use a template for non-instanced unit, -- * this must be set. */ -+ r = unit_name_template(u->id, &k); -+ if (r < 0) -+ return r; - -- r = unit_name_replace_instance(id, u->instance, &free_id); -- if (r < 0) -- return log_debug_errno(r, "Failed to build id (%s + %s): %m", id, u->instance); -- id = free_id; -+ r = load_from_path(u, k); -+ if (r < 0) { -+ if (r == -ENOEXEC) -+ log_unit_notice(u, "Unit configuration has fatal error, unit will not be started."); -+ return r; - } -- } - -- merged = u; -- r = merge_by_names(&merged, names, id); -- if (r < 0) -- return r; -+ if (u->load_state == UNIT_STUB) { -+ SET_FOREACH(t, u->names, i) { -+ _cleanup_free_ char *z = NULL; - -- if (merged != u) -- u->load_state = UNIT_MERGED; -+ if (t == u->id) -+ continue; -+ -+ r = unit_name_template(t, &z); -+ if (r < 0) -+ return r; -+ -+ r = load_from_path(u, z); -+ if (r < 0) -+ return r; -+ -+ if (u->load_state != UNIT_STUB) -+ break; -+ } -+ } -+ } - - return 0; - } -diff --git a/src/core/manager.c b/src/core/manager.c -index 8b1ce70..cfeaca6 100644 ---- a/src/core/manager.c -+++ b/src/core/manager.c -@@ -689,12 +689,6 @@ static int manager_setup_prefix(Manager *m) { - return 0; - } - --static void manager_free_unit_name_maps(Manager *m) { -- m->unit_id_map = hashmap_free(m->unit_id_map); -- m->unit_name_map = hashmap_free(m->unit_name_map); -- m->unit_path_cache = set_free_free(m->unit_path_cache); --} -- - static int manager_setup_run_queue(Manager *m) { - int r; - -@@ -1383,7 +1377,7 @@ Manager* manager_free(Manager *m) { - strv_free(m->client_environment); - - hashmap_free(m->cgroup_unit); -- manager_free_unit_name_maps(m); -+ set_free_free(m->unit_path_cache); - - free(m->switch_root); - free(m->switch_root_init); -@@ -1487,6 +1481,56 @@ static void manager_catchup(Manager *m) { - } - } - -+static void manager_build_unit_path_cache(Manager *m) { -+ char **i; -+ int r; -+ -+ assert(m); -+ -+ set_free_free(m->unit_path_cache); -+ -+ m->unit_path_cache = set_new(&path_hash_ops); -+ if (!m->unit_path_cache) { -+ r = -ENOMEM; -+ goto fail; -+ } -+ -+ /* This simply builds a list of files we know exist, so that -+ * we don't always have to go to disk */ -+ -+ STRV_FOREACH(i, m->lookup_paths.search_path) { -+ _cleanup_closedir_ DIR *d = NULL; -+ struct dirent *de; -+ -+ d = opendir(*i); -+ if (!d) { -+ if (errno != ENOENT) -+ log_warning_errno(errno, "Failed to open directory %s, ignoring: %m", *i); -+ continue; -+ } -+ -+ FOREACH_DIRENT(de, d, r = -errno; goto fail) { -+ char *p; -+ -+ p = path_join(*i, de->d_name); -+ if (!p) { -+ r = -ENOMEM; -+ goto fail; -+ } -+ -+ r = set_consume(m->unit_path_cache, p); -+ if (r < 0) -+ goto fail; -+ } -+ } -+ -+ return; -+ -+fail: -+ log_warning_errno(r, "Failed to build unit path cache, proceeding without: %m"); -+ m->unit_path_cache = set_free_free(m->unit_path_cache); -+} -+ - static void manager_distribute_fds(Manager *m, FDSet *fds) { - Iterator i; - Unit *u; -@@ -1641,10 +1685,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { - - lookup_paths_log(&m->lookup_paths); - -- manager_free_unit_name_maps(m); -- r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); -- if (r < 0) -- return log_error_errno(r, "Failed to build name map: %m"); -+ manager_build_unit_path_cache(m); - - { - /* This block is (optionally) done with the reloading counter bumped */ -@@ -2862,9 +2903,8 @@ int manager_loop(Manager *m) { - assert(m); - assert(m->objective == MANAGER_OK); /* Ensure manager_startup() has been called */ - -- /* Release the path and unit name caches */ -- manager_free_unit_name_maps(m); -- // FIXME: once this happens, we cannot load any more units -+ /* Release the path cache */ -+ m->unit_path_cache = set_free_free(m->unit_path_cache); - - manager_check_finished(m); - -@@ -3539,10 +3579,7 @@ int manager_reload(Manager *m) { - - lookup_paths_log(&m->lookup_paths); - -- manager_free_unit_name_maps(m); -- r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); -- if (r < 0) -- log_warning_errno(r, "Failed to build name map: %m"); -+ manager_build_unit_path_cache(m); - - /* First, enumerate what we can from kernel and suchlike */ - manager_enumerate_perpetual(m); -diff --git a/src/core/manager.h b/src/core/manager.h -index 9ca82ac..daeb454 100644 ---- a/src/core/manager.h -+++ b/src/core/manager.h -@@ -220,8 +220,6 @@ struct Manager { - - UnitFileScope unit_file_scope; - LookupPaths lookup_paths; -- Hashmap *unit_id_map; -- Hashmap *unit_name_map; - Set *unit_path_cache; - - char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */ -diff --git a/src/core/unit.c b/src/core/unit.c -index f96e6e4..1b8d5d9 100644 ---- a/src/core/unit.c -+++ b/src/core/unit.c -@@ -959,9 +959,6 @@ int unit_merge_by_name(Unit *u, const char *name) { - Unit *other; - int r; - -- /* Either add name to u, or if a unit with name already exists, merge it with u. -- * If name is a template, do the same for name@instance, where instance is u's instance. */ -- - assert(u); - assert(name); - -diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c -index bad92a3..cde38c4 100644 ---- a/src/shared/unit-file.c -+++ b/src/shared/unit-file.c -@@ -1,14 +1,7 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - --#include "dirent-util.h" --#include "fd-util.h" --#include "fs-util.h" - #include "macro.h" --#include "path-lookup.h" --#include "set.h" --#include "stat-util.h" - #include "string-util.h" --#include "strv.h" - #include "unit-file.h" - - bool unit_type_may_alias(UnitType type) { -@@ -101,358 +94,3 @@ int unit_validate_alias_symlink_and_warn(const char *filename, const char *targe - - return 0; - } -- --#define FOLLOW_MAX 8 -- --static int unit_ids_map_get( -- Hashmap *unit_ids_map, -- const char *unit_name, -- const char **ret_fragment_path) { -- -- /* Resolve recursively until we hit an absolute path, i.e. a non-aliased unit. -- * -- * We distinguish the case where unit_name was not found in the hashmap at all, and the case where -- * some symlink was broken. -- * -- * If a symlink target points to an instance name, then we also check for the template. */ -- -- const char *id = NULL; -- int r; -- -- for (unsigned n = 0; n < FOLLOW_MAX; n++) { -- const char *t = hashmap_get(unit_ids_map, id ?: unit_name); -- if (!t) { -- _cleanup_free_ char *template = NULL; -- -- if (!id) -- return -ENOENT; -- -- r = unit_name_template(id, &template); -- if (r == -EINVAL) -- return -ENXIO; /* we failed to find the symlink target */ -- if (r < 0) -- return log_error_errno(r, "Failed to determine template name for %s: %m", id); -- -- t = hashmap_get(unit_ids_map, template); -- if (!t) -- return -ENXIO; -- -- /* We successfully switched from instanced name to a template, let's continue */ -- } -- -- if (path_is_absolute(t)) { -- if (ret_fragment_path) -- *ret_fragment_path = t; -- return 0; -- } -- -- id = t; -- } -- -- return -ELOOP; --} -- --int unit_file_build_name_map( -- const LookupPaths *lp, -- Hashmap **ret_unit_ids_map, -- Hashmap **ret_unit_names_map, -- Set **ret_path_cache) { -- -- /* Build two mappings: any name → main unit (i.e. the end result of symlink resolution), unit name → -- * all aliases (i.e. the entry for a given key is a a list of all names which point to this key). The -- * key is included in the value iff we saw a file or symlink with that name. In other words, if we -- * have a key, but it is not present in the value for itself, there was an alias pointing to it, but -- * the unit itself is not loadable. -- * -- * At the same, build a cache of paths where to find units. -- */ -- -- _cleanup_hashmap_free_ Hashmap *ids = NULL, *names = NULL; -- _cleanup_set_free_free_ Set *paths = NULL; -- char **dir; -- int r; -- -- if (ret_path_cache) { -- paths = set_new(&path_hash_ops); -- if (!paths) -- return log_oom(); -- } -- -- STRV_FOREACH(dir, (char**) lp->search_path) { -- struct dirent *de; -- _cleanup_closedir_ DIR *d = NULL; -- -- d = opendir(*dir); -- if (!d) { -- if (errno != ENOENT) -- log_warning_errno(errno, "Failed to open \"%s\", ignoring: %m", *dir); -- continue; -- } -- -- FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { -- char *filename; -- _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; -- const char *suffix, *dst = NULL; -- bool valid_unit_name; -- -- valid_unit_name = unit_name_is_valid(de->d_name, UNIT_NAME_ANY); -- -- /* We only care about valid units and dirs with certain suffixes, let's ignore the -- * rest. */ -- if (!valid_unit_name && -- !ENDSWITH_SET(de->d_name, ".wants", ".requires", ".d")) -- continue; -- -- filename = path_join(*dir, de->d_name); -- if (!filename) -- return log_oom(); -- -- if (ret_path_cache) { -- r = set_consume(paths, filename); -- if (r < 0) -- return log_oom(); -- /* We will still use filename below. This is safe because we know the set -- * holds a reference. */ -- } else -- _filename_free = filename; /* Make sure we free the filename. */ -- -- if (!valid_unit_name) -- continue; -- assert_se(suffix = strrchr(de->d_name, '.')); -- -- /* search_path is ordered by priority (highest first). If the name is already mapped -- * to something (incl. itself), it means that we have already seen it, and we should -- * ignore it here. */ -- if (hashmap_contains(ids, de->d_name)) -- continue; -- -- if (de->d_type == DT_LNK) { -- /* We don't explicitly check for alias loops here. unit_ids_map_get() which -- * limits the number of hops should be used to access the map. */ -- -- _cleanup_free_ char *target = NULL, *target_abs = NULL; -- -- r = readlinkat_malloc(dirfd(d), de->d_name, &target); -- if (r < 0) { -- log_warning_errno(r, "Failed to read symlink %s/%s, ignoring: %m", -- *dir, de->d_name); -- continue; -- } -- -- if (!path_is_absolute(target)) { -- target_abs = path_join(*dir, target); -- if (!target_abs) -- return log_oom(); -- -- free_and_replace(target, target_abs); -- } -- -- /* Get rid of "." and ".." components in target path */ -- r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified); -- if (r < 0) { -- log_warning_errno(r, "Failed to resolve symlink %s pointing to %s, ignoring: %m", -- filename, target); -- continue; -- } -- -- /* Check if the symlink goes outside of our search path. -- * If yes, it's a linked unit file or mask, and we don't care about the target name. -- * Let's just store the link destination directly. -- * If not, let's verify that it's a good symlink. */ -- char *tail = path_startswith_strv(simplified, lp->search_path); -- if (tail) { -- bool self_alias; -- -- dst = basename(simplified); -- self_alias = streq(dst, de->d_name); -- -- if (is_path(tail)) -- log_full(self_alias ? LOG_DEBUG : LOG_WARNING, -- "Suspicious symlink %s→%s, treating as alias.", -- filename, simplified); -- -- r = unit_validate_alias_symlink_and_warn(filename, simplified); -- if (r < 0) -- continue; -- -- if (self_alias) { -- /* A self-alias that has no effect */ -- log_debug("%s: self-alias: %s/%s → %s, ignoring.", -- __func__, *dir, de->d_name, dst); -- continue; -- } -- -- log_debug("%s: alias: %s/%s → %s", __func__, *dir, de->d_name, dst); -- } else { -- dst = simplified; -- -- log_debug("%s: linked unit file: %s/%s → %s", __func__, *dir, de->d_name, dst); -- } -- -- } else { -- dst = filename; -- log_debug("%s: normal unit file: %s", __func__, dst); -- } -- -- r = hashmap_put_strdup(&ids, de->d_name, dst); -- if (r < 0) -- return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", -- de->d_name, dst); -- } -- } -- -- /* Let's also put the names in the reverse db. */ -- Iterator it; -- const char *dummy, *src; -- HASHMAP_FOREACH_KEY(dummy, src, ids, it) { -- const char *dst; -- -- r = unit_ids_map_get(ids, src, &dst); -- if (r < 0) -- continue; -- -- if (null_or_empty_path(dst) != 0) -- continue; -- -- /* Do not treat instance symlinks that point to the template as aliases */ -- if (unit_name_is_valid(basename(dst), UNIT_NAME_TEMPLATE) && -- unit_name_is_valid(src, UNIT_NAME_INSTANCE)) -- continue; -- -- r = string_strv_hashmap_put(&names, basename(dst), src); -- if (r < 0) -- return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", -- basename(dst), src); -- } -- -- *ret_unit_ids_map = TAKE_PTR(ids); -- *ret_unit_names_map = TAKE_PTR(names); -- if (ret_path_cache) -- *ret_path_cache = TAKE_PTR(paths); -- -- return 0; --} -- --int unit_file_find_fragment( -- Hashmap *unit_ids_map, -- Hashmap *unit_name_map, -- const char *unit_name, -- const char **ret_fragment_path, -- Set **ret_names) { -- -- const char *fragment = NULL; -- _cleanup_free_ char *template = NULL, *instance = NULL; -- _cleanup_set_free_free_ Set *names = NULL; -- char **t, **nnn; -- int r, name_type; -- -- /* Finds a fragment path, and returns the set of names: -- * if we have …/foo.service and …/foo-alias.service→foo.service, -- * and …/foo@.service and …/foo-alias@.service→foo@.service, -- * and …/foo@inst.service, -- * this should return: -- * foo.service → …/foo.service, {foo.service, foo-alias.service}, -- * foo-alias.service → …/foo.service, {foo.service, foo-alias.service}, -- * foo@.service → …/foo@.service, {foo@.service, foo-alias@.service}, -- * foo-alias@.service → …/foo@.service, {foo@.service, foo-alias@.service}, -- * foo@bar.service → …/foo@.service, {foo@bar.service, foo-alias@bar.service}, -- * foo-alias@bar.service → …/foo@.service, {foo@bar.service, foo-alias@bar.service}, -- * foo-alias@inst.service → …/foo@inst.service, {foo@inst.service, foo-alias@inst.service}. -- */ -- -- name_type = unit_name_to_instance(unit_name, &instance); -- if (name_type < 0) -- return name_type; -- -- names = set_new(&string_hash_ops); -- if (!names) -- return -ENOMEM; -- -- /* The unit always has its own name if it's not a template. */ -- if (IN_SET(name_type, UNIT_NAME_PLAIN, UNIT_NAME_INSTANCE)) { -- r = set_put_strdup(names, unit_name); -- if (r < 0) -- return r; -- } -- -- /* First try to load fragment under the original name */ -- r = unit_ids_map_get(unit_ids_map, unit_name, &fragment); -- if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) -- return log_debug_errno(r, "Cannot load unit %s: %m", unit_name); -- -- if (fragment) { -- /* Add any aliases of the original name to the set of names */ -- nnn = hashmap_get(unit_name_map, basename(fragment)); -- STRV_FOREACH(t, nnn) { -- if (name_type == UNIT_NAME_INSTANCE && unit_name_is_valid(*t, UNIT_NAME_TEMPLATE)) { -- char *inst; -- -- r = unit_name_replace_instance(*t, instance, &inst); -- if (r < 0) -- return log_debug_errno(r, "Cannot build instance name %s+%s: %m", *t, instance); -- -- if (!streq(unit_name, inst)) -- log_debug("%s: %s has alias %s", __func__, unit_name, inst); -- -- log_info("%s: %s+%s → %s", __func__, *t, instance, inst); -- r = set_consume(names, inst); -- } else { -- if (!streq(unit_name, *t)) -- log_debug("%s: %s has alias %s", __func__, unit_name, *t); -- -- r = set_put_strdup(names, *t); -- } -- if (r < 0) -- return r; -- } -- } -- -- if (!fragment && name_type == UNIT_NAME_INSTANCE) { -- /* Look for a fragment under the template name */ -- -- r = unit_name_template(unit_name, &template); -- if (r < 0) -- return log_error_errno(r, "Failed to determine template name: %m"); -- -- r = unit_ids_map_get(unit_ids_map, template, &fragment); -- if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) -- return log_debug_errno(r, "Cannot load template %s: %m", template); -- -- if (fragment) { -- /* Add any aliases of the original name to the set of names */ -- nnn = hashmap_get(unit_name_map, basename(fragment)); -- STRV_FOREACH(t, nnn) { -- _cleanup_free_ char *inst = NULL; -- const char *inst_fragment = NULL; -- -- r = unit_name_replace_instance(*t, instance, &inst); -- if (r < 0) -- return log_debug_errno(r, "Cannot build instance name %s+%s: %m", template, instance); -- -- /* Exclude any aliases that point in some other direction. */ -- r = unit_ids_map_get(unit_ids_map, inst, &inst_fragment); -- if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) -- return log_debug_errno(r, "Cannot find instance fragment %s: %m", inst); -- -- if (inst_fragment && -- !streq(basename(inst_fragment), basename(fragment))) { -- log_debug("Instance %s has fragment %s and is not an alias of %s.", -- inst, inst_fragment, unit_name); -- continue; -- } -- -- if (!streq(unit_name, inst)) -- log_debug("%s: %s has alias %s", __func__, unit_name, inst); -- r = set_consume(names, TAKE_PTR(inst)); -- if (r < 0) -- return r; -- } -- } -- } -- -- *ret_fragment_path = fragment; -- *ret_names = TAKE_PTR(names); -- -- // FIXME: if instance, consider any unit names with different template name -- return 0; --} -diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h -index 52e17f7..e57f472 100644 ---- a/src/shared/unit-file.h -+++ b/src/shared/unit-file.h -@@ -3,12 +3,10 @@ - - #include - --#include "hashmap.h" - #include "unit-name.h" - - typedef enum UnitFileState UnitFileState; - typedef enum UnitFileScope UnitFileScope; --typedef struct LookupPaths LookupPaths; - - enum UnitFileState { - UNIT_FILE_ENABLED, -@@ -39,16 +37,3 @@ bool unit_type_may_alias(UnitType type) _const_; - bool unit_type_may_template(UnitType type) _const_; - - int unit_validate_alias_symlink_and_warn(const char *filename, const char *target); -- --int unit_file_build_name_map( -- const LookupPaths *lp, -- Hashmap **ret_unit_ids_map, -- Hashmap **ret_unit_names_map, -- Set **ret_path_cache); -- --int unit_file_find_fragment( -- Hashmap *unit_ids_map, -- Hashmap *unit_name_map, -- const char *unit_name, -- const char **ret_fragment_path, -- Set **names); -diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c -index 69063ee..48e0bad 100644 ---- a/src/systemctl/systemctl.c -+++ b/src/systemctl/systemctl.c -@@ -33,7 +33,6 @@ - #include "cgroup-util.h" - #include "copy.h" - #include "cpu-set-util.h" --#include "dirent-util.h" - #include "dropin.h" - #include "efivars.h" - #include "env-util.h" -@@ -167,18 +166,12 @@ static bool arg_jobs_before = false; - static bool arg_jobs_after = false; - static char **arg_clean_what = NULL; - --/* This is a global cache that will be constructed on first use. */ --static Hashmap *cached_id_map = NULL; --static Hashmap *cached_name_map = NULL; -- - STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep); - STATIC_DESTRUCTOR_REGISTER(arg_root, freep); - STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep); - STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep); - STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); - STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep); --STATIC_DESTRUCTOR_REGISTER(cached_id_map, hashmap_freep); --STATIC_DESTRUCTOR_REGISTER(cached_name_map, hashmap_freep); - - static int daemon_reload(int argc, char *argv[], void* userdata); - static int trivial_method(int argc, char *argv[], void *userdata); -@@ -2590,24 +2583,38 @@ static int unit_find_paths( - return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r)); - } - } else { -- const char *_path; -- _cleanup_set_free_free_ Set *names = NULL; -+ _cleanup_set_free_ Set *names = NULL; -+ _cleanup_free_ char *template = NULL; - -- if (!cached_name_map) { -- r = unit_file_build_name_map(lp, &cached_id_map, &cached_name_map, NULL); -- if (r < 0) -- return r; -- } -+ names = set_new(NULL); -+ if (!names) -+ return log_oom(); - -- r = unit_file_find_fragment(cached_id_map, cached_name_map, unit_name, &_path, &names); -+ r = unit_find_template_path(unit_name, lp, &path, &template); - if (r < 0) - return r; -+ if (r > 0) { -+ if (null_or_empty_path(path)) -+ /* The template is masked. Let's cut the process short. */ -+ return -ERFKILL; -+ -+ /* We found the unit file. If we followed symlinks, this name might be -+ * different then the unit_name with started with. Look for dropins matching -+ * that "final" name. */ -+ r = set_put(names, basename(path)); -+ } else if (!template) -+ /* No unit file, let's look for dropins matching the original name. -+ * systemd has fairly complicated rules (based on unit type and provenience), -+ * which units are allowed not to have the main unit file. We err on the -+ * side of including too many files, and always try to load dropins. */ -+ r = set_put(names, unit_name); -+ else -+ /* The cases where we allow a unit to exist without the main file are -+ * never valid for templates. Don't try to load dropins in this case. */ -+ goto not_found; - -- if (_path) { -- path = strdup(_path); -- if (!path) -- return log_oom(); -- } -+ if (r < 0) -+ return log_error_errno(r, "Failed to add unit name: %m"); - - if (ret_dropin_paths) { - r = unit_file_find_dropin_paths(arg_root, lp->search_path, NULL, -diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c -index 988ac15..b626b5f 100644 ---- a/src/test/test-unit-file.c -+++ b/src/test/test-unit-file.c -@@ -25,50 +25,10 @@ static void test_unit_validate_alias_symlink_and_warn(void) { - assert_se(unit_validate_alias_symlink_and_warn("/path/a.slice", "/other/b.slice") == -EINVAL); - } - --static void test_unit_file_build_name_map(char **ids) { -- _cleanup_(lookup_paths_free) LookupPaths lp = {}; -- _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; -- _cleanup_hashmap_free_ Hashmap *unit_names = NULL; -- Iterator i; -- const char *k, *dst; -- char **v; -- -- assert_se(lookup_paths_init(&lp, UNIT_FILE_SYSTEM, 0, NULL) >= 0); -- -- assert_se(unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL) == 0); -- -- HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) -- log_info("ids: %s → %s", k, dst); -- -- HASHMAP_FOREACH_KEY(v, k, unit_names, i) { -- _cleanup_free_ char *j = strv_join(v, ", "); -- log_info("aliases: %s ← %s", k, j); -- } -- -- char **id; -- STRV_FOREACH(id, ids) { -- const char *fragment, *name; -- Iterator it; -- _cleanup_set_free_free_ Set *names = NULL; -- log_info("*** %s ***", *id); -- r = unit_file_find_fragment(unit_ids, -- unit_names, -- *id, -- &fragment, -- &names); -- assert(r == 0); -- log_info("fragment: %s", fragment); -- log_info("names:"); -- SET_FOREACH(name, names, it) -- log_info(" %s", name); -- } --} -- - int main(int argc, char **argv) { - test_setup_logging(LOG_DEBUG); - - test_unit_validate_alias_symlink_and_warn(); -- test_unit_file_build_name_map(strv_skip(argv, 1)); - - return 0; - } -diff --git a/test/TEST-15-DROPIN/test-dropin.sh b/test/TEST-15-DROPIN/test-dropin.sh -index 2cef5a3..f785680 100755 ---- a/test/TEST-15-DROPIN/test-dropin.sh -+++ b/test/TEST-15-DROPIN/test-dropin.sh -@@ -158,14 +158,14 @@ EOF - systemctl show -p Names,Requires bar@0 - systemctl show -p Names,Requires bar-alias@0 - check_ok bar@0 Names bar@0 -- check_ok bar@0 Names bar-alias@0 -+ check_ko bar@0 Names bar-alias@0 - - check_ok bar@0 After bar-template-after.device - - check_ok bar@0 Requires bar-0-requires.device -- check_ok bar@0 Requires bar-alias-0-requires.device -+ check_ko bar@0 Requires bar-alias-0-requires.device - check_ok bar@0 Requires bar-template-requires.device -- check_ok bar@0 Requires bar-alias-template-requires.device -+ check_ko bar@0 Requires bar-alias-template-requires.device - check_ko bar@0 Requires yup-template-requires.device - - check_ok bar-alias@0 After bar-template-after.device -@@ -181,15 +181,15 @@ EOF - systemctl show -p Names,Requires bar@1 - systemctl show -p Names,Requires bar-alias@1 - check_ok bar@1 Names bar@1 -- check_ok bar@1 Names bar-alias@1 -+ check_ko bar@1 Names bar-alias@1 - - check_ok bar@1 After bar-template-after.device - - check_ok bar@1 Requires bar-1-requires.device -- check_ok bar@1 Requires bar-alias-1-requires.device -+ check_ko bar@1 Requires bar-alias-1-requires.device - check_ok bar@1 Requires bar-template-requires.device - # See https://github.com/systemd/systemd/pull/13119#discussion_r308145418 -- check_ok bar@1 Requires bar-alias-template-requires.device -+ check_ko bar@1 Requires bar-alias-template-requires.device - check_ko bar@1 Requires yup-template-requires.device - check_ko bar@1 Requires yup-1-requires.device - -@@ -241,14 +241,14 @@ EOF - check_ko bar@3 Requires yup-template-requires.device - check_ko bar@3 Requires yup-3-requires.device - -- check_ko bar-alias@3 After bar-template-after.device -+ check_ok bar-alias@3 After bar-template-after.device - -- check_ko bar-alias@3 Requires bar-3-requires.device -+ check_ok bar-alias@3 Requires bar-3-requires.device - check_ok bar-alias@3 Requires bar-alias-3-requires.device -- check_ko bar-alias@3 Requires bar-template-requires.device -+ check_ok bar-alias@3 Requires bar-template-requires.device - check_ok bar-alias@3 Requires bar-alias-template-requires.device -- check_ok bar-alias@3 Requires yup-template-requires.device -- check_ok bar-alias@3 Requires yup-3-requires.device -+ check_ko bar-alias@3 Requires yup-template-requires.device -+ check_ko bar-alias@3 Requires yup-3-requires.device - - clear_services foo {bar,yup,bar-alias}@{,1,2,3} - } -@@ -267,7 +267,14 @@ test_alias_dropins () { - rm /etc/systemd/system/b1.service - clear_services a b - -- # Check that dependencies don't vary. -+ # A weird behavior: the dependencies for 'a' may vary. It can be -+ # changed by loading an alias... -+ # -+ # [1] 'a1' is loaded and then "renamed" into 'a'. 'a1' is therefore -+ # part of the names set so all its specific dropins are loaded. -+ # -+ # [2] 'a' is already loaded. 'a1' is simply only merged into 'a' so -+ # none of its dropins are loaded ('y' is missing from the deps). - echo "*** test 2" - create_services a x y - mkdir -p /etc/systemd/system/a1.service.wants/ -@@ -278,7 +285,7 @@ test_alias_dropins () { - check_ok a1 Wants y.service - systemctl start a - check_ok a1 Wants x.service # see [2] -- check_ok a1 Wants y.service -+ check_ko a1 Wants y.service - systemctl stop a x y - rm /etc/systemd/system/a1.service - --- -1.8.3.1 - diff --git a/revert-shared-unit-file-add-a-function-to-validate-u.patch b/revert-shared-unit-file-add-a-function-to-validate-u.patch deleted file mode 100644 index 89667563..00000000 --- a/revert-shared-unit-file-add-a-function-to-validate-u.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 7d1e91d1a9504ab1bc03894038f90a8e87a4e982 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Tue, 2 Apr 2019 11:22:56 +0200 -Subject: [PATCH] shared/unit-file: add a function to validate unit alias - symlinks - -It turns out most possible symlinks are invalid, because the type has to match, -and template units can only be linked to template units. - -I'm not sure if the existing code made the same checks consistently. At least -I don't see the same rules expressed in a single place. - -revert shared unit file add a function to validate unit alias symlinks ---- - src/shared/unit-file.c | 73 ----------------------------------------------- - src/shared/unit-file.h | 2 -- - src/test/meson.build | 4 --- - src/test/test-unit-file.c | 34 ---------------------- - 4 files changed, 113 deletions(-) - delete mode 100644 src/test/test-unit-file.c - -diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c -index cde38c4..deed7dc 100644 ---- a/src/shared/unit-file.c -+++ b/src/shared/unit-file.c -@@ -1,7 +1,6 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - - #include "macro.h" --#include "string-util.h" - #include "unit-file.h" - - bool unit_type_may_alias(UnitType type) { -@@ -22,75 +21,3 @@ bool unit_type_may_template(UnitType type) { - UNIT_TIMER, - UNIT_PATH); - } -- --int unit_validate_alias_symlink_and_warn(const char *filename, const char *target) { -- const char *src, *dst; -- _cleanup_free_ char *src_instance = NULL, *dst_instance = NULL; -- UnitType src_unit_type, dst_unit_type; -- int src_name_type, dst_name_type; -- -- /* Check if the *alias* symlink is valid. This applies to symlinks like -- * /etc/systemd/system/dbus.service → dbus-broker.service, but not to .wants or .requires symlinks -- * and such. Neither does this apply to symlinks which *link* units, i.e. symlinks to outside of the -- * unit lookup path. -- * -- * -EINVAL is returned if the something is wrong with the source filename or the source unit type is -- * not allowed to symlink, -- * -EXDEV if the target filename is not a valid unit name or doesn't match the source. -- */ -- -- src = basename(filename); -- dst = basename(target); -- -- /* src checks */ -- -- src_name_type = unit_name_to_instance(src, &src_instance); -- if (src_name_type < 0) -- return log_notice_errno(src_name_type, -- "%s: not a valid unit name \"%s\": %m", filename, src); -- -- src_unit_type = unit_name_to_type(src); -- assert(src_unit_type >= 0); /* unit_name_to_instance() checked the suffix already */ -- -- if (!unit_type_may_alias(src_unit_type)) -- return log_notice_errno(SYNTHETIC_ERRNO(EINVAL), -- "%s: symlinks are not allowed for units of this type, rejecting.", -- filename); -- -- if (src_name_type != UNIT_NAME_PLAIN && -- !unit_type_may_template(src_unit_type)) -- return log_notice_errno(SYNTHETIC_ERRNO(EINVAL), -- "%s: templates not allowed for %s units, rejecting.", -- filename, unit_type_to_string(src_unit_type)); -- -- /* dst checks */ -- -- dst_name_type = unit_name_to_instance(dst, &dst_instance); -- if (dst_name_type < 0) -- return log_notice_errno(dst_name_type == -EINVAL ? SYNTHETIC_ERRNO(EXDEV) : dst_name_type, -- "%s points to \"%s\" which is not a valid unit name: %m", -- filename, dst); -- -- if (!(dst_name_type == src_name_type || -- (src_name_type == UNIT_NAME_INSTANCE && dst_name_type == UNIT_NAME_TEMPLATE))) -- return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), -- "%s: symlink target name type \"%s\" does not match source, rejecting.", -- filename, dst); -- -- if (dst_name_type == UNIT_NAME_INSTANCE) { -- assert(src_instance); -- assert(dst_instance); -- if (!streq(src_instance, dst_instance)) -- return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), -- "%s: unit symlink target \"%s\" instance name doesn't match, rejecting.", -- filename, dst); -- } -- -- dst_unit_type = unit_name_to_type(dst); -- if (dst_unit_type != src_unit_type) -- return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), -- "%s: symlink target \"%s\" has incompatible suffix, rejecting.", -- filename, dst); -- -- return 0; --} -diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h -index e57f472..2b9df65 100644 ---- a/src/shared/unit-file.h -+++ b/src/shared/unit-file.h -@@ -35,5 +35,3 @@ enum UnitFileScope { - - bool unit_type_may_alias(UnitType type) _const_; - bool unit_type_may_template(UnitType type) _const_; -- --int unit_validate_alias_symlink_and_warn(const char *filename, const char *target); -diff --git a/src/test/meson.build b/src/test/meson.build -index de31e97..5625e68 100644 ---- a/src/test/meson.build -+++ b/src/test/meson.build -@@ -137,10 +137,6 @@ tests += [ - [], - 'ENABLE_EFI'], - -- [['src/test/test-unit-file.c'], -- [], -- []], -- - [['src/test/test-unit-name.c', - 'src/test/test-helper.c'], - [libcore, -diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c -deleted file mode 100644 -index b626b5f..0000000 ---- a/src/test/test-unit-file.c -+++ /dev/null -@@ -1,34 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ -- --#include "path-lookup.h" --#include "set.h" --#include "strv.h" --#include "tests.h" --#include "unit-file.h" -- --static void test_unit_validate_alias_symlink_and_warn(void) { -- log_info("/* %s */", __func__); -- -- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.service") == 0); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.socket") == -EXDEV); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.foobar") == -EXDEV); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.service") == 0); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.socket") == -EXDEV); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.service") == -EXDEV); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.socket") == -EXDEV); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@YYY.service") == -EXDEV); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@XXX.service") == 0); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@.service") == 0); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b.service") == -EXDEV); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b@.service") == -EXDEV); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.slice", "/other/b.slice") == -EINVAL); -- assert_se(unit_validate_alias_symlink_and_warn("/path/a.slice", "/other/b.slice") == -EINVAL); --} -- --int main(int argc, char **argv) { -- test_setup_logging(LOG_DEBUG); -- -- test_unit_validate_alias_symlink_and_warn(); -- -- return 0; --} --- -1.8.3.1 - diff --git a/systemd.spec b/systemd.spec index d5d82e64..a5f03973 100644 --- a/systemd.spec +++ b/systemd.spec @@ -20,7 +20,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 248 -Release: 1 +Release: 2 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -62,10 +62,10 @@ Patch0013: 0013-sd-bus-properly-initialize-containers.patch Patch0014: 0014-Revert-core-one-step-back-again-for-nspawn-we-actual.patch Patch0015: 0015-journal-don-t-enable-systemd-journald-audit.socket-b.patch Patch0016: 0016-systemd-change-time-log-level.patch -#Patch0017: fix-capsh-drop-but-ping-success.patch -#Patch0018: 0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch -#Patch0019: core-serialize-u-pids-until-the-processes-have-been-.patch -#Patch0020: scope-on-unified-make-sure-to-unwatch-all-PIDs-once-.patch +#Patch0017: 0017-fix-capsh-drop-but-ping-success.patch +#Patch0018: 0018-resolved-create-etc-resolv.conf-symlink-at-runtime.patch +#Patch0019: 0019-core-serialize-u-pids-until-the-processes-have-been-.patch +#Patch0020: 0020-scope-on-unified-make-sure-to-unwatch-all-PIDs-once-.patch BuildRequires: gcc, gcc-c++ BuildRequires: libcap-devel, libmount-devel, pam-devel, libselinux-devel @@ -1528,6 +1528,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Fri 30 Apr 2021 hexiaowen - 248-2 +- delete unused patches + * Fri 30 Apr 2021 hexiaowen - 248-1 - Rebase to version 248 -- Gitee From 4bbb1c9403b296025047500436e51587d8fdb55f Mon Sep 17 00:00:00 2001 From: overweight Date: Fri, 30 Apr 2021 05:24:30 -0400 Subject: [PATCH 2/2] delete unused patch --- ...6ff0d0da905a82884ccccbe729af42cc207d.patch | 84285 ---------------- sd-bus-fix-error-handling-on-readv.patch | 50 - systemd.spec | 3 + 3 files changed, 3 insertions(+), 84335 deletions(-) delete mode 100644 rebase-to-bded6ff0d0da905a82884ccccbe729af42cc207d.patch delete mode 100644 sd-bus-fix-error-handling-on-readv.patch diff --git a/rebase-to-bded6ff0d0da905a82884ccccbe729af42cc207d.patch b/rebase-to-bded6ff0d0da905a82884ccccbe729af42cc207d.patch deleted file mode 100644 index 52e1bd9b..00000000 --- a/rebase-to-bded6ff0d0da905a82884ccccbe729af42cc207d.patch +++ /dev/null @@ -1,84285 +0,0 @@ -From 3c6818c7641056bf30ad9dc8561415163fdde008 Mon Sep 17 00:00:00 2001 -From: overweight -Date: Thu, 17 Sep 2020 12:47:33 +0800 -Subject: [PATCH] rebase-to-bded6ff0d0da905a82884ccccbe729af42cc207d - ---- - NEWS | 122 +- - README | 17 +- - TODO | 89 +- - docs/AUTOMATIC_BOOT_ASSESSMENT.md | 20 +- - docs/CODING_STYLE.md | 15 +- - docs/CONTAINER_INTERFACE.md | 77 ++ - docs/CONTRIBUTING.md | 3 +- - docs/DISCOVERABLE_PARTITIONS.md | 22 +- - docs/ENVIRONMENT.md | 4 + - docs/GROUP_RECORD.md | 4 + - docs/JOURNAL_FILE_FORMAT.md | 4 +- - docs/RELEASE.md | 19 +- - docs/TRANSIENT-SETTINGS.md | 4 + - docs/USER_RECORD.md | 38 +- - factory/etc/nsswitch.conf | 2 +- - hwdb.d/60-evdev.hwdb | 8 + - hwdb.d/60-keyboard.hwdb | 34 + - hwdb.d/60-sensor.hwdb | 21 +- - man/custom-entities.ent.in | 1 + - man/daemon.xml | 50 +- - man/homectl.xml | 14 +- - man/homed.conf.xml | 6 +- - man/html.in | 11 +- - man/journalctl.xml | 29 +- - man/journald.conf.xml | 18 +- - man/kernel-install.xml | 4 +- - man/logind.conf.xml | 26 +- - man/man.in | 11 +- - man/meson.build | 10 +- - man/networkctl.xml | 11 +- - man/networkd.conf.xml | 4 +- - man/nss-myhostname.xml | 18 +- - man/nss-mymachines.xml | 12 +- - man/nss-resolve.xml | 18 +- - man/nss-systemd.xml | 2 +- - man/org.freedesktop.LogControl1.xml | 45 +- - man/org.freedesktop.home1.xml | 2 +- - man/org.freedesktop.login1.xml | 4 +- - man/org.freedesktop.machine1.xml | 2 +- - man/org.freedesktop.resolve1.xml | 39 + - man/org.freedesktop.systemd1.xml | 353 +++++- - man/repart.d.xml | 77 +- - man/resolved.conf.xml | 27 +- - man/rules/meson.build | 13 +- - man/runlevel.xml | 3 +- - man/sd_bus_error.xml | 27 +- - man/sd_bus_message_append.xml | 6 +- - man/sd_bus_message_open_container.xml | 17 +- - man/sd_bus_message_read.xml | 14 +- - man/sd_bus_message_read_basic.xml | 24 +- - man/sd_event_add_time.xml | 53 +- - man/sd_listen_fds.xml | 25 +- - man/sd_machine_get_class.xml | 21 +- - man/sd_seat_get_active.xml | 31 +- - man/systemctl.xml | 433 ++++--- - man/systemd-analyze.xml | 32 +- - man/systemd-backlight@.service.xml | 3 +- - man/systemd-detect-virt.xml | 7 +- - man/systemd-dissect.xml | 253 ++++ - man/systemd-gpt-auto-generator.xml | 6 +- - man/systemd-nspawn.xml | 33 + - man/systemd-rc-local-generator.xml | 35 +- - man/systemd-repart.xml | 48 +- - man/systemd-run.xml | 4 +- - man/systemd-sysusers.xml | 13 + - man/systemd-tmpfiles.xml | 34 +- - man/systemd.exec.xml | 330 ++++- - man/systemd.network.xml | 97 +- - man/systemd.resource-control.xml | 57 +- - man/systemd.service.xml | 43 +- - man/systemd.socket.xml | 103 +- - man/systemd.time.xml | 10 + - man/systemd.timer.xml | 27 +- - man/systemd.unit.xml | 13 +- - man/sysusers.d.xml | 12 +- - man/tc.xml | 2 +- - man/telinit.xml | 3 +- - man/udev_device_has_tag.xml | 65 +- - man/userdbctl.xml | 8 +- - meson.build | 111 +- - meson_options.txt | 3 + - po/.gitignore | 1 - - po/be.po | 694 +++++++++-- - po/be@latin.po | 708 +++++++++-- - po/bg.po | 711 +++++++++-- - po/ca.po | 491 +++++++- - po/cs.po | 22 +- - po/da.po | 851 ++++++++++--- - po/de.po | 736 ++++++++++-- - po/el.po | 676 +++++++++-- - po/es.po | 875 ++++++++++---- - po/fr.po | 337 +++--- - po/gl.po | 176 ++- - po/hr.po | 43 +- - po/hu.po | 707 ++++++++--- - po/id.po | 467 +++++++- - po/it.po | 71 +- - po/ja.po | 98 +- - po/ko.po | 701 +++++++++-- - po/lt.po | 345 +++++- - po/pl.po | 22 +- - po/pt_BR.po | 22 +- - po/ro.po | 708 ++++++++--- - po/ru.po | 109 +- - po/sk.po | 696 ++++++++--- - po/sr.po | 706 ++++++++--- - po/sv.po | 705 ++++++++--- - po/systemd.pot | 841 +++++++++++++ - po/tr.po | 438 ++++++- - po/uk.po | 417 ++++--- - po/zh_CN.po | 700 +++++++++-- - po/zh_TW.po | 180 ++- - rules.d/meson.build | 5 +- - shell-completion/bash/homectl | 2 +- - shell-completion/bash/resolvectl | 4 + - shell-completion/bash/systemctl.in | 5 +- - shell-completion/zsh/_journalctl | 4 +- - shell-completion/zsh/_networkctl | 36 +- - shell-completion/zsh/_systemctl.in | 8 + - src/analyze/analyze-condition.c | 103 +- - src/analyze/analyze-security.c | 97 +- - src/analyze/analyze-verify.c | 2 +- - src/analyze/analyze.c | 58 +- - src/backlight/backlight.c | 158 ++- - src/basic/blockdev-util.c | 37 + - src/basic/blockdev-util.h | 2 + - src/basic/btrfs-util.c | 14 +- - src/basic/btrfs-util.h | 6 + - src/basic/cap-list.h | 2 + - src/basic/capability-util.c | 40 +- - src/basic/capability-util.h | 1 + - src/basic/cgroup-util.c | 36 +- - src/basic/copy.c | 263 +++- - src/basic/copy.h | 2 + - src/basic/dlfcn-util.c | 40 + - src/basic/dlfcn-util.h | 2 + - src/basic/env-file.c | 10 +- - src/basic/env-util.c | 2 +- - src/basic/escape.c | 14 +- - src/basic/escape.h | 14 +- - src/basic/extract-word.c | 26 +- - src/basic/extract-word.h | 7 +- - src/basic/fd-util.c | 2 +- - src/basic/fs-util.c | 19 +- - src/basic/hashmap.c | 71 +- - src/basic/hashmap.h | 85 +- - src/basic/in-addr-util.c | 44 +- - src/basic/in-addr-util.h | 11 +- - src/basic/io-util.c | 4 +- - src/basic/label.c | 22 + - src/basic/label.h | 1 + - src/basic/list.h | 15 + - src/basic/log.c | 2 - - src/basic/log.h | 4 +- - src/basic/macro.h | 3 + - src/basic/meson.build | 1 + - src/basic/missing_capability.h | 33 +- - src/basic/missing_loop.h | 15 + - src/basic/missing_network.h | 5 + - src/basic/missing_socket.h | 4 + - src/basic/missing_stat.h | 136 ++- - src/basic/missing_syscall.h | 634 ++++++---- - src/basic/mkdir.c | 54 +- - src/basic/mkdir.h | 2 + - src/basic/mountpoint-util.c | 73 +- - src/basic/ordered-set.c | 27 +- - src/basic/ordered-set.h | 26 +- - src/basic/parse-util.c | 7 +- - src/basic/parse-util.h | 2 + - src/basic/path-lookup.c | 10 +- - src/basic/path-lookup.h | 2 +- - src/basic/path-util.c | 41 +- - src/basic/path-util.h | 3 +- - src/basic/procfs-util.c | 2 +- - src/basic/quota-util.c | 2 +- - src/basic/rm-rf.c | 54 +- - src/basic/rm-rf.h | 1 + - src/basic/selinux-util.c | 130 +- - src/basic/selinux-util.h | 2 + - src/basic/set.h | 18 +- - src/basic/siphash24.h | 6 + - src/basic/smack-util.c | 4 +- - src/basic/socket-label.c | 8 +- - src/basic/socket-util.c | 266 +++- - src/basic/socket-util.h | 57 +- - src/basic/stat-util.c | 57 + - src/basic/stat-util.h | 22 + - src/basic/string-util.c | 106 +- - src/basic/string-util.h | 39 +- - src/basic/strv.c | 92 +- - src/basic/strv.h | 25 +- - src/basic/terminal-util.h | 54 +- - src/basic/time-util.c | 84 +- - src/basic/time-util.h | 22 +- - src/basic/unit-def.h | 4 +- - src/basic/user-util.c | 31 + - src/basic/user-util.h | 1 + - src/basic/utf8.c | 22 +- - src/basic/utf8.h | 7 +- - src/basic/virt.c | 12 + - src/basic/virt.h | 1 + - src/basic/xattr-util.c | 8 +- - src/boot/bless-boot.c | 1 + - src/boot/bootctl.c | 65 +- - src/busctl/busctl.c | 12 +- - src/cgtop/cgtop.c | 3 +- - src/core/automount.c | 17 +- - src/core/bpf-firewall.c | 13 +- - src/core/cgroup.c | 182 +-- - src/core/cgroup.h | 4 +- - src/core/core-varlink.c | 9 +- - src/core/dbus-execute.c | 647 +++++++++- - src/core/dbus-job.c | 5 +- - src/core/dbus-manager.c | 85 +- - src/core/dbus-mount.c | 1 - - src/core/dbus-scope.c | 1 - - src/core/dbus-service.c | 6 +- - src/core/dbus-slice.c | 1 - - src/core/dbus-socket.c | 5 +- - src/core/dbus-swap.c | 1 - - src/core/dbus-unit.c | 34 +- - src/core/dbus.c | 24 +- - src/core/device.c | 34 +- - src/core/dynamic-user.c | 6 +- - src/core/execute.c | 868 +++++++++++--- - src/core/execute.h | 33 +- - src/core/job.c | 28 +- - src/core/killall.c | 6 +- - src/core/load-fragment-gperf.gperf.m4 | 36 +- - src/core/load-fragment.c | 1066 ++++++++++++----- - src/core/load-fragment.h | 8 +- - src/core/machine-id-setup.c | 2 +- - src/core/main.c | 50 +- - src/core/manager.c | 121 +- - src/core/manager.h | 5 +- - src/core/meson.build | 3 +- - src/core/mount-setup.c | 20 +- - src/core/mount.c | 8 +- - src/core/namespace.c | 333 ++++- - src/core/namespace.h | 43 +- - src/core/path.c | 20 +- - src/core/path.h | 1 + - src/core/selinux-access.c | 6 +- - src/core/selinux-setup.c | 5 +- - src/core/service.c | 34 +- - src/core/slice.c | 12 +- - src/core/socket.c | 156 ++- - src/core/socket.h | 1 + - src/core/swap.c | 10 +- - src/core/systemd.pc.in | 12 +- - src/core/target.c | 3 +- - src/core/timer.c | 4 +- - src/core/transaction.c | 82 +- - src/core/unit.c | 151 +-- - src/core/unit.h | 34 +- - src/coredump/coredump.c | 20 +- - src/cryptsetup/cryptsetup-generator.c | 64 +- - ...cryptsetup-util.c => cryptsetup-keyfile.c} | 2 +- - ...cryptsetup-util.h => cryptsetup-keyfile.h} | 0 - src/cryptsetup/cryptsetup-pkcs11.c | 2 +- - src/cryptsetup/cryptsetup.c | 31 +- - src/delta/delta.c | 43 +- - src/dissect/dissect.c | 625 ++++++++-- - src/escape/escape.c | 8 +- - src/firstboot/firstboot.c | 109 +- - src/fstab-generator/fstab-generator.c | 2 +- - src/getty-generator/getty-generator.c | 114 +- - src/gpt-auto-generator/gpt-auto-generator.c | 8 +- - src/home/homectl-fido2.c | 3 +- - src/home/homectl-pkcs11.c | 3 +- - src/home/homectl-recovery-key.c | 253 ++++ - src/home/homectl-recovery-key.h | 6 + - src/home/homectl.c | 97 +- - src/home/homed-conf.c | 2 +- - src/home/homed-home-bus.c | 4 +- - src/home/homed-home.c | 35 +- - src/home/homed-home.h | 1 + - src/home/homed-manager-bus.c | 9 +- - src/home/homed-manager.c | 8 +- - src/home/homed-varlink.c | 12 +- - src/home/homed.conf | 2 +- - src/home/homework-luks.c | 184 +-- - src/home/homework-luks.h | 4 +- - src/home/homework.c | 94 +- - src/home/homework.h | 1 + - src/home/meson.build | 28 +- - src/home/modhex.c | 74 ++ - src/home/modhex.h | 14 + - src/home/pam_systemd_home.c | 4 +- - src/home/pwquality-util.c | 186 --- - src/home/pwquality-util.h | 9 - - src/home/test-modhex.c | 51 + - src/home/user-record-pwquality.c | 90 ++ - src/home/user-record-pwquality.h | 7 + - src/home/user-record-util.c | 72 +- - src/home/user-record-util.h | 4 +- - src/hostname/hostnamectl.c | 2 +- - src/hostname/hostnamed.c | 36 +- - src/import/curl-util.c | 6 +- - src/import/import-common.c | 1 + - src/import/importd.c | 12 +- - src/initctl/initctl.c | 2 +- - src/journal-remote/journal-remote-main.c | 2 +- - src/journal/catalog.c | 3 +- - src/journal/compress.c | 11 +- - src/journal/journal-file.c | 9 +- - src/journal/journal-qrcode.c | 108 +- - src/journal/journal-qrcode.h | 2 +- - src/journal/journalctl.c | 268 +++-- - src/journal/journald-server.c | 52 +- - src/journal/journald-stream.c | 3 +- - src/journal/meson.build | 6 +- - src/journal/mmap-cache.c | 5 +- - src/journal/pcre2-dlopen.c | 57 + - src/journal/pcre2-dlopen.h | 18 + - src/journal/sd-journal.c | 99 +- - src/journal/test-catalog.c | 9 +- - src/kernel-install/90-loaderentry.install | 7 +- - src/kernel-install/kernel-install | 20 +- - src/libsystemd-network/arp-util.c | 2 +- - src/libsystemd-network/dhcp-option.c | 5 +- - src/libsystemd-network/dhcp6-internal.h | 5 +- - src/libsystemd-network/dhcp6-lease-internal.h | 2 + - src/libsystemd-network/dhcp6-option.c | 123 +- - src/libsystemd-network/lldp-network.c | 2 +- - src/libsystemd-network/sd-dhcp-client.c | 3 +- - src/libsystemd-network/sd-dhcp-server.c | 3 +- - src/libsystemd-network/sd-dhcp6-client.c | 12 +- - src/libsystemd-network/sd-dhcp6-lease.c | 39 +- - src/libsystemd-network/sd-ipv4acd.c | 16 + - src/libsystemd-network/sd-lldp.c | 3 +- - src/libsystemd-network/test-dhcp-client.c | 10 +- - src/libsystemd-network/test-dhcp6-client.c | 66 +- - src/libsystemd-network/test-ndisc-ra.c | 8 +- - src/libsystemd-network/test-ndisc-rs.c | 16 +- - src/libsystemd/libsystemd.sym | 13 + - src/libsystemd/sd-bus/bus-common-errors.h | 1 + - src/libsystemd/sd-bus/bus-error.c | 57 +- - src/libsystemd/sd-bus/bus-match.c | 6 +- - src/libsystemd/sd-bus/bus-objects.c | 3 +- - src/libsystemd/sd-bus/bus-socket.c | 12 +- - src/libsystemd/sd-bus/sd-bus.c | 4 +- - src/libsystemd/sd-bus/test-bus-chat.c | 10 +- - src/libsystemd/sd-bus/test-bus-error.c | 83 ++ - src/libsystemd/sd-bus/test-bus-server.c | 2 +- - src/libsystemd/sd-daemon/sd-daemon.c | 2 +- - src/libsystemd/sd-device/device-enumerator.c | 28 +- - src/libsystemd/sd-device/device-internal.h | 8 +- - src/libsystemd/sd-device/device-monitor.c | 21 +- - src/libsystemd/sd-device/device-private.c | 62 +- - src/libsystemd/sd-device/device-private.h | 2 +- - src/libsystemd/sd-device/device-util.h | 33 +- - src/libsystemd/sd-device/sd-device.c | 157 ++- - src/libsystemd/sd-event/sd-event.c | 51 +- - src/libsystemd/sd-hwdb/hwdb-util.c | 2 +- - src/libsystemd/sd-login/sd-login.c | 171 ++- - src/libsystemd/sd-netlink/netlink-types.c | 12 + - src/libsystemd/sd-netlink/netlink-util.h | 4 + - src/libsystemd/sd-netlink/rtnl-message.c | 24 +- - src/libsystemd/sd-netlink/sd-netlink.c | 4 +- - src/libsystemd/sd-netlink/test-netlink.c | 2 +- - src/libsystemd/sd-path/sd-path.c | 20 +- - src/libsystemd/sd-resolve/sd-resolve.c | 4 +- - src/libsystemd/sd-resolve/test-resolve.c | 4 +- - src/libudev/libudev-device.c | 62 +- - src/libudev/libudev-list.c | 3 +- - src/libudev/libudev.h | 2 + - src/libudev/libudev.sym | 6 + - src/locale/keymap-util.c | 6 +- - src/locale/localectl.c | 6 +- - src/login/loginctl.c | 18 +- - src/login/logind-acl.c | 7 +- - src/login/logind-button.c | 25 +- - src/login/logind-core.c | 29 +- - src/login/logind-dbus.c | 67 +- - src/login/logind-dbus.h | 2 +- - src/login/logind-gperf.gperf | 2 + - src/login/logind-inhibit.c | 55 +- - src/login/logind-inhibit.h | 5 +- - src/login/logind-seat-dbus.c | 5 +- - src/login/logind-session-dbus.c | 8 +- - src/login/logind-session-device.c | 12 +- - src/login/logind-session.c | 29 +- - src/login/logind-user-dbus.c | 5 +- - src/login/logind-user.c | 8 +- - src/login/logind.c | 15 +- - src/login/logind.conf.in | 3 + - src/login/logind.h | 3 + - src/login/org.freedesktop.login1.policy | 11 + - src/login/sysfs-show.c | 6 +- - src/login/user-runtime-dir.c | 22 +- - src/machine/image-dbus.c | 3 +- - src/machine/machine-dbus.c | 30 +- - src/machine/machinectl.c | 34 +- - src/machine/machined-core.c | 6 +- - src/machine/machined-dbus.c | 28 +- - src/machine/machined-varlink.c | 37 +- - src/machine/machined.c | 5 +- - src/network/generator/main.c | 9 +- - src/network/generator/network-generator.c | 3 +- - src/network/meson.build | 2 + - src/network/netdev/bond.c | 3 +- - src/network/netdev/bridge.c | 2 +- - src/network/netdev/l2tp-tunnel.c | 11 +- - src/network/netdev/macsec.c | 27 +- - src/network/netdev/macvlan.c | 3 +- - src/network/netdev/netdev-gperf.gperf | 4 +- - src/network/netdev/wireguard.c | 68 +- - src/network/netdev/wireguard.h | 4 +- - src/network/networkctl.c | 15 +- - src/network/networkd-address-pool.c | 8 +- - src/network/networkd-address.c | 17 +- - src/network/networkd-address.h | 2 + - src/network/networkd-brvlan.c | 2 +- - src/network/networkd-dhcp-server-bus.c | 3 +- - src/network/networkd-dhcp-server.c | 5 +- - src/network/networkd-dhcp4.c | 167 +-- - src/network/networkd-dhcp6.c | 67 +- - src/network/networkd-fdb.c | 12 +- - src/network/networkd-link-bus.c | 3 +- - src/network/networkd-link.c | 184 ++- - src/network/networkd-link.h | 6 +- - src/network/networkd-lldp-tx.c | 10 +- - src/network/networkd-manager-bus.c | 6 +- - src/network/networkd-manager.c | 93 +- - src/network/networkd-mdb.c | 252 ++++ - src/network/networkd-mdb.h | 32 + - src/network/networkd-ndisc.c | 446 +++++-- - src/network/networkd-ndisc.h | 18 + - src/network/networkd-network-bus.c | 6 +- - src/network/networkd-network-gperf.gperf | 4 +- - src/network/networkd-network.c | 33 +- - src/network/networkd-network.h | 4 + - src/network/networkd-radv.c | 4 +- - src/network/networkd-route.c | 15 +- - src/network/networkd-route.h | 2 + - src/network/networkd-routing-policy-rule.c | 236 ++-- - src/network/networkd-routing-policy-rule.h | 4 +- - src/network/networkd-speed-meter.c | 3 +- - src/network/test-routing-policy-rule.c | 19 +- - src/network/wait-online/manager.c | 8 +- - src/nspawn/meson.build | 2 + - src/nspawn/nspawn-creds.c | 25 + - src/nspawn/nspawn-creds.h | 12 + - src/nspawn/nspawn-mount.c | 2 +- - src/nspawn/nspawn-oci.c | 3 + - src/nspawn/nspawn-seccomp.c | 32 +- - src/nspawn/nspawn-seccomp.h | 2 +- - src/nspawn/nspawn-settings.c | 108 +- - src/nspawn/nspawn-settings.h | 7 +- - src/nspawn/nspawn-setuid.c | 16 +- - src/nspawn/nspawn.c | 246 +++- - src/nss-resolve/nss-resolve.c | 526 ++++---- - src/nss-systemd/nss-systemd.c | 2 +- - src/nss-systemd/userdb-glue.c | 2 +- - src/partition/growfs.c | 27 +- - src/partition/makefs.c | 42 +- - src/partition/repart.c | 1034 +++++++++++++--- - src/partition/test-repart.sh | 68 ++ - src/portable/portable.c | 15 +- - src/portable/portablectl.c | 11 +- - src/portable/portabled-bus.c | 3 +- - src/portable/portabled-image-bus.c | 3 +- - src/portable/portabled-image.c | 3 +- - src/rc-local-generator/rc-local-generator.c | 2 +- - src/resolve/meson.build | 78 +- - src/resolve/resolvectl.c | 1 + - src/resolve/resolved-bus.c | 168 ++- - src/resolve/resolved-conf.c | 199 ++- - src/resolve/resolved-conf.h | 15 +- - src/resolve/resolved-dns-cache.c | 6 +- - src/resolve/resolved-dns-packet.c | 6 +- - src/resolve/resolved-dns-query.c | 57 +- - src/resolve/resolved-dns-query.h | 14 +- - src/resolve/resolved-dns-rr.c | 3 +- - src/resolve/resolved-dns-scope.c | 86 +- - src/resolve/resolved-dns-server.c | 3 +- - src/resolve/resolved-dns-stream.c | 23 +- - src/resolve/resolved-dns-stream.h | 3 + - src/resolve/resolved-dns-stub.c | 408 +++++-- - src/resolve/resolved-dns-stub.h | 34 + - src/resolve/resolved-dns-transaction.c | 71 +- - src/resolve/resolved-dns-trust-anchor.c | 3 +- - src/resolve/resolved-dns-zone.c | 6 +- - src/resolve/resolved-dnssd-bus.c | 6 +- - src/resolve/resolved-dnssd.c | 22 +- - src/resolve/resolved-dnssd.h | 2 +- - src/resolve/resolved-gperf.gperf | 23 +- - src/resolve/resolved-link-bus.c | 6 +- - src/resolve/resolved-link.c | 3 +- - src/resolve/resolved-llmnr.c | 4 +- - src/resolve/resolved-manager.c | 48 +- - src/resolve/resolved-manager.h | 10 +- - src/resolve/resolved-resolv-conf.c | 16 +- - src/resolve/resolved-varlink.c | 534 +++++++++ - src/resolve/resolved-varlink.h | 7 + - src/run/run.c | 6 +- - src/shared/acl-util.c | 39 +- - src/shared/acl-util.h | 14 +- - src/shared/ask-password-api.c | 3 + - src/shared/bitmap.h | 6 +- - src/shared/bus-polkit.c | 6 +- - src/shared/bus-unit-procs.c | 9 +- - src/shared/bus-unit-util.c | 304 ++++- - src/shared/bus-util.c | 10 +- - src/shared/bus-util.h | 1 + - src/shared/cgroup-setup.c | 74 +- - src/shared/cgroup-setup.h | 4 +- - src/shared/clock-util.c | 16 +- - src/shared/condition.c | 21 +- - src/shared/condition.h | 2 - - src/shared/conf-parser.c | 8 +- - src/shared/conf-parser.h | 34 +- - src/shared/cpu-set-util.c | 2 +- - src/shared/cpu-set-util.h | 1 + - src/shared/crypt-util.c | 28 - - src/shared/crypt-util.h | 12 - - src/shared/cryptsetup-util.c | 111 ++ - src/shared/cryptsetup-util.h | 36 + - src/shared/dev-setup.c | 38 +- - src/shared/dev-setup.h | 2 +- - src/shared/dissect-image.c | 461 +++++-- - src/shared/dissect-image.h | 36 +- - src/shared/dropin.c | 3 +- - src/shared/ethtool-util.c | 26 +- - src/shared/exit-status.c | 2 + - src/shared/exit-status.h | 1 + - src/shared/fdset.c | 6 +- - src/shared/fdset.h | 6 +- - src/shared/format-table.c | 2 +- - src/shared/fstab-util.c | 68 +- - src/shared/generate-syscall-list.py | 14 + - src/shared/gpt.h | 45 +- - src/shared/group-record-nss.c | 219 ---- - src/shared/group-record-nss.h | 15 - - src/shared/group-record-show.c | 76 -- - src/shared/group-record-show.h | 6 - - src/shared/group-record.c | 2 + - src/shared/group-record.h | 2 + - src/shared/install.c | 47 +- - src/shared/install.h | 8 +- - src/shared/journal-util.c | 3 +- - src/shared/json.c | 192 ++- - src/shared/json.h | 14 + - src/shared/libcrypt-util.c | 19 +- - src/shared/libcrypt-util.h | 2 +- - src/shared/log-link.h | 24 +- - src/shared/logs-show.c | 86 +- - src/shared/loop-util.c | 128 +- - src/shared/loop-util.h | 1 + - src/shared/machine-image.c | 2 +- - src/shared/meson.build | 37 +- - src/shared/mkfs-util.c | 135 +++ - src/shared/mkfs-util.h | 10 + - src/shared/module-util.c | 2 +- - src/shared/mount-util.c | 22 +- - src/shared/numa-util.c | 57 + - src/shared/numa-util.h | 2 + - src/shared/offline-passwd.c | 2 +- - src/shared/pkcs11-util.c | 6 +- - src/shared/pretty-print.c | 6 + - src/shared/ptyfwd.c | 8 +- - src/shared/pwquality-util.c | 191 +++ - src/shared/pwquality-util.h | 41 + - src/shared/qrcode-util.c | 63 + - src/shared/qrcode-util.h | 9 + - src/shared/reboot-util.h | 2 +- - src/shared/resolve-util.h | 2 +- - src/shared/seccomp-util.c | 144 ++- - src/shared/seccomp-util.h | 36 +- - src/shared/sleep-config.c | 67 +- - src/shared/socket-netlink.c | 240 ++-- - src/shared/socket-netlink.h | 2 +- - src/shared/syscall-names.text | 597 +++++++++ - src/shared/tests.c | 85 ++ - src/shared/udev-util.c | 110 +- - src/shared/udev-util.h | 1 + - src/shared/unit-file.c | 54 +- - src/shared/unit-file.h | 12 +- - src/shared/user-record-nss.c | 269 ++++- - src/shared/user-record-nss.h | 11 +- - src/shared/user-record-show.c | 78 +- - src/shared/user-record-show.h | 2 + - src/shared/user-record.c | 77 +- - src/shared/user-record.h | 13 + - src/shared/userdb.c | 1 - - src/shared/varlink.c | 38 +- - src/shared/varlink.h | 1 + - src/shared/vlan-util.c | 6 +- - src/sleep/sleep.c | 12 +- - src/socket-proxy/socket-proxyd.c | 12 +- - src/sysctl/sysctl.c | 3 +- - src/systemctl/systemctl.c | 344 ++++-- - src/systemd/_sd-common.h | 2 +- - src/systemd/sd-bus-protocol.h | 6 + - src/systemd/sd-bus.h | 8 +- - src/systemd/sd-device.h | 4 + - src/systemd/sd-dhcp6-lease.h | 1 + - src/systemd/sd-event.h | 2 + - src/systemd/sd-login.h | 8 +- - src/systemd/sd-messages.h | 2 + - src/systemd/sd-netlink.h | 2 + - src/sysusers/sysusers.c | 58 +- - src/sysv-generator/sysv-generator.c | 11 +- - src/test/meson.build | 12 +- - src/test/test-acl-util.c | 22 +- - src/test/test-bitmap.c | 7 +- - src/test/test-calendarspec.c | 10 +- - src/test/test-capability.c | 2 + - src/test/test-cgroup-mask.c | 16 +- - src/test/test-condition.c | 15 - - src/test/test-copy.c | 42 +- - src/test/test-date.c | 4 +- - src/test/test-dev-setup.c | 5 +- - src/test/test-dissect-image.c | 51 - - src/test/test-env-file.c | 45 + - src/test/test-execute.c | 31 +- - src/test/test-extract-word.c | 66 +- - src/test/test-fdset.c | 3 +- - src/test/test-fileio.c | 22 +- - src/test/test-fs-util.c | 23 +- - src/test/test-hashmap-plain.c | 10 +- - src/test/test-hashmap.c | 3 +- - src/test/test-in-addr-util.c | 163 ++- - src/test/test-install-root.c | 3 +- - src/test/test-install.c | 3 +- - src/test/test-json.c | 38 +- - src/test/test-list.c | 47 + - src/test/test-load-fragment.c | 3 +- - src/test/test-mountpoint-util.c | 3 +- - src/test/test-namespace.c | 5 +- - src/test/test-ns.c | 8 +- - src/test/test-nss.c | 39 +- - src/test/test-parse-util.c | 12 +- - src/test/test-path.c | 2 +- - src/test/test-rm-rf.c | 74 ++ - src/test/test-seccomp.c | 27 +- - src/test/test-sizeof.c | 11 + - src/test/test-socket-netlink.c | 192 ++- - src/test/test-socket-util.c | 286 +---- - src/test/test-stat-util.c | 2 +- - src/test/test-string-util.c | 213 +++- - src/test/test-strv.c | 131 +- - src/test/test-terminal-util.c | 99 +- - src/test/test-time-util.c | 8 +- - src/test/test-udev.c | 36 +- - src/test/test-unit-file.c | 8 +- - src/test/test-user-util.c | 20 + - src/test/test-utf8.c | 20 + - src/time-wait-sync/time-wait-sync.c | 2 +- - src/timedate/timedatectl.c | 2 +- - src/timesync/timesyncd-conf.c | 3 +- - src/timesync/timesyncd-manager.c | 13 +- - src/tmpfiles/tmpfiles.c | 343 ++++-- - .../tty-ask-password-agent.c | 24 +- - src/udev/net/link-config-gperf.gperf | 3 +- - src/udev/net/link-config.c | 3 +- - src/udev/udev-builtin-keyboard.c | 6 +- - src/udev/udev-builtin-net_id.c | 2 +- - src/udev/udev-builtin-uaccess.c | 4 +- - src/udev/udev-builtin-usb_id.c | 2 +- - src/udev/udev-builtin.c | 7 +- - src/udev/udev-ctrl.c | 7 +- - src/udev/udev-event.c | 33 +- - src/udev/udev-node.c | 25 +- - src/udev/udev-rules.c | 57 +- - src/udev/udev-watch.c | 6 +- - src/udev/udevadm-monitor.c | 5 +- - src/udev/udevadm-test.c | 6 +- - src/udev/udevd.c | 30 +- - src/update-done/update-done.c | 2 +- - src/update-utmp/update-utmp.c | 6 +- - src/userdb/userdbctl.c | 10 +- - src/userdb/userdbd.c | 2 +- - src/userdb/userwork.c | 1 - - src/veritysetup/veritysetup.c | 6 +- - src/volatile-root/volatile-root.c | 2 +- - .../xdg-autostart-generator.c | 3 +- - .../xdg-autostart-service.c | 12 +- - test/README.testsuite | 14 +- - test/TEST-21-SYSUSERS/test.sh | 5 +- - ...ci-ppc64el => deny-list-ubuntu-ci-ppc64el} | 0 - ...lacklist-ubuntu-ci => deny-list-ubuntu-ci} | 0 - ...buntu-ci-i386 => deny-list-ubuntu-ci-i386} | 0 - ...ntu-ci-s390x => deny-list-ubuntu-ci-s390x} | 0 - ...ntu-ci-arm64 => deny-list-ubuntu-ci-arm64} | 0 - test/TEST-50-DISSECT/test.sh | 4 +- - test/TEST-54-CREDS/Makefile | 1 + - test/TEST-54-CREDS/test.sh | 7 + - test/TEST-55-UDEV-TAGS/Makefile | 1 + - test/TEST-55-UDEV-TAGS/test.sh | 8 + - test/create-busybox-container | 11 + - .../fuzz-network-parser/directives.network | 3 + - test/fuzz/fuzz-unit-file/directives.service | 3 + - .../fuzz-unit-file/systemd-machined.service | 3 - - test/networkd-test.py | 47 +- - .../exec-dynamicuser-statedir.service | 4 +- - ...emcallfilter-override-error-action.service | 8 + - ...mcallfilter-override-error-action2.service | 8 + - test/test-functions | 17 +- - .../conf/25-address-static.network | 258 ++++ - ...oken-prefixstable-without-address.network} | 2 +- - ...-prefix-veth-token-static-multiple.network | 9 - - .../ipv6-prefix-veth-token-static.network | 4 + - test/test-network/conf/ipv6-prefix.network | 5 + - .../routing-policy-rule-reconfigure.network | 33 + - test/test-network/systemd-networkd-tests.py | 102 +- - test/testsuite-52.units/testsuite-52.service | 0 - test/udev-test.pl | 4 +- - test/units/testsuite-13.sh | 44 +- - test/units/testsuite-50.sh | 104 +- - test/units/testsuite-54.service | 7 + - test/units/testsuite-54.sh | 31 + - test/units/testsuite-55.service | 7 + - test/units/testsuite-55.sh | 66 + - tools/make-man-index.py | 3 +- - tools/syscall-names-update.sh | 6 + - tools/update-dbus-docs.py | 75 +- - units/initrd-cleanup.service | 2 +- - units/initrd-fs.target | 2 +- - units/initrd-parse-etc.service | 2 +- - units/initrd-root-device.target | 2 +- - units/initrd-root-fs.target | 2 +- - units/initrd-switch-root.service | 2 +- - units/initrd-switch-root.target | 4 +- - units/initrd-udevadm-cleanup-db.service | 2 +- - units/initrd.target | 2 +- - units/meson.build | 1 + - units/rc-local.service.in | 8 +- - units/systemd-hibernate-resume@.service.in | 2 +- - units/systemd-hostnamed.service.in | 3 +- - units/systemd-journal-gatewayd.service.in | 3 +- - units/systemd-journal-remote.service.in | 3 +- - units/systemd-journal-upload.service.in | 3 +- - units/systemd-localed.service.in | 3 +- - units/systemd-logind.service.in | 4 +- - units/systemd-networkd.service.in | 10 +- - units/systemd-resolved.service.in | 4 +- - units/systemd-timedated.service.in | 3 +- - units/systemd-timesyncd.service.in | 4 +- - units/systemd-user-sessions.service.in | 2 +- - units/systemd-userdbd.service.in | 1 + - units/systemd-volatile-root.service.in | 2 +- - 743 files changed, 33232 insertions(+), 11401 deletions(-) - create mode 100644 man/systemd-dissect.xml - delete mode 100644 po/.gitignore - create mode 100644 po/systemd.pot - create mode 100644 src/basic/dlfcn-util.c - create mode 100644 src/basic/missing_loop.h - rename src/cryptsetup/{cryptsetup-util.c => cryptsetup-keyfile.c} (99%) - rename src/cryptsetup/{cryptsetup-util.h => cryptsetup-keyfile.h} (100%) - create mode 100644 src/home/homectl-recovery-key.c - create mode 100644 src/home/homectl-recovery-key.h - create mode 100644 src/home/modhex.c - create mode 100644 src/home/modhex.h - delete mode 100644 src/home/pwquality-util.c - delete mode 100644 src/home/pwquality-util.h - create mode 100644 src/home/test-modhex.c - create mode 100644 src/home/user-record-pwquality.c - create mode 100644 src/home/user-record-pwquality.h - create mode 100644 src/journal/pcre2-dlopen.c - create mode 100644 src/journal/pcre2-dlopen.h - create mode 100644 src/network/networkd-mdb.c - create mode 100644 src/network/networkd-mdb.h - create mode 100644 src/nspawn/nspawn-creds.c - create mode 100644 src/nspawn/nspawn-creds.h - create mode 100644 src/resolve/resolved-varlink.c - create mode 100644 src/resolve/resolved-varlink.h - delete mode 100644 src/shared/crypt-util.c - delete mode 100644 src/shared/crypt-util.h - create mode 100644 src/shared/cryptsetup-util.c - create mode 100644 src/shared/cryptsetup-util.h - create mode 100755 src/shared/generate-syscall-list.py - delete mode 100644 src/shared/group-record-nss.c - delete mode 100644 src/shared/group-record-nss.h - delete mode 100644 src/shared/group-record-show.c - delete mode 100644 src/shared/group-record-show.h - create mode 100644 src/shared/mkfs-util.c - create mode 100644 src/shared/mkfs-util.h - create mode 100644 src/shared/pwquality-util.c - create mode 100644 src/shared/pwquality-util.h - create mode 100644 src/shared/qrcode-util.c - create mode 100644 src/shared/qrcode-util.h - create mode 100644 src/shared/syscall-names.text - delete mode 100644 src/test/test-dissect-image.c - create mode 100644 src/test/test-rm-rf.c - rename test/TEST-24-UNIT-TESTS/{blacklist-ubuntu-ci-ppc64el => deny-list-ubuntu-ci-ppc64el} (100%) - rename test/TEST-25-IMPORT/{blacklist-ubuntu-ci => deny-list-ubuntu-ci} (100%) - rename test/TEST-30-ONCLOCKCHANGE/{blacklist-ubuntu-ci-i386 => deny-list-ubuntu-ci-i386} (100%) - rename test/TEST-36-NUMAPOLICY/{blacklist-ubuntu-ci-s390x => deny-list-ubuntu-ci-s390x} (100%) - rename test/TEST-40-EXEC-COMMAND-EX/{blacklist-ubuntu-ci-arm64 => deny-list-ubuntu-ci-arm64} (100%) - create mode 120000 test/TEST-54-CREDS/Makefile - create mode 100755 test/TEST-54-CREDS/test.sh - create mode 120000 test/TEST-55-UDEV-TAGS/Makefile - create mode 100755 test/TEST-55-UDEV-TAGS/test.sh - create mode 100644 test/test-execute/exec-systemcallfilter-override-error-action.service - create mode 100644 test/test-execute/exec-systemcallfilter-override-error-action2.service - rename test/test-network/conf/{ipv6-prefix-veth-token-static-explicit.network => ipv6-prefix-veth-token-prefixstable-without-address.network} (61%) - delete mode 100644 test/test-network/conf/ipv6-prefix-veth-token-static-multiple.network - create mode 100644 test/test-network/conf/routing-policy-rule-reconfigure.network - mode change 100755 => 100644 test/testsuite-52.units/testsuite-52.service - create mode 100644 test/units/testsuite-54.service - create mode 100755 test/units/testsuite-54.sh - create mode 100644 test/units/testsuite-55.service - create mode 100755 test/units/testsuite-55.sh - create mode 100755 tools/syscall-names-update.sh - -diff --git a/NEWS b/NEWS -index 95685ed..99194b0 100644 ---- a/NEWS -+++ b/NEWS -@@ -1,5 +1,106 @@ - systemd System and Service Manager - -+CHANGES WITH 247 in spe: -+ -+ * KERNEL API INCOMPATIBILTY: Linux 4.12 introduced two new uevents -+ "bind" and "unbind" to the Linux device model. When this kernel -+ change was made, systemd-udevd was only minimally updated to handle -+ and propagate these new event types. The introduction of these new -+ uevents (which are typically generated for USB devices and devices -+ needing a firmware upload before being functional) resulted in a -+ number of software issues, we so far didn't address (mostly because -+ there was hope the kernel maintainers would themeselves address these -+ issues in some form – which did not happen). To handle them properly, -+ many (if not most) udev rules files shipped in various packages need -+ updating, and so do many programs that monitor or enumerate devices -+ with libudev or sd-device, or otherwise process uevents. Please note -+ that this incompatibility is not fault of systemd or udev, but caused -+ by an incompatible kernel change that happened back in Linux 4.12. -+ -+ To minimize issues resulting from this kernel change (but not avoid -+ them entirely) starting with systemd-udevd 247 the udev "tags" -+ concept (which is a concept for marking and filtering devices during -+ enumeration and monitoring) has been reworked: udev tags are now -+ "sticky", meaning that once a tag is assigned to a device it will not -+ be removed from the device again until the device itself is removed -+ (i.e. unplugged). This makes sure that any application monitoring -+ devices that match a specific tag is guaranteed to both see uevents -+ where the device starts being relevant, and those where it stops -+ being relevant (the latter now regularly happening due to the new -+ "unbind" uevent type). The udev tags concept is hence now a concept -+ tied to a *device* instead of a device *event* — unlike for example -+ udev properties whose lifecycle (as before) is generally tied to a -+ device event, meaning that the previously determined properties are -+ forgotten whenever a new uevent is processed. -+ -+ With the newly redefined udev tags concept, sometimes it's necessary -+ to determine which tags are the ones applied by the most recent -+ uevent/database update, in order to discern them from those -+ originating from earlier uevents/database updates of the same -+ device. To accommodate for this a new automatic property CURRENT_TAGS -+ has been added that works similar to the existing TAGS property but -+ only lists tags set by the most recent uevent/database -+ update. Similar, the libudev/sd-device API has been updated with new -+ functions to enumerate these 'current' tags, in addition to the -+ existing APIs that now enumerate the 'sticky' ones. -+ -+ To properly handle "bind"/"unbind" on Linux 4.12 and newer it is -+ essential that all udev rules files and applications are updated to -+ handle the new events. Specifically: -+ -+ • All rule files that currently use a header guard similar to -+ ACTION!="add|change",GOTO="xyz_end" should be updated to use -+ ACTION=="remove",GOTO="xyz_end" instead, so that the -+ properties/tags they add are also applied whenever "bind" (or -+ "unbind") is seen. (This is most important for all physical device -+ types — as that's for which "bind" and "unbind" are currently -+ usually generated, for all other device types this change is still -+ recommended but not as important — but certainly prepares for -+ future kernel uevent type additions). -+ -+ • Similar, all code monitoring devices that contains an 'if' branch -+ discerning the "add" + "change" uevent actions from all other -+ uevents actions (i.e. considering devices only relevant after "add" -+ or "change", and irrelevant on all other events) should be reworked -+ to instead negatively check for "remove" only (i.e. considering -+ devices relevant after all event types, except for "remove", which -+ invalidates the device). Note that this also means that devices -+ should be considered relevant on "unbind", even though conceptually -+ this — in some form — invalidates the device. Since the precise -+ effect of "unbind" is not generically defined, devices should be -+ considered relevant even after "unbind", however I/O errors -+ accessing the device should then be handled gracefully. -+ -+ • Any code that uses device tags for deciding whether a device is -+ relevant or not most likely needs to be updated to use the new -+ udev_device_has_current_tag() API (or sd_device_has_current_tag() -+ in case sd-device is used), to check whether the tag is set -+ at the moment an uevent is seen (as opposed to the existing -+ udev_device_has_tag() API which checks if the tag ever existed on -+ the device, following the API concept redefinition explained -+ above). -+ -+ We are very sorry for this breakage and the requirement to update -+ packages using these interfaces. We'd again like to underline that -+ this is not caused by systemd/udev changes, but result of a kernel -+ behaviour change. -+ -+ * Since PAM 1.2.0 (2015) configuration snippets may be placed in -+ /usr/lib/pam.d/ in addition to /etc/pam.d/. If a file exists in the -+ latter it takes precedence over the former, similar to how most of -+ systemd's own configuration is handled. Given that PAM stack -+ definitions are primarily put together by OS vendors/distributions -+ (though possibly overridden by users), this systemd release moves its -+ own PAM stack configuration for the "systemd-user" PAM service (i.e. -+ for the PAM session invoked by the per-user user@.service instance) -+ from /etc/pam.d/ to /usr/lib/pam.d/. We recommend moving all -+ packages' vendor versions of their PAM stack definitions from -+ /etc/pam.d/ to /usr/lib/pam.d/, but if such OS-wide migration is not -+ desired the location to which systemd installs its PAM stack -+ configuration file may be changed via the "pamconfdir" meson variable -+ at build time, optionally undoing this change of default paths -+ introduced with systemd 247. -+ - CHANGES WITH 246: - - * The service manager gained basic support for cgroup v2 freezer. Units -@@ -114,7 +215,9 @@ CHANGES WITH 246: - - * tmpfs mounts automatically created by systemd (/tmp, /run, /dev/shm, - and others) now have a size and inode limits applied (50% of RAM for -- /tmp and /dev/shm, 10% of RAM for other mounts, etc.) -+ /tmp and /dev/shm, 10% of RAM for other mounts, etc.). Please note -+ that the implicit kernel default is 50% too, so there is no change -+ in the size limit for /tmp and /dev/shm. - - * nss-mymachines lost support for resolution of users and groups, and - now only does resolution of hostnames. This functionality is now -@@ -156,12 +259,17 @@ CHANGES WITH 246: - now automatically set to "Y" at boot, in order to enable pstore - generation for collection with systemd-pstore. - -- * A new 'hwdb' file has been added that collects information about PCI -- and USB devices that correctly support auto-suspend, on top of the -- databases for this we import from the ChromiumOS project. If you have -- a device that supports auto-suspend correctly and where it should be -- enabled by default, please submit a patch that adds it to the -- database (see /usr/lib/udev/hwdb.d/60-autosuspend.hwdb). -+ * We provide a set of udev rules to enable auto-suspend on PCI and USB -+ devices that were tested to correctly support it. Previously, this -+ was distributed as a set of udev rules, but has now been replaced by -+ by a set of hwdb entries (and a much shorter udev rule to take action -+ if the device modalias matches one of the new hwdb entries). -+ -+ As before, entries are periodically imported from the database -+ maintained by the ChromiumOS project. If you have a device that -+ supports auto-suspend correctly and where it should be enabled by -+ default, please submit a patch that adds it to the database (see -+ /usr/lib/udev/hwdb.d/60-autosuspend.hwdb). - - * systemd-udevd gained the new configuration option timeout_signal= as well - as a corresponding kernel command line option udev.timeout_signal=. -diff --git a/README b/README -index 558b8d9..b1fbf28 100644 ---- a/README -+++ b/README -@@ -151,6 +151,7 @@ REQUIREMENTS: - libcryptsetup (optional), >= 2.3.0 required for signed Verity images support - libaudit (optional) - libacl (optional) -+ libfdisk >= 2.33 (from util-linux) (optional) - libselinux (optional) - liblzma (optional) - liblz4 >= 1.3.0 / 130 (optional) -@@ -324,14 +325,14 @@ WARNINGS: - we don't execve() systemd-shutdown. - - STABLE BRANCHES AND BACKPORTS: -- Stable branches with backported patches are available in the -- systemd-stable repo at https://github.com/systemd/systemd-stable. -- -- Stable branches are started for certain releases of systemd and named -- after them, e.g. v238-stable. Stable branches are managed by -- distribution maintainers on an as needed basis. See -- https://www.freedesktop.org/wiki/Software/systemd/Backports/ for some -- more information and examples. -+ Stable branches with backported patches are available in the -+ systemd-stable repo at https://github.com/systemd/systemd-stable. -+ -+ Stable branches are started for certain releases of systemd and named -+ after them, e.g. v238-stable. Stable branches are managed by -+ distribution maintainers on an as needed basis. See -+ https://www.freedesktop.org/wiki/Software/systemd/Backports/ for some -+ more information and examples. - - ENGINEERING AND CONSULTING SERVICES: - Kinvolk (https://kinvolk.io) offers professional engineering -diff --git a/TODO b/TODO -index 58fdc45..76cc74f 100644 ---- a/TODO -+++ b/TODO -@@ -4,6 +4,9 @@ Bugfixes: - manager or system manager can be always set. It would be better to reject - them when parsing config. - -+* userdbctl: "Password OK: yes" is shown even when there are no passwords -+ or the password is locked. -+ - External: - - * Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros. -@@ -17,13 +20,20 @@ Janitorial Clean-ups: - - Features: - -+* nss-systemd: also synthesize shadow records for users/groups -+ - * nspawn: move "incoming mount" directory to /run/host, move "inaccessible" - nodes to /run/host, move notify socket (for sd_notify() between payload and - container manager) - -+* make use of new glibc 2.32 APIs sigabbrev_np() and strerrorname_np(). -+ - * cryptsetup: if keyfile specified in crypttab is AF_UNIX socket, connect to it - and read from it (like we do elsewhere with READ_FULL_FILE_CONNECT_SOCKET) - -+* when main nspawn supervisor process gets suspended due to SIGSTOP/SIGTTOU or -+ so, freeze the payload too. -+ - * repart: support setting up dm-integrity with HMAC - - * add /etc/integritytab, to support dm-integrity setups. In particular those -@@ -34,9 +44,6 @@ Features: - mounting a subdir of the root fs as actual root. This can be used as - fstype-agnostic version of btrfs' rootflags=subvol=foobar. - --* add --copy-from and --copy-to command to systemd-dissect which copies stuff -- in and out of a disk image -- - * Support ProtectProc= or so, using: https://patchwork.kernel.org/cover/11310197/ - - * if /usr/bin/swapoff fails due to OOM, log a friendly explanatory message about it -@@ -80,15 +87,11 @@ Features: - - * make us use dynamically fewer deps for containers in general purpose distros: - o turn into dlopen() deps: -- - pcre2 (always) — irrelevant on Fedora, since dep by -- libselinux, but should benefit Debian -- - libpwquality (always) - only relevant for homed, and maybe soon -- firstboot -+ - libidn2 (always) - - elfutils (always) - - p11-kit-trust (always) - - kmod-libs (only when called from PID 1) -- - cryptsetup-libs (only in RootImage= handling in PID 1, but not in systemd-cryptsetup) -- - similar: libblkid -+ - libblkid (only in RootImage= handling in PID 1, but not elsewhere) - - libpam (only when called from PID 1) - - bzip2, xz, lz4 (always — gzip and zstd should probably stay static deps the way they are, - since they are so basic and our defaults) -@@ -106,14 +109,10 @@ Features: - * systemd-path: add ESP and XBOOTLDR path. Add "private" runtime/state/cache dir enum, - mapping to $RUNTIME_DIRECTORY, $STATE_DIRECTORY and such - --* make "systemd-dissect" an official supported tool, i.e. move to /usr/bin/ and -- provide man page. Given that we now have a tool that can generate images like -- this, it's useful to have one that can dump contents of them, too. -- - * All tools that support --root= should also learn --image= so that they can -- operate on disk images directly. Specifically: bootctl, tmpfiles, sysusers, -- systemctl, repart, journalctl, coredumpctl. (Already done: systemd-nspawn, -- systemd-firstboot) -+ operate on disk images directly. Specifically: bootctl, systemctl, -+ coredumpctl. (Already done: systemd-nspawn, systemd-firstboot, -+ systemd-repart, systemd-tmpfiles, systemd-sysusers, journalctl) - - * seccomp: by default mask x32 ABI system wide on x86-64. it's on its way out - -@@ -122,20 +121,18 @@ Features: - - * seccomp: maybe merge all filters we install into one with that libseccomp API that allows merging. - --* per-service credential system. Specifically: add LoadCredential= (for loading -- cred from file), AcquireCredential= (for asking user for cred, via -- ask-password), PassCredential= (for passing on credential systemd itself -- got). Then, place credentials in a per-service, immutable ramfs instance (so -- that it cannot be swapped out), destroy after use. Also pass via keyring -- (with graceful fallback to cover for containers). Define CredentialPath= for -- defining subdir of /run/credentials/ where to place it. Set $CREDENTIAL_PATH -- env var for services to the result. Also pass via fd passing (optionally). -- --* homed: add native recovery key support. use 48 lowercase modhex characters -- (192bit), show qr code of it, include pattern expression in user record. -- --* homed: introduce "degraded" state for home directories that weren't cleanly -- unmounted (use xattr we add and remove on the loop back file) -+* credentials system: -+ - maybe add AcquireCredential= for querying a cred via ask-password -+ - maybe try to acquire creds via keyring? -+ - maybe try to pass creds via keyring? -+ - maybe optionally pass creds via memfd -+ - maybe add support for decrypting creds via TPM -+ - maybe add support for decrypting/importing creds via pkcs11 -+ - make systemd-cryptsetup acquire pw via creds logic -+ - make PAMName= acquire pw via creds logic -+ - make macsec/wireguard code in networkd read key via creds logic -+ - make gatwayd/remote read key via creds logic -+ - add sd_notify() command for flushing out creds not needed anymore - - * homed: during login resize fs automatically towards size goal. Specifically, - resize to diskSize if possible, but leave a certain amount (configured by a -@@ -174,11 +171,6 @@ Features: - * systemd-gpt-auto should probably set x-systemd.growfs on the mounts it - creates - --* homed/userdb: distinguish passwords and recovery keys in the records, since -- we probably want to use different PBKDF algorithms/settings for them: -- passwords have low entropy but recovery keys should have good entropy key -- hence we can make them quicker to work. -- - * bootctl: - - teach it to prepare an ESP wholesale, i.e. with mkfs.vfat invocation - - teach it to copy in unified kernel images and maybe type #1 boot loader spec entries from host -@@ -237,9 +229,6 @@ Features: - * systemd-repart: allow sizing partitions as factor of available RAM, so that - we can reasonably size swap partitions for hibernation. - --* systemd-repart: allow running mkfs before making partitions pop up + -- encryption via LUKS to allow booting into an empty root with only /usr mounted in -- - * systemd-repart: allow managing the gpt read-only partition flag + auto-mount flag - - * systemd-repart: allow boolean option that ensures that if existing partition -@@ -255,10 +244,6 @@ Features: - * systemd-repart: add per-partition option to fail if partition already exist, - i.e. is not added new. Similar, add option to fail if partition does not exist yet. - --* systemd-repart: add --size=auto for generating/resizing images of minimal -- size, i.e. where the image file is sized exactly as large as necessary taking -- SizeMin= into account, but not a single byte larger. -- - * systemd-repart: allow disabling growing of specific partitions, or making - them (think ESP: we don't ever want to grow it, since we cannot resize vfat) - -@@ -328,9 +313,6 @@ Features: - right) become genuine first class citizens, and we gain automatic, sane JSON - output for them. - --* systemd-firstboot: teach it dissector magic, so that you can point it to some -- disk image and it will just set everything in it all behind the scenes. -- - * We should probably replace /var/log/README, /etc/rc.d/README with symlinks - that are linked to these places instead of copied. After all they are - constant vendor data. -@@ -366,9 +348,7 @@ Features: - - in systemd's PAMName= logic: query passwords with ssh-askpassword, so that we can make "loginctl set-linger" mode work - - fingerprint authentication, pattern authentication, … - - make sure "classic" user records can also be managed by homed -- - description field for groups - - make size of $XDG_RUNTIME_DIR configurable in user record -- - reuse pwquality magic in firstboot - - query password from kernel keyring first - - update even if record is "absent" - - add a "access mode" + "fstype" field to the "status" section of json identity records reflecting the actually used access mode and fstype, even on non-luks backends -@@ -549,7 +529,7 @@ Features: - directory trees from the host to the services RootImage= and RootDirectory= - environment. Which we can use for /etc/machine-id and in particular - /etc/resolv.conf. Should be smart and do something useful on read-only -- images, for example fallback to read-only bind mounting the file instead. -+ images, for example fall back to read-only bind mounting the file instead. - - * show invocation ID in systemd-run output - -@@ -581,6 +561,9 @@ Features: - * sd-bus: add vtable flag, that may be used to request client creds implicitly - and asynchronously before dispatching the operation - -+* sd-bus: parse addresses given in sd_bus_set_addresses immediately and not -+ only when used. Add unit tests. -+ - * make use of ethtool veth peer info in machined, for automatically finding out - host-side interface pointing to the container. - -@@ -933,6 +916,10 @@ Features: - - allow multiple signal handlers per signal? - - document chaining of signal handler for SIGCHLD and child handlers - - define more intervals where we will shift wakeup intervals around in, 1h, 6h, 24h, ... -+ - maybe support iouring as backend, so that we allow hooking read and write -+ operations instead of IO ready events into event loops. See considerations -+ here: -+ http://blog.vmsplice.net/2020/07/rethinking-event-loop-integration-for.html - - * investigate endianness issues of UUID vs. GUID - -@@ -1022,7 +1009,7 @@ Features: - - journald: also get thread ID from client, plus thread name - - journal: when waiting for journal additions in the client always sleep at least 1s or so, in order to minimize wakeups - - add API to close/reopen/get fd for journal client fd in libsystemd-journal. -- - fallback to /dev/log based logging in libsystemd-journal, if we cannot log natively? -+ - fall back to /dev/log based logging in libsystemd-journal, if we cannot log natively? - - declare the local journal protocol stable in the wiki interface chart - - sd-journal: speed up sd_journal_get_data() with transparent hash table in bg - - journald: when dropping msgs due to ratelimit make sure to write -@@ -1147,10 +1134,6 @@ Features: - - optionally automatically add FORWARD rules to iptables whenever nspawn is - running, remove them when shut down. - --* dissect -- - refuse mounting over a mount point -- - automatically discover .roothash files in dissect, similarly to nspawn -- - * machined: - - add an API so that libvirt-lxc can inform us about network interfaces being - removed or added to an existing machine -diff --git a/docs/AUTOMATIC_BOOT_ASSESSMENT.md b/docs/AUTOMATIC_BOOT_ASSESSMENT.md -index 83ddf28..f6d63af 100644 ---- a/docs/AUTOMATIC_BOOT_ASSESSMENT.md -+++ b/docs/AUTOMATIC_BOOT_ASSESSMENT.md -@@ -10,12 +10,11 @@ systemd provides support for automatically reverting back to the previous - version of the OS or kernel in case the system consistently fails to boot. This - support is built into various of its components. When used together these - components provide a complete solution on UEFI systems, built as add-on to the --[Boot Loader --Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION). However, the --different components may also be used independently, and in combination with --other software, to implement similar schemes, for example with other boot --loaders or for non-UEFI systems. Here's a brief overview of the complete set of --components: -+[Boot Loader Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION). -+However, the different components may also be used independently, and in -+combination with other software, to implement similar schemes, for example with -+other boot loaders or for non-UEFI systems. Here's a brief overview of the -+complete set of components: - - * The - [`systemd-boot(7)`](https://www.freedesktop.org/software/systemd/man/systemd-boot.html) -@@ -45,11 +44,10 @@ components: - - * The `boot-complete.target` target unit (see - [`systemd.special(7)`](https://www.freedesktop.org/software/systemd/man/systemd.special.html)) -- serves as a generic extension point both for units that shall be considered -- necessary to consider a boot successful on one side (example: -- `systemd-boot-check-no-failures.service` as described above), and units that -- want to act only if the boot is successful on the other (example: -- `systemd-bless-boot.service` as described above). -+ serves as a generic extension point both for units that are necessary to -+ consider a boot successful (example: `systemd-boot-check-no-failures.service` -+ as described above), and units that want to act only if the boot is -+ successful (example: `systemd-bless-boot.service` as described above). - - * The - [`kernel-install(8)`](https://www.freedesktop.org/software/systemd/man/kernel-install.html) -diff --git a/docs/CODING_STYLE.md b/docs/CODING_STYLE.md -index f335a10..11cc622 100644 ---- a/docs/CODING_STYLE.md -+++ b/docs/CODING_STYLE.md -@@ -25,6 +25,17 @@ layout: default - note that emacs loads `.dir-locals.el` automatically, but vim needs to be - configured to load `.vimrc`, see that file for instructions. - -+- If you break a function declaration over multiple lines, do it like this: -+ -+ ```c -+ void some_function( -+ int foo, -+ bool bar, -+ char baz) { -+ -+ int a, b, c; -+ ``` -+ - - Try to write this: - - ```c -@@ -372,7 +383,7 @@ layout: default - broken on Linux). - - - When applying C-style unescaping as well as specifier expansion on the same -- string, always apply the C-style unescaping fist, followed by the specifier -+ string, always apply the C-style unescaping first, followed by the specifier - expansion. When doing the reverse, make sure to escape `%` in specifier-style - first (i.e. `%` → `%%`), and then do C-style escaping where necessary. - -@@ -529,7 +540,7 @@ layout: default - - - Don't use `fgets()`, it's too hard to properly handle errors such as overly - long lines. Use `read_line()` instead, which is our own function that handles -- this much nicer. -+ this much more nicely. - - - Don't invoke `exit()`, ever. It is not replacement for proper error - handling. Please escalate errors up your call chain, and use normal `return` -diff --git a/docs/CONTAINER_INTERFACE.md b/docs/CONTAINER_INTERFACE.md -index a36d2ed..40b1533 100644 ---- a/docs/CONTAINER_INTERFACE.md -+++ b/docs/CONTAINER_INTERFACE.md -@@ -131,6 +131,17 @@ manager, please consider supporting the following interfaces. - `$container_host_variant_id=server` - `$container_host_version_id=10` - -+5. systemd supports passing immutable binary data blobs with limited size and -+ restricted access to services via the `LoadCredential=` and `SetCredential=` -+ settings. The same protocol may be used to pass credentials from the -+ container manager to systemd itself. The credential data should be placed in -+ some location (ideally a read-only and non-swappable file system, like -+ 'ramfs'), and the absolute path to this directory exported in the -+ `$CREDENTIALS_DIRECTORY` environment variable. If the container managers -+ does this, the credentials passed to the service manager can be propagated -+ to services via `LoadCredential=` (see ...). The container manager can -+ choose any path, but `/run/host/credentials` is recommended." -+ - ## Advanced Integration - - 1. Consider syncing `/etc/localtime` from the host file system into the -@@ -172,6 +183,13 @@ manager, please consider supporting the following interfaces. - unit they created for their container. That's private property of systemd, - and no other code should modify it. - -+6. systemd running inside the container can report when boot-up is complete -+ using the usual `sd_notify()` protocol that is also used when a service -+ wants to tell the service manager about readiness. A container manager can -+ set the `$NOTIFY_SOCKET` environment variable to a suitable socket path to -+ make use of this functionality. (Also see information about -+ `/run/host/notify` below.) -+ - ## Networking - - 1. Inside of a container, if a `veth` link is named `host0`, `systemd-networkd` -@@ -189,6 +207,65 @@ manager, please consider supporting the following interfaces. - devices, for example hashed out of the container names. That way it is more - likely that DHCP and IPv4LL will acquire stable addresses. - -+## The `/run/host/` Hierarchy -+ -+Container managers may place certain resources the manager wants to provide to -+the container payload below the `/run/host/` hierarchy. This hierarchy should -+be mostly immutable (possibly some subdirs might be writable, but the top-level -+hierarchy — and probably most subdirs should be read-only to the -+container). Note that this hierarchy is used by various container managers, and -+care should be taken to avoid naming conflicts. `systemd` (and in particular -+`systemd-nspawn`) use the hierarchy for the following resources: -+ -+1. The `/run/host/incoming/` directory mount point is configured for `MS_SLAVE` -+ mount propagation with the host, and is used as intermediary location for -+ mounts to establish in the container, for the implementation of `machinectl -+ bind`. Container payload should usually not directly interact with this -+ directory: it's used by code outside the container to insert mounts inside -+ it only, and is mostly an internal vehicle to achieve this. Other container -+ managers that want to implement similar functionality might consider using -+ the same directory. -+ -+2. The `/run/host/inaccessible/` directory may be set up by the container -+ manager to include six file nodes: `reg`, `dir`, `fifo`, `sock`, `chr`, -+ `blk`. These nodes correspond with the six types of file nodes Linux knows -+ (with the exceptions of symlinks). Each node should be of the specific type -+ and have an all zero access mode, i.e. be inaccessible. The two device node -+ types should have major and minor of zero (which are unallocated devices on -+ Linux). These nodes are used as mount source for implementing the -+ `InaccessiblePath=` setting of unit files, i.e. file nodes to mask this way -+ are overmounted with these "inaccessible" inodes, guaranteeing that the file -+ node type does not change this way but the nodes still become -+ inaccessible. Note that systemd when run as PID 1 in the container payload -+ will create these nodes on its own if not passed in by the container -+ manager. However, in that case it likely lacks the privileges to create the -+ character and block devices nodes (there are fallbacks for this case). -+ -+3. The `/run/host/notify` path is a good choice to place the `sd_notify()` -+ socket in, that may be used for the container's PID 1 to report to the -+ container manager when boot-up is complete. The path used for this doesn't -+ matter much as it is communicated via the `$NOTIFY_SOCKET` environment -+ variable, following the usual protocol for this, however it's suitable, and -+ recommended place for this socket in case ready notification is desired. -+ -+4. The `/run/host/os-release` file contains the `/etc/os-release` file of the -+ host, i.e. may be used by the container payload to gather limited -+ information about the host environment, on top of what `uname -a` reports. -+ -+5. The `/run/host/container-manager` file may be used to pass the same -+ information as the `$container` environment variable (see above), i.e. a -+ short string identifying the container manager implementation. This file -+ should be newline terminated. Passing this information via this file has the -+ benefit that payload code can easily access it, even when running -+ unprivileged without access to the container PID1's environment block. -+ -+6. The `/run/host/container-uuid` file may be used to pass the same information -+ as the `$container_uuid` environment variable (see above). This file should -+ be newline terminated. -+ -+7. The `/run/host/credentials/` directory is a good place to pass credentials -+ into the container, using the `$CREDENTIALS_DIRECTORY` protocol, see above. -+ - ## What You Shouldn't Do - - 1. Do not drop `CAP_MKNOD` from the container. `PrivateDevices=` is a commonly -diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md -index 7d7bb38..cab0074 100644 ---- a/docs/CONTRIBUTING.md -+++ b/docs/CONTRIBUTING.md -@@ -10,8 +10,9 @@ We welcome contributions from everyone. However, please follow the following gui - - ## Filing Issues - --* We use [GitHub Issues](https://github.com/systemd/systemd/issues) **exclusively** for tracking **bugs** and **feature** **requests** of systemd. If you are looking for help, please contact [systemd-devel mailing list](https://lists.freedesktop.org/mailman/listinfo/systemd-devel) instead. -+* We use [GitHub Issues](https://github.com/systemd/systemd/issues) **exclusively** for tracking **bugs** and **feature** **requests** (RFEs) of systemd. If you are looking for help, please contact [systemd-devel mailing list](https://lists.freedesktop.org/mailman/listinfo/systemd-devel) instead. - * We only track bugs in the **two** **most** **recently** **released** (non-rc) **versions** of systemd in the GitHub Issue tracker. If you are using an older version of systemd, please contact your distribution's bug tracker instead (see below). See [GitHub Release Page](https://github.com/systemd/systemd/releases) for the list of most recent releases. -+* When filing a feature request issue (RFE), please always check first if the newest upstream version of systemd already implements the feature, and whether there's already an issue filed for your feature by someone else. - * When filing an issue, specify the **systemd** **version** you are experiencing the issue with. Also, indicate which **distribution** you are using. - * Please include an explanation how to reproduce the issue you are pointing out. - -diff --git a/docs/DISCOVERABLE_PARTITIONS.md b/docs/DISCOVERABLE_PARTITIONS.md -index f1537b8..380dee1 100644 ---- a/docs/DISCOVERABLE_PARTITIONS.md -+++ b/docs/DISCOVERABLE_PARTITIONS.md -@@ -9,21 +9,21 @@ _TL;DR: Let's automatically discover, mount and enable the root partition, - `/home/`, `/srv/`, `/var/` and `/var/tmp/` and the swap partitions based on - GUID Partition Tables (GPT)!_ - --The GUID Partition Table (GPT) is mandatory on EFI systems. It allows --identification of partition types with UUIDs. So far Linux has made little use --of this, and mostly just defined one UUID for file system/data partitions and --another one for swap partitions. With this specification, we introduce --additional partition types to enable automatic discovery of partitions and --their intended mountpoint. This has many benefits: -+This specification describes the use of GUID Partition Table (GPT) UUIDs to -+enable automatic discovery of partitions and their intended mountpoints. -+Traditionally Linux has made little use of partition types, mostly just -+defining one UUID for file system/data partitions and another one for swap -+partitions. With this specification, we introduce additional partition types -+for specific uses. This has many benefits: - - * OS installers can automatically discover and make sense of partitions of - existing Linux installations. --* The OS can discover and mount the necessary file systems with a non-existing -+* The OS can discover and mount the necessary file systems with a non-existent - or incomplete `/etc/fstab` file and without the `root=` kernel command line - option. --* Container managers (such as nspawn and libvirt-lxc) can decode and set up -+* Container managers (such as nspawn and libvirt-lxc) can introspect and set up - file systems contained in GPT disk images automatically and mount them to the -- right places, thus allowing booting the same, identical images on bare-metal -+ right places, thus allowing booting the same, identical images on bare metal - and in Linux containers. This enables true, natural portability of disk - images between physical machines and Linux containers. - * As a help to administrators and users partition manager tools can show more -@@ -31,7 +31,7 @@ their intended mountpoint. This has many benefits: - - Note that the OS side of this specification is currently implemented in - [systemd](http://systemd.io/) 211 and newer in the --[systemd-auto-gpt-generator(8)](http://www.freedesktop.org/software/systemd/man/systemd-gpt-auto-generator.html) -+[systemd-gpt-auto-generator(8)](http://www.freedesktop.org/software/systemd/man/systemd-gpt-auto-generator.html) - generator tool. Note that automatic discovery of the root only works if the - boot loader communicates this information to the OS, by implementing the [Boot - Loader -@@ -64,7 +64,7 @@ Other GPT type IDs might be used on Linux, for example to mark software RAID or - LVM partitions. The definitions of those GPT types is outside of the scope of - this specification. - --[systemd-id128(1)](http://www.freedesktop.org/software/systemd/man/systemd-i128.html) -+[systemd-id128(1)](http://www.freedesktop.org/software/systemd/man/systemd-id128.html) - may be used to list those UUIDs. - - ## Partition Names -diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md -index d6f5126..ea433a4 100644 ---- a/docs/ENVIRONMENT.md -+++ b/docs/ENVIRONMENT.md -@@ -90,6 +90,10 @@ systemctl: - - * `$SYSTEMCTL_SKIP_SYSV=1` — if set, do not call out to SysV compatibility hooks. - -+* `$SYSTEMD_LOG_SECCOMP=1` — if set, system calls blocked by seccomp filtering, -+ for example in systemd-nspawn, will be logged to the audit log, if the current -+ kernel version supports this. -+ - systemd-nspawn: - - * `$SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=1` — if set, force nspawn into unified -diff --git a/docs/GROUP_RECORD.md b/docs/GROUP_RECORD.md -index 2ea0b73..0180049 100644 ---- a/docs/GROUP_RECORD.md -+++ b/docs/GROUP_RECORD.md -@@ -22,6 +22,10 @@ UNIX/glibc NSS `struct group`, or the shadow structure `struct sgrp`'s - `realm` → The "realm" the group belongs to, conceptually identical to the same - field of user records. A string in DNS domain name syntax. - -+`description` → A descriptive string for the group. This is similar to the -+`realName` field of user records, and accepts arbitrary strings, as long as -+they follow the same GECOS syntax requirements as `realName`. -+ - `disposition` → The disposition of the group, conceptually identical to the - same field of user records. A string. - -diff --git a/docs/JOURNAL_FILE_FORMAT.md b/docs/JOURNAL_FILE_FORMAT.md -index 523ed62..e87a758 100644 ---- a/docs/JOURNAL_FILE_FORMAT.md -+++ b/docs/JOURNAL_FILE_FORMAT.md -@@ -196,8 +196,8 @@ The currently used part of the file is the **header_size** plus the - **arena_size** field of the header. If a writer needs to write to a file where - the actual file size on disk is smaller than the reported value it shall - immediately rotate the file and start a new one. If a writer is asked to write --to a file with a header that is shorter than his own definition of the struct --Header, he shall immediately rotate the file and start a new one. -+to a file with a header that is shorter than its own definition of the struct -+Header, it shall immediately rotate the file and start a new one. - - The **n_objects** field contains a counter for objects currently available in - this file. As objects are appended to the end of the file this counter is -diff --git a/docs/RELEASE.md b/docs/RELEASE.md -index b56635a..b9bf196 100644 ---- a/docs/RELEASE.md -+++ b/docs/RELEASE.md -@@ -10,12 +10,13 @@ layout: default - 2. Update the contributors list in NEWS (`ninja -C build git-contrib`) - 3. Update the time and place in NEWS - 4. Update version and library numbers in `meson.build` --5. Tag the release: `version=vXXX-rcY && git tag -s "${version}" -m "systemd ${version}"` --6. Do `ninja -C build` --7. Make sure that the version string and package string match: `build/systemctl --version` --8. Upload the documentation: `ninja -C build doc-sync` --9. [After final release] Close the github milestone and open a new one (https://github.com/systemd/systemd/milestones) --10. "Draft" a new release on github (https://github.com/systemd/systemd/releases/new), mark "This is a pre-release" if appropriate. --11. Check that announcement to systemd-devel, with a copy&paste from NEWS, was sent. This should happen automatically. --12. Update IRC topic (`/msg chanserv TOPIC #systemd Version NNN released`) --13. [After final release] Also push commits to stable, create an empty -stable branch: `git push systemd-stable origin/master:master origin/master:refs/heads/${version}-stable`, and change the default branch to latest release (https://github.com/systemd/systemd-stable/settings/branches). -+5. Check dbus docs with `ninja -C build man/update-dbus-docs` -+6. Tag the release: `version=vXXX-rcY && git tag -s "${version}" -m "systemd ${version}"` -+7. Do `ninja -C build` -+8. Make sure that the version string and package string match: `build/systemctl --version` -+9. Upload the documentation: `ninja -C build doc-sync` -+10. [After final release] Close the github milestone and open a new one (https://github.com/systemd/systemd/milestones) -+11. "Draft" a new release on github (https://github.com/systemd/systemd/releases/new), mark "This is a pre-release" if appropriate. -+12. Check that announcement to systemd-devel, with a copy&paste from NEWS, was sent. This should happen automatically. -+13. Update IRC topic (`/msg chanserv TOPIC #systemd Version NNN released`) -+14. [After final release] Also push commits to stable, create an empty -stable branch: `git push systemd-stable origin/master:master origin/master:refs/heads/${version}-stable`, and change the default branch to latest release (https://github.com/systemd/systemd-stable/settings/branches). -diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md -index 19944d0..f8ff413 100644 ---- a/docs/TRANSIENT-SETTINGS.md -+++ b/docs/TRANSIENT-SETTINGS.md -@@ -151,9 +151,12 @@ All execution-related settings are available for transient units. - ✓ TimerSlackNSec= - ✓ NoNewPrivileges= - ✓ KeyringMode= -+✓ ProtectProc= -+✓ ProcSubset= - ✓ SystemCallFilter= - ✓ SystemCallArchitectures= - ✓ SystemCallErrorNumber= -+✓ SystemCallLog= - ✓ MemoryDenyWriteExecute= - ✓ RestrictNamespaces= - ✓ RestrictRealtime= -@@ -413,6 +416,7 @@ Most socket unit settings are available to transient units. - ✓ SocketMode= - ✓ DirectoryMode= - ✓ Accept= -+✓ FlushPending= - ✓ Writable= - ✓ MaxConnections= - ✓ MaxConnectionsPerSource= -diff --git a/docs/USER_RECORD.md b/docs/USER_RECORD.md -index f6d22c2..6cba02a 100644 ---- a/docs/USER_RECORD.md -+++ b/docs/USER_RECORD.md -@@ -221,12 +221,14 @@ optional, when unset the user should not be considered part of any realm. A - user record with a realm set is never compatible (for the purpose of updates, - see above) with a user record without one set, even if the `userName` field matches. - --`realName` → The real name of the user, a string. This should contain the user's --real ("human") name, and corresponds loosely to the GECOS field of classic UNIX --user records. When converting a `struct passwd` to a JSON user record this --field is initialized from GECOS (i.e. the `pw_gecos` field), and vice versa --when converting back. That said, unlike GECOS this field is supposed to contain --only the real name and no other information. -+`realName` → The real name of the user, a string. This should contain the -+user's real ("human") name, and corresponds loosely to the GECOS field of -+classic UNIX user records. When converting a `struct passwd` to a JSON user -+record this field is initialized from GECOS (i.e. the `pw_gecos` field), and -+vice versa when converting back. That said, unlike GECOS this field is supposed -+to contain only the real name and no other information. This field must not -+contain control characters (such as `\n`) or colons (`:`), since those are used -+as record separators in classic `/etc/passwd` files and similar formats. - - `emailAddress` → The email address of the user, formatted as - string. [`pam_systemd`](https://www.freedesktop.org/software/systemd/man/pam_systemd.html) -@@ -551,6 +553,11 @@ credential ID that shell be used for authentication with FIDO2 devices that - implement the `hmac-secret` extension. The salt to pass to the FIDO2 device is - found in `fido2HmacSalt`. - -+`recoveryKeyType` → An array of strings, each indicating the type of one -+recovery key. The only supported recovery key type at the moment is `modhex64`, -+for details see the description of `recoveryKey` below. An account may have any -+number of recovery keys defined, and the array should have one entry for each. -+ - `privileged` → An object, which contains the fields of the `privileged` section - of the user record, see below. - -@@ -630,6 +637,25 @@ matching one in `fido2HmacCredential`, and vice versa, with the same credential - ID, appearing in the same order, but this should not be required by - applications processing user records. - -+`recoveryKey`→ An array of objects, each defining a recovery key. The object -+has two mandatory fields: `type` indicates the type of recovery key. The only -+currently permitted value is the string `modhex64`. The `hashedPassword` field -+contains a UNIX password hash of the normalized recovery key. Recovery keys are -+in most ways similar to regular passwords, except that they are generated by -+the computer, not chosen by the user, and are longer. Currently, the only -+supported recovery key format is `modhex64`, which consists of 64 -+[modhex](https://developers.yubico.com/yubico-c/Manuals/modhex.1.html) -+characters (i.e. 256bit of information), in groups of 8 chars separated by -+dashes, -+e.g. `lhkbicdj-trbuftjv-tviijfck-dfvbknrh-uiulbhui-higltier-kecfhkbk-egrirkui`. Recovery -+keys should be accepted wherever regular passwords are. The `recoveryKey` field -+should always be accompanied by a `recoveryKeyType` field (see above), and each -+entry in either should map 1:1 to an entry in the other, in the same order and -+matching the type. When accepting a recovery key it should be brought -+automatically into normalized form, i.e. the dashes inserted when missing, and -+converted into lowercase before tested against the UNIX password hash, so that -+recovery keys are effectively case-insensitive. -+ - ## Fields in the `perMachine` section - - As mentioned, the `perMachine` section contains settings that shall apply to -diff --git a/factory/etc/nsswitch.conf b/factory/etc/nsswitch.conf -index da74b19..d87f881 100644 ---- a/factory/etc/nsswitch.conf -+++ b/factory/etc/nsswitch.conf -@@ -4,7 +4,7 @@ passwd: compat systemd - group: compat [SUCCESS=merge] systemd - shadow: compat - --hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname -+hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns - networks: files - - protocols: db files -diff --git a/hwdb.d/60-evdev.hwdb b/hwdb.d/60-evdev.hwdb -index 6d760b2..bf9f68a 100644 ---- a/hwdb.d/60-evdev.hwdb -+++ b/hwdb.d/60-evdev.hwdb -@@ -399,6 +399,14 @@ evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPad??40?:* - EVDEV_ABS_35=::41 - EVDEV_ABS_36=::37 - -+# Lenovo X240 series -+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX240:* -+evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX240?:* -+ EVDEV_ABS_00=1232:5711:51 -+ EVDEV_ABS_01=1159:4700:53 -+ EVDEV_ABS_35=1232:5711:51 -+ EVDEV_ABS_36=1159:4700:53 -+ - # Lenovo ThinkPad X140e - evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX140e* - EVDEV_ABS_00=1176:5767:62 -diff --git a/hwdb.d/60-keyboard.hwdb b/hwdb.d/60-keyboard.hwdb -index 84d997e..855b98f 100644 ---- a/hwdb.d/60-keyboard.hwdb -+++ b/hwdb.d/60-keyboard.hwdb -@@ -1348,6 +1348,40 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOQO*Inc.*:pnOQO*Model*2*:pvr* - KEYBOARD_KEY_f2=volumedown - KEYBOARD_KEY_f3=volumeup - -+########################################################### -+# Ortek -+########################################################### -+ -+# Adesso AKB-805MAC -+# The key code identifiers used below exactly match the text -+# labels on the keys/buttons (or standard icons on the buttons -+# that have no text labels), except as noted. -+evdev:input:b0003v05A4p9735* -+ KEYBOARD_KEY_c0015=back -+ KEYBOARD_KEY_c0012=forward -+ KEYBOARD_KEY_c000c=stop -+ KEYBOARD_KEY_c0018=refresh -+ KEYBOARD_KEY_c00b9=search -+ KEYBOARD_KEY_c0006=bookmarks # Button labeled "Favorites" -+ KEYBOARD_KEY_c00a8=homepage # Button labeled "Web/Home" -+ KEYBOARD_KEY_c0010=mute -+ KEYBOARD_KEY_c0011=volumedown -+ KEYBOARD_KEY_c0014=volumeup -+ KEYBOARD_KEY_c000e=close -+ KEYBOARD_KEY_c00a7=print -+ KEYBOARD_KEY_c0013=documents # Button labeled "Stickies" -+ KEYBOARD_KEY_c000d=find # Button labeled "Sherlock2" -+ KEYBOARD_KEY_c000f=mail -+ KEYBOARD_KEY_c000a=calc -+ KEYBOARD_KEY_c000b=sleep -+ KEYBOARD_KEY_c0007=previoussong # Button with standard |<< icon -+ KEYBOARD_KEY_c0008=playpause # Button with standad >/|| icon -+ KEYBOARD_KEY_c0009=nextsong # Button with standard >>| icon -+ KEYBOARD_KEY_c00b2=stopcd # Button with standard square box icon -+ KEYBOARD_KEY_c0016=prog1 # Key labeled "pf1" -+ KEYBOARD_KEY_c00bb=prog2 # Key labeled "pf2" -+ KEYBOARD_KEY_c00b8=prog3 # Key labeled "pf3" -+ - ########################################################### - # Plantronics - ########################################################### -diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb -index 092d356..1c30d43 100644 ---- a/hwdb.d/60-sensor.hwdb -+++ b/hwdb.d/60-sensor.hwdb -@@ -78,6 +78,9 @@ sensor:modalias:acpi:INVN6500*:dmi:*svn*Acer*:*pn*AspireSW5-011* - sensor:modalias:acpi:INVN6500*:dmi:*svn*Acer*:*pn*AspireSW5-012* - ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 - -+sensor:modalias:acpi:BOSC0200*:dmi:*svnAcer*:*TP-SW5-017-17BU* -+ ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, -1 -+ - sensor:modalias:acpi:BMA250E*:dmi:*:svnAcer:pnIconiaW1-810:* - ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 - -@@ -90,6 +93,7 @@ sensor:modalias:acpi:KIOX0009*:dmi:*:svnAcer:pnOneS1003:* - sensor:modalias:acpi:BOSC0200*:dmi:*:svnAcer*:pnSwitchSW312-31:* - ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 - -+sensor:modalias:acpi:BOSC0200*:dmi:*svn*Acer*:*pn*Spin*SP111-32* - sensor:modalias:acpi:BOSC0200*:dmi:*svn*Acer*:*pn*Spin*SP111-33* - ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 - -@@ -111,6 +115,7 @@ sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100CHI* - sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pnT300CHI* - ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1 - -+sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnM80TA* - sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100TA* - sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pnT200TA* - ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 -@@ -379,11 +384,17 @@ sensor:modalias:acpi:BMA250*:dmi:*:bvritWORKS.G.WI71C.JGBMRB*:*:svnInsyde:pni71c - ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 - - ######################################### --# Irbis TW90 -+# Irbis - ######################################### -+ -+#TW90 - sensor:modalias:acpi:BOSC0200*:dmi:*:svnIRBIS:pnTW90:* - ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1 - -+#TW118 -+sensor:modalias:acpi:BOSC0200*:dmi:*:svnIRBIS:pnTW118:* -+ ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 -+ - ######################################### - # iOTA 360 - ######################################### -@@ -558,6 +569,14 @@ sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrONDA.W89*:svnInsyde:pnONDATa - sensor:modalias:acpi:SMO8500*:dmi:bvnAmericanMegatrendsInc.:bvr5.6.5:bd07/25/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.: - ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 - -+######################################### -+# One-netbook -+######################################### -+ -+# One-netbook OneMix 3 Pro -+sensor:modalias:acpi:BOSC0200*:dmi:*svnONE-NETBOOKTECHNOLOGYCO*:pnOne-Mix3Pro:* -+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 -+ - ######################################### - # Peaq - ######################################### -diff --git a/man/custom-entities.ent.in b/man/custom-entities.ent.in -index 03fe05f..dc4b242 100644 ---- a/man/custom-entities.ent.in -+++ b/man/custom-entities.ent.in -@@ -10,3 +10,4 @@ - - - -+ -diff --git a/man/daemon.xml b/man/daemon.xml -index 072529e..b5ae084 100644 ---- a/man/daemon.xml -+++ b/man/daemon.xml -@@ -448,37 +448,27 @@ - - Other Forms of Activation - -- Other forms of activation have been suggested and -- implemented in some systems. However, there are often simpler or -- better alternatives, or they can be put together of combinations -- of the schemes above. Example: Sometimes, it appears useful to -- start daemons or .socket units when a -- specific IP address is configured on a network interface, -- because network sockets shall be bound to the address. However, -- an alternative to implement this is by utilizing the Linux -- IP_FREEBIND socket option, as accessible -- via FreeBind=yes in systemd socket files (see -- systemd.socket5 -- for details). This option, when enabled, allows sockets to be -- bound to a non-local, not configured IP address, and hence -- allows bindings to a particular IP address before it actually -- becomes available, making such an explicit dependency to the -- configured address redundant. Another often suggested trigger -- for service activation is low system load. However, here too, a -- more convincing approach might be to make proper use of features -- of the operating system, in particular, the CPU or I/O scheduler -- of Linux. Instead of scheduling jobs from userspace based on -- monitoring the OS scheduler, it is advisable to leave the -- scheduling of processes to the OS scheduler itself. systemd -- provides fine-grained access to the CPU and I/O schedulers. If a -- process executed by the init system shall not negatively impact -- the amount of CPU or I/O bandwidth available to other processes, -- it should be configured with -+ Other forms of activation have been suggested and implemented in some systems. However, there are -+ often simpler or better alternatives, or they can be put together of combinations of the schemes -+ above. Example: Sometimes, it appears useful to start daemons or .socket units -+ when a specific IP address is configured on a network interface, because network sockets shall be bound -+ to the address. However, an alternative to implement this is by utilizing the Linux -+ IP_FREEBIND/IPV6_FREEBIND socket option, as accessible via -+ FreeBind=yes in systemd socket files (see -+ systemd.socket5 for -+ details). This option, when enabled, allows sockets to be bound to a non-local, not configured IP -+ address, and hence allows bindings to a particular IP address before it actually becomes available, -+ making such an explicit dependency to the configured address redundant. Another often suggested trigger -+ for service activation is low system load. However, here too, a more convincing approach might be to -+ make proper use of features of the operating system, in particular, the CPU or I/O scheduler of -+ Linux. Instead of scheduling jobs from userspace based on monitoring the OS scheduler, it is advisable -+ to leave the scheduling of processes to the OS scheduler itself. systemd provides fine-grained access -+ to the CPU and I/O schedulers. If a process executed by the init system shall not negatively impact the -+ amount of CPU or I/O bandwidth available to other processes, it should be configured with - CPUSchedulingPolicy=idle and/or -- IOSchedulingClass=idle. Optionally, this may -- be combined with timer-based activation to schedule background -- jobs during runtime and with minimal impact on the system, and -- remove it from the boot phase itself. -+ IOSchedulingClass=idle. Optionally, this may be combined with timer-based activation -+ to schedule background jobs during runtime and with minimal impact on the system, and remove it from -+ the boot phase itself. - - - -diff --git a/man/homectl.xml b/man/homectl.xml -index 0724749..4c792ca 100644 ---- a/man/homectl.xml -+++ b/man/homectl.xml -@@ -376,6 +376,16 @@ - discussion see above. - - -+ -+ BOOL -+ -+ Accepts a boolean argument. If enabled a recovery key is configured for the -+ account. A recovery key is a computer generated access key that may be used to regain access to an -+ account if the password has been forgotten or the authentication token lost. The key is generated and -+ shown on screen, and should be printed or otherwise transferred to a secure location. A recovery key -+ may be entered instead of a regular password to unlock the account. -+ -+ - - BOOLEAN - -@@ -566,8 +576,8 @@ - TYPE - - When LUKS2 storage is used configures the file system type to use inside the home -- directory LUKS2 container. One of ext4, xfs, -- btrfs. If not specified -+ directory LUKS2 container. One of btrfs, ext4, -+ xfs. If not specified - homed.conf5 - defines which default file system type to use. Note that xfs is not recommended as - its support for file system resizing is too limited. -diff --git a/man/homed.conf.xml b/man/homed.conf.xml -index 2c5f335..d43a83d 100644 ---- a/man/homed.conf.xml -+++ b/man/homed.conf.xml -@@ -63,9 +63,9 @@ - - DefaultFileSystemType= - When using luks as storage (see above), selects the default file -- system to use inside the user's LUKS volume. Takes one of ext4, -- xfs or btrfs. If not specified defaults to -- ext4. This setting has no effect if a different storage mechanism is used. The -+ system to use inside the user's LUKS volume. Takes one of btrfs, -+ ext4 or xfs. If not specified defaults to -+ btrfs. This setting has no effect if a different storage mechanism is used. The - file system type selected on the homectl command line always takes - precedence. - -diff --git a/man/html.in b/man/html.in -index b7e7984..23b77eb 100755 ---- a/man/html.in -+++ b/man/html.in -@@ -11,5 +11,14 @@ ninja -C "@BUILD_ROOT@" version.h - - target="man/$1.html" - ninja -C "@BUILD_ROOT@" "$target" -+ -+fullname="@BUILD_ROOT@/$target" -+redirect="$(readlink "$fullname" 2>/dev/null)" -+if [ -n "$redirect" ]; then -+ ninja -C "@BUILD_ROOT@" "man/$redirect" -+ -+ fullname="@BUILD_ROOT@/man/$redirect" -+fi -+ - set -x --exec xdg-open "@BUILD_ROOT@/$target" -+exec xdg-open "$fullname" -diff --git a/man/journalctl.xml b/man/journalctl.xml -index 07310d9..fa23048 100644 ---- a/man/journalctl.xml -+++ b/man/journalctl.xml -@@ -453,7 +453,7 @@ - - - Suppresses all informational messages -- (i.e. "-- Logs begin at …", "-- Reboot --"), -+ (i.e. "-- Journal begins at …", "-- Reboot --"), - any warning messages regarding - inaccessible system journals when run as a normal - user. -@@ -756,16 +756,29 @@ - - - -- Takes a directory path as an argument. If -- specified, journalctl will operate on journal directories and catalog file hierarchy -- underneath the specified directory instead of the root -- directory (e.g. will create -- ROOT/var/lib/systemd/catalog/database, -- and journal files under ROOT/run/journal/ -- or ROOT/var/log/journal/ will be displayed). -+ Takes a directory path as an argument. If specified, journalctl -+ will operate on journal directories and catalog file hierarchy underneath the specified directory -+ instead of the root directory (e.g. will create -+ ROOT/var/lib/systemd/catalog/database, and journal -+ files under ROOT/run/journal/ or -+ ROOT/var/log/journal/ will be displayed). - - - -+ -+ -+ -+ Takes a path to a disk image file or block device node. If specified, -+ journalctl will operate on the file system in the indicated disk image. This is -+ similar to but operates on file systems stored in disk images or block -+ devices, thus providing an easy way to extract log data from disk images. The disk image should -+ either contain just a file system or a set of file systems within a GPT partition table, following -+ the Discoverable Partitions -+ Specification. For further information on supported disk images, see -+ systemd-nspawn1's -+ switch of the same name. -+ -+ - - - -diff --git a/man/journald.conf.xml b/man/journald.conf.xml -index bfd359a..d792ef7 100644 ---- a/man/journald.conf.xml -+++ b/man/journald.conf.xml -@@ -67,12 +67,18 @@ - persistent, data will be stored preferably on disk, i.e. below the - /var/log/journal hierarchy (which is created if needed), with a fallback to - /run/log/journal (which is created if needed), during early boot and if the disk -- is not writable. auto is similar to persistent but the -- directory /var/log/journal is not created if needed, so that its existence -- controls where log data goes. none turns off all storage, all log data received -- will be dropped. Forwarding to other targets, such as the console, the kernel log buffer, or a syslog -- socket will still work however. Defaults to auto in the default journal namespace, -- and persistent in all others. -+ is not writable. auto behaves like persistent if the -+ /var/log/journal directory exists, and volatile otherwise -+ (the existence of the directory controls the storage mode). none turns off all -+ storage, all log data received will be dropped (but forwarding to other targets, such as the console, -+ the kernel log buffer, or a syslog socket will still work). Defaults to auto in -+ the default journal namespace, and persistent in all others. -+ -+ Note that when this option is changed to volatile, existing persistent data -+ is not removed. In the other direction, -+ journalctl1 with -+ the option may be used to move volatile data to persistent storage. -+ - - - -diff --git a/man/kernel-install.xml b/man/kernel-install.xml -index 273270f..3de95f7 100644 ---- a/man/kernel-install.xml -+++ b/man/kernel-install.xml -@@ -211,7 +211,9 @@ - /etc/machine-id - - -- The content of the file specifies the machine identification MACHINE-ID. -+ The content of this file specifies the machine identification -+ MACHINE-ID. If it cannot read /etc/machine-id, -+ kernel-install will use "Linux" as the machine ID instead. - - - -diff --git a/man/logind.conf.xml b/man/logind.conf.xml -index 81b870c..97d11da 100644 ---- a/man/logind.conf.xml -+++ b/man/logind.conf.xml -@@ -199,10 +199,11 @@ - HandleLidSwitch= - HandleLidSwitchExternalPower= - HandleLidSwitchDocked= -+ HandleRebootKey= - - Controls how logind shall handle the -- system power and sleep keys and the lid switch to trigger -- actions such as system power-off or suspend. Can be one of -+ system power, reboot and sleep keys and the lid switch to trigger -+ actions such as system power-off, reboot or suspend. Can be one of - ignore, - poweroff, - reboot, -@@ -219,7 +220,8 @@ - in the respective event. Only input devices with the - power-switch udev tag will be watched for - key/lid switch events. HandlePowerKey= -- defaults to poweroff. -+ defaults to poweroff, HandleRebootKey= -+ defaults to reboot. - HandleSuspendKey= and - HandleLidSwitch= default to - suspend. -@@ -240,7 +242,8 @@ - A different application may disable logind's handling of system power and - sleep keys and the lid switch by taking a low-level inhibitor lock - (handle-power-key, handle-suspend-key, -- handle-hibernate-key, handle-lid-switch). -+ handle-hibernate-key, handle-lid-switch, -+ handle-reboot-switch). - This is most commonly used by graphical desktop environments - to take over suspend and hibernation handling, and to use their own configuration - mechanisms. If a low-level inhibitor lock is taken, logind will not take any -@@ -253,20 +256,23 @@ - SuspendKeyIgnoreInhibited= - HibernateKeyIgnoreInhibited= - LidSwitchIgnoreInhibited= -+ RebootKeyIgnoreInhibited= - - Controls whether actions that systemd-logind -- takes when the power and sleep keys and the lid switch are triggered are subject -- to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor -+ takes when the power, reboot and sleep keys and the lid switch are triggered are subject -+ to high-level inhibitor locks ("shutdown", "reboot", "sleep", "idle"). Low level inhibitor - locks (handle-power-key, handle-suspend-key, -- handle-hibernate-key, handle-lid-switch), -+ handle-hibernate-key, handle-lid-switch, -+ handle-reboot-key), - are always honored, irrespective of this setting. - - These settings take boolean arguments. If no, the - inhibitor locks taken by applications are respected. If yes, -- "shutdown", "sleep", and "idle" inhibitor locks are ignored. -+ "shutdown", "reboot" "sleep", and "idle" inhibitor locks are ignored. - PowerKeyIgnoreInhibited=, -- SuspendKeyIgnoreInhibited=, and -- HibernateKeyIgnoreInhibited= default to no. -+ SuspendKeyIgnoreInhibited=, -+ HibernateKeyIgnoreInhibited= and -+ RebootKeyIgnoreInhibited= default to no. - LidSwitchIgnoreInhibited= defaults to yes. - This means that when systemd-logind is handling events by - itself (no low level inhibitor locks are taken by another application), the lid -diff --git a/man/man.in b/man/man.in -index fa6164b..12eb332 100755 ---- a/man/man.in -+++ b/man/man.in -@@ -16,4 +16,13 @@ if [ -z "$target" ]; then - exit 1 - fi - ninja -C "@BUILD_ROOT@" "$target" --exec man "@BUILD_ROOT@/$target" -+ -+fullname="@BUILD_ROOT@/$target" -+redirect="$(sed -n -r '1 s|^\.so man[0-9]/(.*)|\1|p' "$fullname")" -+if [ -n "$redirect" ]; then -+ ninja -C "@BUILD_ROOT@" "man/$redirect" -+ -+ fullname="@BUILD_ROOT@/man/$redirect" -+fi -+ -+exec man "$fullname" -diff --git a/man/meson.build b/man/meson.build -index 3a7143a..3c2c702 100644 ---- a/man/meson.build -+++ b/man/meson.build -@@ -202,11 +202,17 @@ if dbus_docs.length() > 0 - custom_target( - 'update-dbus-docs', - output : 'update-dbus-docs', -- command : ['python3', -- '@0@/tools/update-dbus-docs.py'.format(project_source_root), -+ command : [update_dbus_docs_py, - '--build-dir=@0@'.format(project_build_root), - '@INPUT@'], - input : dbus_docs) -+ -+ if conf.get('DEVELOPER_MODE') == 1 -+ test('dbus-docs-fresh', -+ update_dbus_docs_py, -+ args : ['--build-dir=@0@'.format(project_build_root), -+ '--test'] + dbus_docs) -+ endif - endif - - ############################################################ -diff --git a/man/networkctl.xml b/man/networkctl.xml -index bd958fb..9b50912 100644 ---- a/man/networkctl.xml -+++ b/man/networkctl.xml -@@ -255,6 +255,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) - - - delete -+ DEVICE… - - Deletes virtual netdevs. Takes interface name or index number. - -@@ -262,6 +263,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) - - - up -+ DEVICE… - - Bring devices up. Takes interface name or index number. - -@@ -269,6 +271,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) - - - down -+ DEVICE… - - Bring devices down. Takes interface name or index number. - -@@ -276,6 +279,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) - - - renew -+ DEVICE… - - Renew dynamic configurations e.g. addresses received from DHCP server. - Takes interface name or index number. -@@ -284,6 +288,7 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) - - - forcerenew -+ DEVICE… - - Send a FORCERENEW message to all connected clients, triggering DHCP reconfiguration. - Takes interface name or index number. -@@ -292,8 +297,12 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) - - - reconfigure -+ DEVICE… - -- Reconfigure network interfaces. Takes interface name or index number. -+ Reconfigure network interfaces. Takes interface name or index number. Note that -+ this does not reload .netdev or .network -+ corresponding to the the specified interface. So, if you edit config files, it is necessary to -+ call networkctl reload first to apply new settings. - - - -diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml -index e8e41eb..821212c 100644 ---- a/man/networkd.conf.xml -+++ b/man/networkd.conf.xml -@@ -52,8 +52,8 @@ - SpeedMeter= - Takes a boolean. If set to yes, then systemd-networkd - measures the traffic of each interface, and -- networkctl status INTERFACE shows the measured speed. -- Defaults to no. -+ networkctl status INTERFACE shows the measured speed. -+ Defaults to no. - - - -diff --git a/man/nss-myhostname.xml b/man/nss-myhostname.xml -index a41c383..b424f1f 100644 ---- a/man/nss-myhostname.xml -+++ b/man/nss-myhostname.xml -@@ -67,12 +67,12 @@ - hosts: in /etc/nsswitch.conf. - - It is recommended to place myhostname either between resolve -- and "traditional" modules like files and dns, or after them. In the -- first version, well-known names like localhost and the machine hostname are given -- higher priority than the external configuration. This is recommended when the external DNS servers and -- network are not absolutely trusted. In the second version, external configuration is given higher -- priority and nss-myhostname only provides a fallback mechanism. This might be suitable -- in closely controlled networks, for example on a company LAN. -+ and "traditional" modules like dns, or after them. In the first version, well-known -+ names like localhost and the machine hostname are given higher priority than the -+ external configuration. This is recommended when the external DNS servers and network are not absolutely -+ trusted. In the second version, external configuration is given higher priority and -+ nss-myhostname only provides a fallback mechanism. This might be suitable in closely -+ controlled networks, for example on a company LAN. - - - -@@ -83,11 +83,11 @@ - - - passwd: compat systemd --group: compat systemd -+group: compat [SUCCESS=merge] systemd - shadow: compat - --# Either (untrusted network): --hosts: mymachines resolve [!UNAVAIL=return] myhostname files dns -+# Either (untrusted network, see above): -+hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns - # Or (only trusted networks): - hosts: mymachines resolve [!UNAVAIL=return] files dns myhostname - networks: files -diff --git a/man/nss-mymachines.xml b/man/nss-mymachines.xml -index e0e6989..56ee073 100644 ---- a/man/nss-mymachines.xml -+++ b/man/nss-mymachines.xml -@@ -42,10 +42,10 @@ - To activate the NSS module, add mymachines to the line starting with - hosts: in /etc/nsswitch.conf. - -- It is recommended to place mymachines after the files or -- compat entry of the /etc/nsswitch.conf line to make sure that its -- mappings are preferred over other resolvers such as DNS, but so that /etc/hosts -- based mappings take precedence. -+ It is recommended to place mymachines before the resolve or -+ dns entry of the hosts: line of -+ /etc/nsswitch.conf in order to make sure that its mappings are preferred over other -+ resolvers such as DNS. - - - -@@ -56,10 +56,10 @@ - - - passwd: compat systemd --group: compat systemd -+group: compat [SUCCESS=merge] systemd - shadow: compat - --hosts: mymachines resolve [!UNAVAIL=return] myhostname files dns -+hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns - networks: files - - protocols: db files -diff --git a/man/nss-resolve.xml b/man/nss-resolve.xml -index c377468..e6963e5 100644 ---- a/man/nss-resolve.xml -+++ b/man/nss-resolve.xml -@@ -44,14 +44,12 @@ - dns somewhere after resolve, to fall back to - nss-dns if systemd-resolved.service is not available. - -- Note that systemd-resolved will synthesize DNS resource -- records in a few cases, for example for localhost and the -- current hostname, see -- systemd-resolved8 -- for the full list. This duplicates the functionality of -- nss-myhostname8, -- but it is still recommended (see examples below) to keep -- nss-myhostname configured in -+ Note that systemd-resolved will synthesize DNS resource records in a few cases, -+ for example for localhost and the current local hostname, see -+ systemd-resolved8 for -+ the full list. This duplicates the functionality of -+ nss-myhostname8, but -+ it is still recommended (see examples below) to keep nss-myhostname configured in - /etc/nsswitch.conf, to keep those names resolveable if - systemd-resolved is not running. - -@@ -64,10 +62,10 @@ - - - passwd: compat systemd --group: compat systemd -+group: compat [SUCCESS=merge] systemd - shadow: compat - --hosts: mymachines resolve [!UNAVAIL=return] myhostname files dns -+hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns - networks: files - - protocols: db files -diff --git a/man/nss-systemd.xml b/man/nss-systemd.xml -index 34aee0e..6285b8d 100644 ---- a/man/nss-systemd.xml -+++ b/man/nss-systemd.xml -@@ -65,7 +65,7 @@ - group: compat [SUCCESS=merge] systemd - shadow: compat - --hosts: mymachines resolve [!UNAVAIL=return] myhostname files dns -+hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns - networks: files - - protocols: db files -diff --git a/man/org.freedesktop.LogControl1.xml b/man/org.freedesktop.LogControl1.xml -index d8ce392..1fdfb89 100644 ---- a/man/org.freedesktop.LogControl1.xml -+++ b/man/org.freedesktop.LogControl1.xml -@@ -24,8 +24,8 @@ - Introduction - - org.freedesktop.LogControl1 is a generic interface that is intended -- to be used by any daemon which should allow setting the log level and target over D-Bus. It is implemented -- by various daemons that are part of the -+ to be used by any daemon which allows the log level and target to be set over D-Bus. It is implemented by -+ various daemons that are part of the - systemd1 suite. - - It is assumed that those settings are global for the whole program, so a fixed object path is -@@ -75,7 +75,7 @@ node /org/freedesktop/LogControl1 { - Properties - - LogLevel describes the -- syslog3-style -+ syslog3-style - log-level, and should be one of emerg, alert, - crit, err, warning, notice, - info, debug, in order of increasing verbosity. -@@ -86,21 +86,44 @@ node /org/freedesktop/LogControl1 { - journal (log to the journal natively, see - systemd-journald.service8), - syslog (log using the -- syslog3 call). -+ syslog3 call). - - - Those two properties are writable, so they may be set by sufficiently privileged users. - - SyslogIdentifier is a read-only property that shows the "syslog identifier". - It is a short string that identifies the program that is the source of log messages that is passed to -- the syslog3 call. -+ the syslog3 call. - -- -- Note: journalctl option / may -- be used to filter log messages by log level, option / -- may be used to by the syslog identifier, and filters like _TRANSPORT=syslog, -- _TRANSPORT=journal, and _TRANSPORT=kernel may be used to filter -- messages by the mechanism through which they reached systemd-journald. - - -+ -+ -+ Tools -+ -+ journalctl option / may be used -+ to filter log messages by log level, option / may be -+ used to by the syslog identifier, and filters like _TRANSPORT=syslog, -+ _TRANSPORT=journal, and _TRANSPORT=kernel may be used to filter -+ messages by the mechanism through which they reached systemd-journald. -+ -+ systemctl log-level and systemctl log-target verbs may be -+ used to query and set the LogLevel and LogTarget properties of the -+ service manager. systemctl service-log-level and systemctl -+ service-log-target may similarly be used for individual services. (Services must have the -+ BusName= property set and must implement the interface described here. See -+ systemd.service5 -+ for details about BusName=.) -+ -+ -+ -+ See Also -+ -+ systemd1, -+ journalctl1, -+ systemctl1, -+ systemd.service5, -+ syslog3 -+ -+ - -diff --git a/man/org.freedesktop.home1.xml b/man/org.freedesktop.home1.xml -index 5cf1159..73f8682 100644 ---- a/man/org.freedesktop.home1.xml -+++ b/man/org.freedesktop.home1.xml -@@ -165,7 +165,7 @@ node /org/freedesktop/home1 { - - GetHomeByName() returns basic user information (a minimal subset of the full - user record), provided a user name. The information supplied more or less matches what -- getpwnam3 returns: -+ getpwnam3 returns: - the numeric UID and GID, the real name, home directory and shell. In addition it returns a state - identifier describing the state the user's home directory is in, as well as a bus path referring to the - bus object encapsulating the user record and home directory. This object implements the -diff --git a/man/org.freedesktop.login1.xml b/man/org.freedesktop.login1.xml -index 1b7c3b6..7e127ef 100644 ---- a/man/org.freedesktop.login1.xml -+++ b/man/org.freedesktop.login1.xml -@@ -567,7 +567,7 @@ node /org/freedesktop/login1 { - - SetWallMessage() sets the wall message (the message that will be sent out to - all terminals and stored in a -- utmp5 record) for a -+ utmp5 record) for a - subsequent scheduled shutdown operation. The parameter wall_message specifies the - shutdown reason (and may be empty) which will be included in the shutdown message. The parameter - enable specifies whether to print a wall message on shutdown. -@@ -1224,7 +1224,7 @@ node /org/freedesktop/login1/session/1 { - signals (or after an internal timeout) are automatically completed by - systemd-logind asynchronously. - -- SetLockedHint() may be used to set the "idle hint" to -+ SetLockedHint() may be used to set the "locked hint" to - locked, i.e. information whether the session is locked. This is intended to be used - by the desktop environment to tell systemd-logind when the session is locked and - unlocked. -diff --git a/man/org.freedesktop.machine1.xml b/man/org.freedesktop.machine1.xml -index a54fa04..da4738b 100644 ---- a/man/org.freedesktop.machine1.xml -+++ b/man/org.freedesktop.machine1.xml -@@ -368,7 +368,7 @@ node /org/freedesktop/machine1 { - - OpenMachinePTY() allocates a pseudo TTY in the container and returns a file - descriptor and its path. This is equivalent to transitioning into the container and invoking -- posix_openpt3. -+ posix_openpt3. - - - OpenMachineLogin() allocates a pseudo TTY in the container and ensures that -diff --git a/man/org.freedesktop.resolve1.xml b/man/org.freedesktop.resolve1.xml -index 96e22c6..5b8acbb 100644 ---- a/man/org.freedesktop.resolve1.xml -+++ b/man/org.freedesktop.resolve1.xml -@@ -86,6 +86,8 @@ node /org/freedesktop/resolve1 { - out o path); - SetLinkDNS(in i ifindex, - in a(iay) addresses); -+ SetLinkDNSEx(in i ifindex, -+ in a(iayqs) addresses); - SetLinkDomains(in i ifindex, - in a(sb) domains); - SetLinkDefaultRoute(in i ifindex, -@@ -122,9 +124,13 @@ node /org/freedesktop/resolve1 { - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly s DNSOverTLS = '...'; - readonly a(iiay) DNS = [...]; -+ readonly a(iiayqs) DNSEx = [...]; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly a(iiay) FallbackDNS = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(iiayqs) FallbackDNSEx = [...]; - readonly (iiay) CurrentDNSServer = ...; -+ readonly (iiayqs) CurrentDNSServerEx = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly a(isb) Domains = [...]; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") -@@ -148,6 +154,8 @@ node /org/freedesktop/resolve1 { - }; - - -+ -+ - - - -@@ -166,10 +174,16 @@ node /org/freedesktop/resolve1 { - - - -+ -+ - - -+ -+ - - -+ -+ - - - -@@ -194,6 +208,8 @@ node /org/freedesktop/resolve1 { - - - -+ -+ - - - -@@ -230,10 +246,16 @@ node /org/freedesktop/resolve1 { - - - -+ -+ - - -+ -+ - - -+ -+ - - - -@@ -547,6 +569,7 @@ node /org/freedesktop/resolve1/link/_1 { - interface org.freedesktop.resolve1.Link { - methods: - SetDNS(in a(iay) addresses); -+ SetDNSEx(in a(iayqs) addresses); - SetDomains(in a(sb) domains); - SetDefaultRoute(in b enable); - SetLLMNR(in s mode); -@@ -561,8 +584,12 @@ node /org/freedesktop/resolve1/link/_1 { - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly a(iay) DNS = [...]; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") -+ readonly a(iayqs) DNSEx = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly (iay) CurrentDNSServer = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") -+ readonly (iayqs) CurrentDNSServerEx = ...; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly a(sb) Domains = [...]; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly b DefaultRoute = ...; -@@ -585,6 +612,8 @@ node /org/freedesktop/resolve1/link/_1 { - }; - - -+ -+ - - - -@@ -601,8 +630,12 @@ node /org/freedesktop/resolve1/link/_1 { - - - -+ -+ - - -+ -+ - - - -@@ -623,6 +656,8 @@ node /org/freedesktop/resolve1/link/_1 { - - - -+ -+ - - - -@@ -643,8 +678,12 @@ node /org/freedesktop/resolve1/link/_1 { - - - -+ -+ - - -+ -+ - - - -diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml -index 6b16ae1..3d83324 100644 ---- a/man/org.freedesktop.systemd1.xml -+++ b/man/org.freedesktop.systemd1.xml -@@ -138,6 +138,7 @@ node /org/freedesktop/systemd1 { - CancelJob(in u id); - ClearJobs(); - ResetFailed(); -+ SetShowStatus(in s mode); - ListUnits(out a(ssssssouso) units); - ListUnitsFiltered(in as states, - out a(ssssssouso) units); -@@ -178,6 +179,13 @@ node /org/freedesktop/systemd1 { - DisableUnitFiles(in as files, - in b runtime, - out a(sss) changes); -+ EnableUnitFilesWithFlags(in as files, -+ in t flags, -+ out b carries_install_info, -+ out a(sss) changes); -+ DisableUnitFilesWithFlags(in as files, -+ in t flags, -+ out a(sss) changes); - ReenableUnitFiles(in as files, - in b runtime, - in b force, -@@ -505,6 +513,8 @@ node /org/freedesktop/systemd1 { - - - -+ -+ - - - -@@ -781,6 +791,8 @@ node /org/freedesktop/systemd1 { - - - -+ -+ - - - -@@ -831,6 +843,10 @@ node /org/freedesktop/systemd1 { - - - -+ -+ -+ -+ - - - -@@ -1287,6 +1303,20 @@ node /org/freedesktop/systemd1 { - Similarly, DisableUnitFiles() disables one or more units in the system, - i.e. removes all symlinks to them in /etc and /run. - -+ The EnableUnitFilesWithFlags() and DisableUnitFilesWithFlags() -+ take in options as flags instead of booleans to allow for extendability, defined as follows: -+ -+ -+#define SD_SYSTEMD_UNIT_RUNTIME (UINT64_C(1) << 0) -+#define SD_SYSTEMD_UNIT_FORCE (UINT64_C(1) << 1) -+#define SD_SYSTEMD_UNIT_PORTABLE (UINT64_C(1) << 2) -+ -+ -+ SD_SYSTEMD_UNIT_RUNTIME will enable or disable the unit for runtime only, -+ SD_SYSTEMD_UNIT_FORCE controls whether symlinks pointing to other units shall be -+ replaced if necessary. SD_SYSTEMD_UNIT_PORTABLE will add or remove the symlinks in -+ /etc/systemd/system.attached and /run/systemd/system.attached. -+ - Similarly, ReenableUnitFiles() applies the changes to one or more units that - would result from disabling and enabling the unit quickly one after the other in an atomic - fashion. This is useful to apply updated [Install] information contained in unit files. -@@ -1475,6 +1505,7 @@ node /org/freedesktop/systemd1 { - RestartUnit() and similar, SetProperty()) require - org.freedesktop.systemd1.manage-units. Operations which modify unit file - enablement state (EnableUnitFiles(), DisableUnitFiles(), -+ EnableUnitFilesWithFlags(), DisableUnitFilesWithFlags(), - ReenableUnitFiles(), LinkUnitFiles(), - PresetUnitFiles, MaskUnitFiles, and similar) require - org.freedesktop.systemd1.manage-unit-files. Operations which modify the -@@ -2183,8 +2214,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t TimeoutAbortUSec = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -- readonly t RuntimeMaxUSec = ...; -+ readonly s TimeoutStartFailureMode = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s TimeoutStopFailureMode = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly t RuntimeMaxUSec = ...; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t WatchdogUSec = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("false") - readonly t WatchdogTimestamp = ...; -@@ -2460,6 +2495,20 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s RootImage = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ss) RootImageOptions = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly ay RootHash = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootHashPath = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly ay RootHashSignature = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootHashSignaturePath = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootVerity = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ssba(ss)) MountImages = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly i OOMScoreAdjust = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly t CoredumpFilter = ...; -@@ -2544,6 +2593,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b RemoveIPC = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(say) SetCredential = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ss) LoadCredential = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly as SupplementaryGroups = ['...', ...]; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s PAMName = '...'; -@@ -2650,6 +2703,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s KeyringMode = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s ProtectProc = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s ProcSubset = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b ProtectHostname = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s NetworkNamespacePath = '...'; -@@ -2689,11 +2746,9 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - -- -- -- -+ - -- -+ - - - -@@ -2947,6 +3002,20 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -3027,6 +3096,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - -+ -+ -+ -+ - - - -@@ -3131,6 +3204,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - -+ -+ -+ -+ - - - -@@ -3179,6 +3256,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - -+ -+ -+ -+ - - - -@@ -3473,6 +3554,20 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -3557,6 +3652,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - -+ -+ -+ -+ - - - -@@ -3663,6 +3762,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - - - -+ -+ -+ -+ - - - -@@ -3689,6 +3792,18 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { - Most properties of the Service interface map directly to the corresponding settings in service - unit files. For the sake of brevity, here's a list of all exceptions only: - -+ TimeoutStartUSec, TimeoutStopUSec and -+ TimeoutAbortUSec contain the start, stop and abort timeouts, in microseconds. Note -+ the slight difference in naming when compared to the matching unit file settings (see -+ systemd.service7): -+ these bus properties strictly use microseconds (and thus are suffixed …USec) while -+ the unit file settings default to a time unit of seconds (and thus are suffixed -+ …Sec), unless a different unit is explicitly specified. This reflects that fact that -+ internally the service manager deals in microsecond units only, and the bus properties are a relatively -+ low-level (binary) concept exposing this. The unit file settings on the other hand are relatively -+ high-level (string-based) concepts and thus support more user friendly time specifications which -+ default to second time units but allow other units too, if specified. -+ - WatchdogTimestamp and WatchdogTimestampMonotonic contain - CLOCK_REALTIME/CLOCK_MONOTONIC microsecond timestamps of the - last watchdog ping received from the service, or 0 if none was ever received. -@@ -3789,6 +3904,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b Accept = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly b FlushPending = ...; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b Writable = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b KeepAlive = ...; -@@ -3825,6 +3942,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b PassSecurity = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly b PassPacketInfo = ...; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b RemoveOnStop = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly a(ss) Listen = [...]; -@@ -4077,6 +4196,20 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s RootImage = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ss) RootImageOptions = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly ay RootHash = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootHashPath = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly ay RootHashSignature = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootHashSignaturePath = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootVerity = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ssba(ss)) MountImages = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly i OOMScoreAdjust = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly t CoredumpFilter = ...; -@@ -4161,6 +4294,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b RemoveIPC = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(say) SetCredential = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ss) LoadCredential = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly as SupplementaryGroups = ['...', ...]; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s PAMName = '...'; -@@ -4267,6 +4404,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s KeyringMode = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s ProtectProc = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s ProcSubset = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b ProtectHostname = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s NetworkNamespacePath = '...'; -@@ -4348,6 +4489,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - -+ -+ - - - -@@ -4586,6 +4729,20 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -4666,6 +4823,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - -+ -+ -+ -+ - - - -@@ -4770,6 +4931,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - -+ -+ -+ -+ - - - -@@ -4820,6 +4985,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - -+ -+ - - - -@@ -4856,6 +5023,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - -+ -+ - - - -@@ -5112,6 +5281,20 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -5196,6 +5379,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - -+ -+ -+ -+ - - - -@@ -5302,6 +5489,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - - - -+ -+ -+ -+ - - - -@@ -5347,6 +5538,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket { - meaning as they have for the corresponding field of service units (see above). In addition to that, - the value service-failed-permanent indicates that the service of this socket failed - continuously. -+ -+ FlushPending specifies whether to flush the socket -+ just before entering the listening state. This setting only applies to sockets with -+ Accept= set to no. - - - -@@ -5442,6 +5637,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { - readonly b LazyUnmount = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b ForceUnmount = ...; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly b ReadWriteOnly = ...; - readonly s Result = '...'; - readonly u UID = ...; - readonly u GID = ...; -@@ -5652,6 +5849,20 @@ node /org/freedesktop/systemd1/unit/home_2emount { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s RootImage = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ss) RootImageOptions = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly ay RootHash = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootHashPath = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly ay RootHashSignature = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootHashSignaturePath = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootVerity = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ssba(ss)) MountImages = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly i OOMScoreAdjust = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly t CoredumpFilter = ...; -@@ -5736,6 +5947,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b RemoveIPC = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(say) SetCredential = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ss) LoadCredential = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly as SupplementaryGroups = ['...', ...]; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s PAMName = '...'; -@@ -5842,6 +6057,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s KeyringMode = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s ProtectProc = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s ProcSubset = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b ProtectHostname = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s NetworkNamespacePath = '...'; -@@ -5889,6 +6108,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - -+ -+ - - - -@@ -6091,6 +6312,20 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -6171,6 +6406,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - -+ -+ -+ -+ - - - -@@ -6275,6 +6514,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - -+ -+ -+ -+ - - - -@@ -6327,6 +6570,8 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - -+ -+ - - - -@@ -6539,6 +6784,20 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -6623,6 +6882,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - -+ -+ -+ -+ - - - -@@ -6729,6 +6992,10 @@ node /org/freedesktop/systemd1/unit/home_2emount { - - - -+ -+ -+ -+ - - - -@@ -7200,6 +7467,20 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s RootImage = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ss) RootImageOptions = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly ay RootHash = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootHashPath = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly ay RootHashSignature = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootHashSignaturePath = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s RootVerity = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ssba(ss)) MountImages = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly i OOMScoreAdjust = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly t CoredumpFilter = ...; -@@ -7284,6 +7565,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b RemoveIPC = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(say) SetCredential = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly a(ss) LoadCredential = [...]; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly as SupplementaryGroups = ['...', ...]; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s PAMName = '...'; -@@ -7390,6 +7675,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s KeyringMode = '...'; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s ProtectProc = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly s ProcSubset = '...'; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b ProtectHostname = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly s NetworkNamespacePath = '...'; -@@ -7627,6 +7916,20 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - - -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -7707,6 +8010,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - - -+ -+ -+ -+ - - - -@@ -7811,6 +8118,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - - -+ -+ -+ -+ - - - -@@ -8063,6 +8374,20 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - - -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -8147,6 +8472,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - - -+ -+ -+ -+ - - - -@@ -8253,6 +8582,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - - -+ -+ -+ -+ - - - -@@ -8278,15 +8611,15 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap { - - Most of the properties map directly to the corresponding settings in swap unit files. As mount - units invoke the -- swapon8 command, -+ swapon8 command, - their bus objects include implicit ExecActivate (and similar) fields which contain - information about processes to execute. They also share most of the fields related to the execution - context that Service objects expose (see above). In addition to these properties there are the - following: - - ControlPID contains the PID of the currently running -- swapon8 or -- swapoff8 -+ swapon8 or -+ swapoff8 - command if there is one running, otherwise 0. - - Result contains a value explaining why a mount unit failed if it failed. It -@@ -8778,7 +9111,7 @@ node /org/freedesktop/systemd1/unit/system_2eslice { - - Scope Unit Objects - -- All slice unit objects implement the org.freedesktop.systemd1.Scope -+ All scope unit objects implement the org.freedesktop.systemd1.Scope - interface (described here) in addition to the generic - org.freedesktop.systemd1.Unit interface (see above). - -@@ -8945,8 +9278,6 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope { - - - -- -- - - - -diff --git a/man/repart.d.xml b/man/repart.d.xml -index 1b104e7..9714a36 100644 ---- a/man/repart.d.xml -+++ b/man/repart.d.xml -@@ -55,11 +55,11 @@ - partition slot greater than the highest slot number currently in use. Any existing partitions that have - no matching partition file are left as they are. - -- Note that these partition definition files do not describe the contents of the partitions, such as -- the file system used. Separate mechanisms, such as -- systemd-growfs8 and -- systemd-makefs maybe be used to initialize or grow the file systems inside of these -- partitions. -+ Note that these definitions may only be used to created and initialize new partitions or grow -+ existing ones. In the latter case it will not grow the contained files systems however; separate -+ mechanisms, such as -+ systemd-growfs8 may be -+ used to grow the file systems inside of these partitions. - - - -@@ -327,7 +327,72 @@ - data is never overwritten. Note that the data is copied in before the partition table is updated, - i.e. before the partition actually is persistently created. This provides robustness: it is - guaranteed that the partition either doesn't exist or exists fully populated; it is not possible that -- the partition exists but is not or only partially populated. -+ the partition exists but is not or only partially populated. -+ -+ This option cannot be combined with Format= or -+ CopyFiles=. -+ -+ -+ -+ Format= -+ -+ Takes a file system name, such as ext4, btrfs, -+ xfs or vfat, or the special value swap. If -+ specified and the partition is newly created it is formatted with the specified file system (or as -+ swap device). The file system UUID and label are automatically derived from the partition UUID and -+ label. If this option is used, the size allocation algorithm is slightly altered: the partition is -+ created as least as big as required for the minimal file system of the specified type (or 4KiB if the -+ minimal size is not known). -+ -+ This option has no effect if the partition already exists. -+ -+ Similar to the behaviour of CopyBlocks= the file system is formatted before -+ the partition is created, ensuring that the partition only ever exists with a fully initialized -+ file system. -+ -+ This option cannot be combined with CopyBlocks=. -+ -+ -+ -+ CopyFiles= -+ -+ Takes a pair of colon separated absolute file system paths. The first path refers to -+ a source file or directory on the host, the second path refers to a target in the file system of the -+ newly created partition and formatted file system. This setting may be used to copy files or -+ directories from the host into the file system that is created due to the Format= -+ option. If CopyFiles= is used without Format= specified -+ explicitly, Format= with a suitable default is implied (currently -+ ext4, but this may change in the future). This option may be used multiple times -+ to copy multiple files or directories from host into the newly formatted file system. The colon and -+ second path may be omitted in which case the source path is also used as the target path (relative to -+ the root of the newly created file system). If the source path refers to a directory it is copied -+ recursively. -+ -+ This option has no effect if the partition already exists: it cannot be used to copy additional -+ files into an existing partition, it may only be used to populate a file system created anew. -+ -+ The copy operation is executed before the file system is registered in the partition table, -+ thus ensuring that a file system populated this way only ever exists fully initialized. -+ -+ This option cannot be combined with CopyBlocks=. -+ -+ -+ -+ Encrypt= -+ -+ Takes a boolean parameter, defaulting to false. If true the partition will be -+ formatted with a LUKS2 superblock, before the blocks configured with CopyBlocks= -+ are copied in or the file system configured with Format= is created. -+ -+ The LUKS2 UUID is automatically derived from the partition UUID in a stable fashion. A single -+ key is added to the LUKS2 superblock, configurable with the switch to -+ systemd-repart. -+ -+ When used this slightly alters the size allocation logic as the implicit, minimal size limits -+ of Format= and CopyBlocks= are increased by the space necessary -+ for the LUKS2 superblock (see above). -+ -+ This option has no effect if the partition already exists. - - - -diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml -index 535a23f..2cefc40 100644 ---- a/man/resolved.conf.xml -+++ b/man/resolved.conf.xml -@@ -63,7 +63,7 @@ - - FallbackDNS= - A space-separated list of IPv4 and IPv6 addresses to use as the fallback DNS servers. Please see -- DNS= for acceptable format of adddresses. Any per-link DNS servers obtained from -+ DNS= for acceptable format of addresses. Any per-link DNS servers obtained from - systemd-networkd.service8 - take precedence over this setting, as do any servers set via DNS= above or - /etc/resolv.conf. This setting is hence only used if no other DNS server information is -@@ -269,6 +269,31 @@ - in use. - - -+ -+ DNSStubListenerExtra= -+ Takes an IPv4 or IPv6 address to listen on. The address may be optionally -+ prefixed with a protocol name (udp or tcp) separated with -+ :. If the protocol is not specified, the service will listen on both UDP and -+ TCP. It may be also optionally suffixed by a numeric port number with separator -+ :. When an IPv6 address is specified with a port number, then the address -+ must be in the square brackets. If the port is not specified, then the service uses port 53. -+ Note that this is independent of the primary DNS stub configured with -+ DNSStubListener=, and only configures additional -+ sockets to listen on. This option can be specified multiple times. If an empty string is -+ assigned, then the all previous assignments are cleared. Defaults to unset. -+ -+ Examples: -+ DNSStubListenerExtra=192.168.10.10 -+DNSStubListenerExtra=2001:db8:0:f102::10 -+DNSStubListenerExtra=192.168.10.11:9953 -+DNSStubListenerExtra=[2001:db8:0:f102::11]:9953 -+DNSStubListenerExtra=tcp:192.168.10.12 -+DNSStubListenerExtra=udp:2001:db8:0:f102::12 -+DNSStubListenerExtra=tcp:192.168.10.13:9953 -+DNSStubListenerExtra=udp:[2001:db8:0:f102::13]:9953 -+ -+ -+ - - ReadEtcHosts= - Takes a boolean argument. If yes (the default), -diff --git a/man/rules/meson.build b/man/rules/meson.build -index 3fb454f..c702d88 100644 ---- a/man/rules/meson.build -+++ b/man/rules/meson.build -@@ -63,7 +63,7 @@ manpages = [ - ['repart.d', '5', [], 'ENABLE_REPART'], - ['resolvectl', '1', ['resolvconf'], 'ENABLE_RESOLVE'], - ['resolved.conf', '5', ['resolved.conf.d'], 'ENABLE_RESOLVE'], -- ['runlevel', '8', [], ''], -+ ['runlevel', '8', [], 'HAVE_SYSV_COMPAT'], - ['sd-bus-errors', - '3', - ['SD_BUS_ERROR_ACCESS_DENIED', -@@ -241,6 +241,8 @@ manpages = [ - 'sd_bus_error_free', - 'sd_bus_error_get_errno', - 'sd_bus_error_has_name', -+ 'sd_bus_error_has_names', -+ 'sd_bus_error_has_names_sentinel', - 'sd_bus_error_is_set', - 'sd_bus_error_move', - 'sd_bus_error_set', -@@ -785,7 +787,7 @@ manpages = [ - ['shutdown', '8', [], ''], - ['sysctl.d', '5', [], ''], - ['systemctl', '1', [], ''], -- ['systemd-analyze', '1', [], ''], -+ ['systemd-analyze', '1', [], 'ENABLE_ANALYZE'], - ['systemd-ask-password-console.service', - '8', - ['systemd-ask-password-console.path', -@@ -818,6 +820,7 @@ manpages = [ - ['systemd-debug-generator', '8', [], ''], - ['systemd-delta', '1', [], ''], - ['systemd-detect-virt', '1', [], ''], -+ ['systemd-dissect', '1', [], 'HAVE_BLKID'], - ['systemd-environment-d-generator', - '8', - ['30-systemd-environment-d-generator'], -@@ -830,7 +833,7 @@ manpages = [ - ''], - ['systemd-fstab-generator', '8', [], ''], - ['systemd-getty-generator', '8', [], ''], -- ['systemd-gpt-auto-generator', '8', [], ''], -+ ['systemd-gpt-auto-generator', '8', [], 'HAVE_BLKID'], - ['systemd-halt.service', - '8', - ['systemd-kexec.service', -@@ -911,7 +914,7 @@ manpages = [ - '8', - ['systemd-random-seed'], - 'ENABLE_RANDOMSEED'], -- ['systemd-rc-local-generator', '8', [], ''], -+ ['systemd-rc-local-generator', '8', [], 'HAVE_SYSV_COMPAT'], - ['systemd-remount-fs.service', '8', ['systemd-remount-fs'], ''], - ['systemd-repart', '8', ['systemd-repart.service'], 'ENABLE_REPART'], - ['systemd-resolved.service', '8', ['systemd-resolved'], 'ENABLE_RESOLVE'], -@@ -1009,7 +1012,7 @@ manpages = [ - ['systemd.timer', '5', [], ''], - ['systemd.unit', '5', [], ''], - ['sysusers.d', '5', [], 'ENABLE_SYSUSERS'], -- ['telinit', '8', [], ''], -+ ['telinit', '8', [], 'HAVE_SYSV_COMPAT'], - ['timedatectl', '1', [], 'ENABLE_TIMEDATECTL'], - ['timesyncd.conf', '5', ['timesyncd.conf.d'], 'ENABLE_TIMESYNCD'], - ['tmpfiles.d', '5', [], ''], -diff --git a/man/runlevel.xml b/man/runlevel.xml -index 87e2ed2..75a572c 100644 ---- a/man/runlevel.xml -+++ b/man/runlevel.xml -@@ -3,7 +3,7 @@ - "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> - - -- - - -@@ -159,5 +159,4 @@ - systemctl1 - - -- - -diff --git a/man/sd_bus_error.xml b/man/sd_bus_error.xml -index 8616f7e..3ce375b 100644 ---- a/man/sd_bus_error.xml -+++ b/man/sd_bus_error.xml -@@ -31,6 +31,8 @@ - sd_bus_error_move - sd_bus_error_is_set - sd_bus_error_has_name -+ sd_bus_error_has_names_sentinel -+ sd_bus_error_has_names - - sd-bus error handling - -@@ -128,6 +130,16 @@ - const sd_bus_error *e - const char *name - -+ -+ -+ int sd_bus_error_has_names_sentinel -+ const sd_bus_error *e -+ ... -+ -+ -+ -+ #define sd_bus_error_has_names(e, ...) sd_bus_error_has_names_sentinel(e, ..., NULL) -+ - - - -@@ -268,6 +280,12 @@ - name has been set, - false otherwise. - -+ sd_bus_error_has_names_sentinel() is similar to -+ sd_bus_error_has_name(), but takes multiple names to check against. The list must be -+ terminated with NULL. sd_bus_error_has_names() -+ is a macro wrapper around sd_bus_error_has_names_sentinel() that adds the -+ NULL sentinel automatically. -+ - sd_bus_error_free() will destroy - resources held by e. The parameter itself - will not be deallocated, and must be name field are - non-NULL, zero otherwise. - -- sd_bus_error_has_name() returns a -- non-zero value when e is -- non-NULL and the -- name field is equal to -- name, zero otherwise. -+ sd_bus_error_has_name(), sd_bus_error_has_names(), and -+ sd_bus_error_has_names_sentinel() return a non-zero value when e is -+ non-NULL and the name field is equal to one of the given -+ names, zero otherwise. - - - -diff --git a/man/sd_bus_message_append.xml b/man/sd_bus_message_append.xml -index 5faadd6..7f92359 100644 ---- a/man/sd_bus_message_append.xml -+++ b/man/sd_bus_message_append.xml -@@ -146,8 +146,10 @@ - - - -- For types "s" and "g" (unicode string or signature), the pointer may be -- NULL, which is equivalent to an empty string. See -+ For types s and g (unicode string or signature), the pointer -+ may be NULL, which is equivalent to an empty string. For h (UNIX -+ file descriptor), the descriptor is duplicated by this call and the passed descriptor stays in possession -+ of the caller. See - sd_bus_message_append_basic3 - for the precise interpretation of those and other types. - -diff --git a/man/sd_bus_message_open_container.xml b/man/sd_bus_message_open_container.xml -index 5a65518..64fda41 100644 ---- a/man/sd_bus_message_open_container.xml -+++ b/man/sd_bus_message_open_container.xml -@@ -80,7 +80,7 @@ - m itself if there is no parent container. - - sd_bus_message_enter_container() enters the next container of the message -- m. It behaves mostly the same as -+ m for reading. It behaves mostly the same as - sd_bus_message_open_container(). Entering a container allows reading its contents - with - sd_bus_message_read3 -@@ -89,7 +89,12 @@ - - sd_bus_message_exit_container() exits the scope of the last container entered - with sd_bus_message_enter_container(). It behaves mostly the same as -- sd_bus_message_close_container(). -+ sd_bus_message_close_container(). Note that -+ sd_bus_message_exit_container() may only be called after iterating through all -+ members of the container, i.e. reading or skipping them. Use -+ sd_bus_message_skip3 -+ to skip over felds of a container in order to be able to exit the container with -+ sd_bus_message_exit_container() without reading all members. - - - -@@ -128,6 +133,13 @@ - - Memory allocation failed. - -+ -+ -+ -EBUSY -+ -+ sd_bus_message_exit_container() was called but there are -+ unread members left in the container. -+ - - - -@@ -158,6 +170,7 @@ - sd-bus3, - sd_bus_message_append3, - sd_bus_message_read3, -+ sd_bus_message_skip3, - The D-Bus specification - - -diff --git a/man/sd_bus_message_read.xml b/man/sd_bus_message_read.xml -index 1b9f36c..2b5f100 100644 ---- a/man/sd_bus_message_read.xml -+++ b/man/sd_bus_message_read.xml -@@ -73,7 +73,10 @@ - should be read. See the table below for a complete list of allowed arguments and their types. Note that, - if the basic type is a pointer (e.g., const char * in the case of a string), the argument is - a pointer to a pointer, and also the pointer value that is written is only borrowed and the contents must -- be copied if they are to be used after the end of the messages lifetime. -+ be copied if they are to be used after the end of the messages lifetime. If the type is -+ h (UNIX file descriptor), the descriptor is not duplicated by this call and the -+ returned descriptor remains in possession of the message object, and needs to be duplicated by the caller -+ in order to keep an open reference to it after the message object is freed. - - Each argument may also be NULL, in which case the value is read and ignored. - -@@ -228,6 +231,15 @@ const char *s, *t, *u; - - sd_bus_message_read(m, "a{is}", 3, &i, &s, &j, &t, &k, &u); - -+ -+ Read a single file descriptor, and duplicate it in order to keep it open after the message is -+ freed. -+ -+ sd_bus_message *m; -+int fd, fd_copy; -+ -+sd_bus_message_read(m, "h", &fd); -+fd_copy = fcntl(fd, FD_DUPFD_CLOEXEC, 3); - - - -diff --git a/man/sd_bus_message_read_basic.xml b/man/sd_bus_message_read_basic.xml -index e1e9934..dc9f960 100644 ---- a/man/sd_bus_message_read_basic.xml -+++ b/man/sd_bus_message_read_basic.xml -@@ -52,17 +52,19 @@ - - - -- If p is not NULL, it should contain -- a pointer to an appropriate object. For example, if type -- is 'y', the object passed in p -- should have type uint8_t *. If type is -- 's', the object passed in p should -- have type const char **. Note that, if the basic type is a pointer -- (e.g., const char * in the case of a string), the pointer is only -- borrowed and the contents must be copied if they are to be used after the end -- of the messages lifetime. Similarly, during the lifetime of such a pointer, the -- message must not be modified. See the table below for a complete list of allowed -- types. -+ If p is not NULL, it should contain a pointer to an -+ appropriate object. For example, if type is 'y', the object -+ passed in p should have type uint8_t *. If -+ type is 's', the object passed in p -+ should have type const char **. Note that, if the basic type is a pointer (e.g., -+ const char * in the case of a string), the pointer is only borrowed and the contents must -+ be copied if they are to be used after the end of the messages lifetime. Similarly, during the lifetime -+ of such a pointer, the message must not be modified. If type is -+ 'h' (UNIX file descriptor), the descriptor is not duplicated by this call and the -+ returned descriptor remains in possession of the message object, and needs to be duplicated by the caller -+ in order to keep an open reference to it after the message object is freed (for example by calling -+ fcntl(fd, FD_DUPFD_CLOEXEC, 3)). See the table below for a complete list of -+ allowed types. - - - -diff --git a/man/sd_event_add_time.xml b/man/sd_event_add_time.xml -index 8d3511e..1fc24c8 100644 ---- a/man/sd_event_add_time.xml -+++ b/man/sd_event_add_time.xml -@@ -51,6 +51,17 @@ - void *userdata - - -+ -+ int sd_event_add_time_relative -+ sd_event *event -+ sd_event_source **source -+ clockid_t clock -+ uint64_t usec -+ uint64_t accuracy -+ sd_event_time_handler_t handler -+ void *userdata -+ -+ - - int sd_event_source_get_time - sd_event_source *source -@@ -63,6 +74,12 @@ - uint64_t usec - - -+ -+ int sd_event_source_set_time_relative -+ sd_event_source *source -+ uint64_t usec -+ -+ - - int sd_event_source_get_time_accuracy - sd_event_source *source -@@ -123,6 +140,11 @@ - sd_event_source_set_time(). - - -+ sd_event_add_time_relative() is like sd_event_add_time(), -+ but takes a relative time specification. It's relative to the current time of the event loop iteration, -+ as returned by -+ sd_event_now3. -+ - To destroy an event source object use - sd_event_source_unref3, - but note that the event source is only removed from the event loop -@@ -173,17 +195,21 @@ - events will be regular, while in the latter case the scheduling - latency will keep accumulating on the timer. - -- sd_event_source_get_time() retrieves -- the configured time value of an event source created -- previously with sd_event_add_time(). It takes -- the event source object and a pointer to a variable to store the -- time in, relative to the selected clock's epoch, in µs. -+ sd_event_source_get_time() retrieves the configured time value of an event -+ source created previously with sd_event_add_time() or -+ sd_event_add_time_relative(). It takes the event source object and a pointer to a -+ variable to store the time in, relative to the selected clock's epoch, in µs. The returned value is -+ relative to the epoch, even if the event source was created with a relative time via -+ sd_event_add_time_relative(). -+ -+ sd_event_source_set_time() changes the time of an event source created -+ previously with sd_event_add_time() or -+ sd_event_add_time_relative(). It takes the event source object and a time relative -+ to the selected clock's epoch, in µs. - -- sd_event_source_set_time() changes the -- time of an event source created previously with -- sd_event_add_time(). It takes the event -- source object and a time relative to the selected clock's epoch, -- in µs. -+ sd_event_source_set_time_relative() is similar to -+ sd_event_source_set_time(), but takes a time relative to the current time of the -+ event loop iteration, as returned by sd_event_now(). - - sd_event_source_get_time_accuracy() - retrieves the configured accuracy value of an event source -@@ -255,6 +281,13 @@ - - The passed event source is not a timer event source. - -+ -+ -+ -EOVERFLOW -+ -+ The passed relative time is outside of the allowed range for time values (i.e. the -+ specified value added to the current time is outside the 64 bit unsigned integer range). -+ - - - -diff --git a/man/sd_listen_fds.xml b/man/sd_listen_fds.xml -index 9a66ee3..4973718 100644 ---- a/man/sd_listen_fds.xml -+++ b/man/sd_listen_fds.xml -@@ -54,24 +54,19 @@ - (i.e. SD_LISTEN_FDS_START), the remaining - descriptors follow at 4, 5, 6, …, if any. - -- If a daemon receives more than one file descriptor, they -- will be passed in the same order as configured in the systemd -- socket unit file (see -- systemd.socket5 -- for details). Nonetheless, it is recommended to verify the correct -- socket types before using them. To simplify this checking, the -- functions -+ If a daemon receives more than one file descriptor, they will be passed in the same order as -+ configured in the systemd socket unit file (see -+ systemd.socket5 for -+ details) — if there's only one such file (see below). Nonetheless, it is recommended to verify the -+ correct socket types before using them. To simplify this checking, the functions - sd_is_fifo3, - sd_is_socket3, - sd_is_socket_inet3, -- sd_is_socket_unix3 -- are provided. In order to maximize flexibility, it is recommended -- to make these checks as loose as possible without allowing -- incorrect setups. i.e. often, the actual port number a socket is -- bound to matters little for the service to work, hence it should -- not be verified. On the other hand, whether a socket is a datagram -- or stream socket matters a lot for the most common program logics -- and should be checked. -+ sd_is_socket_unix3 are -+ provided. In order to maximize flexibility, it is recommended to make these checks as loose as possible -+ without allowing incorrect setups. i.e. often, the actual port number a socket is bound to matters little -+ for the service to work, hence it should not be verified. On the other hand, whether a socket is a -+ datagram or stream socket matters a lot for the most common program logics and should be checked. - - This function call will set the FD_CLOEXEC flag for all - passed file descriptors to avoid further inheritance to children -diff --git a/man/sd_machine_get_class.xml b/man/sd_machine_get_class.xml -index cd259c8..a8db371 100644 ---- a/man/sd_machine_get_class.xml -+++ b/man/sd_machine_get_class.xml -@@ -35,7 +35,7 @@ - - int sd_machine_get_ifindices - const char* machine -- int **ifindices -+ int **ret_ifindices - - - -@@ -53,21 +53,22 @@ - project='man-pages'>free3 - call after use. - -- sd_machine_get_ifindices() may be used -- to determine the numeric indices of the network interfaces on the -- host that are pointing towards the specified locally running -- virtual machine or container that is registered with -+ sd_machine_get_ifindices() may be used to determine the numeric indices of the -+ network interfaces on the host that are pointing towards the specified locally running virtual machine or -+ container. The vm or container must be registered with - systemd-machined.service8. -- The returned array needs to be freed with the libc free3 -- call after use. -+ The output parameter ret_ifindices may be passed as NULL when -+ the output value is not needed. The returned array needs to be freed with the libc free3 call after -+ use. - - - - Return Value - -- On success, these calls return 0 or a positive integer. On failure, these calls return a negative -- errno-style error code. -+ On success, these functions return a non-negative integer. -+ sd_machine_get_ifindices() returns the number of the relevant network interfaces. -+ On failure, these calls return a negative errno-style error code. - - - Errors -diff --git a/man/sd_seat_get_active.xml b/man/sd_seat_get_active.xml -index cf70b35..94401ca 100644 ---- a/man/sd_seat_get_active.xml -+++ b/man/sd_seat_get_active.xml -@@ -38,9 +38,9 @@ - - int sd_seat_get_sessions - const char *seat -- char ***sessions -- uid_t **uid -- unsigned int *n_uids -+ char ***ret_sessions -+ uid_t **ret_uids -+ unsigned int *ret_n_uids - - - -@@ -68,21 +68,16 @@ - free3 - call after use. - -- sd_seat_get_sessions() may be used to -- determine all sessions on the specified seat. Returns two arrays, -- one (NULL terminated) with the session -- identifiers of the sessions and one with the user identifiers of -- the Unix users the sessions belong to. An additional parameter may -- be used to return the number of entries in the latter array. This -- value is the same the return value, if the latter is nonnegative. -- The two arrays and the last parameter may be passed as -- NULL in case these values need not to be -- determined. The arrays and the strings referenced by them need to -- be freed with the libc -- free3 -- call after use. Note that instead of an empty array -- NULL may be returned and should be considered -- equivalent to an empty array. -+ sd_seat_get_sessions() may be used to determine all sessions on the specified -+ seat. Returns two arrays, one (NULL terminated) with the session identifiers of the -+ sessions and one with the user identifiers of the Unix users the sessions belong to. An additional -+ parameter may be used to return the number of entries in the latter array. This value is the same as the -+ return value if the return value is nonnegative. The output parameters may be passed as -+ NULL in case these output values are not needed. The arrays and the strings -+ referenced by them need to be freed with the libc free3 call after -+ use. Note that instead of an empty array NULL may be returned and should be -+ considered equivalent to an empty array. - - sd_seat_can_tty() may be used to - determine whether a specific seat provides TTY functionality, i.e. -diff --git a/man/systemctl.xml b/man/systemctl.xml -index 506f9ca..dc02fdc 100644 ---- a/man/systemctl.xml -+++ b/man/systemctl.xml -@@ -50,7 +50,7 @@ - The following commands are understood: - - -- Unit Commands -+ Unit Commands (Introspection and Modification) - - - -@@ -151,6 +151,196 @@ Sun 2017-02-26 20:57:49 EST 2h 3min left Sun 2017-02-26 11:56:36 EST 6h ago - - - -+ -+ is-active PATTERN -+ -+ -+ Check whether any of the specified units are active -+ (i.e. running). Returns an exit code -+ 0 if at least one is active, or -+ non-zero otherwise. Unless is -+ specified, this will also print the current unit state to -+ standard output. -+ -+ -+ -+ -+ is-failed PATTERN -+ -+ -+ Check whether any of the specified units are in a -+ "failed" state. Returns an exit code -+ 0 if at least one has failed, -+ non-zero otherwise. Unless is -+ specified, this will also print the current unit state to -+ standard output. -+ -+ -+ -+ -+ status PATTERN…|PID…] -+ -+ -+ Show terse runtime status information about one or -+ more units, followed by most recent log data from the -+ journal. If no units are specified, show system status. If -+ combined with , also show the status of -+ all units (subject to limitations specified with -+ ). If a PID is passed, show information -+ about the unit the process belongs to. -+ -+ This function is intended to generate human-readable -+ output. If you are looking for computer-parsable output, -+ use show instead. By default, this -+ function only shows 10 lines of output and ellipsizes -+ lines to fit in the terminal window. This can be changed -+ with and , -+ see above. In addition, journalctl -+ --unit=NAME or -+ journalctl -+ --user-unit=NAME use -+ a similar filter for messages and might be more -+ convenient. -+ -+ -+ systemd implicitly loads units as necessary, so just running the status will -+ attempt to load a file. The command is thus not useful for determining if something was already loaded or -+ not. The units may possibly also be quickly unloaded after the operation is completed if there's no reason -+ to keep it in memory thereafter. -+ -+ -+ -+ Example output from systemctl status -+ -+ $ systemctl status bluetooth -+● bluetooth.service - Bluetooth service -+ Loaded: loaded (/usr/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled) -+ Active: active (running) since Wed 2017-01-04 13:54:04 EST; 1 weeks 0 days ago -+ Docs: man:bluetoothd(8) -+ Main PID: 930 (bluetoothd) -+ Status: "Running" -+ Tasks: 1 -+ Memory: 648.0K -+ CPU: 435ms -+ CGroup: /system.slice/bluetooth.service -+ └─930 /usr/lib/bluetooth/bluetoothd -+ -+Jan 12 10:46:45 example.com bluetoothd[8900]: Not enough free handles to register service -+Jan 12 10:46:45 example.com bluetoothd[8900]: Current Time Service could not be registered -+Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output error (5) -+ -+ -+ The dot ("●") uses color on supported terminals to summarize the unit state at a glance. White -+ indicates an inactive or deactivating state. Red indicates a -+ failed or error state and green indicates an -+ active, reloading or activating state. -+ -+ -+ The "Loaded:" line in the output will show loaded if the unit has been loaded into -+ memory. Other possible values for "Loaded:" include: error if there was a problem -+ loading it, not-found if no unit file was found for this unit, -+ bad-setting if an essential unit file setting could not be parsed and -+ masked if the unit file has been masked. Along with showing the path to the unit file, -+ this line will also show the enablement state. Enabled commands start at boot. See the full table of -+ possible enablement states — including the definition of masked — in the documentation -+ for the is-enabled command. -+ -+ -+ The "Active:" line shows active state. The value is usually active or -+ inactive. Active could mean started, bound, plugged in, etc depending on the unit type. -+ The unit could also be in process of changing states, reporting a state of activating or -+ deactivating. A special failed state is entered when the service -+ failed in some way, such as a crash, exiting with an error code or timing out. If the failed state is -+ entered the cause will be logged for later reference. -+ -+ -+ -+ -+ -+ -+ show PATTERN…|JOB -+ -+ -+ Show properties of one or more units, jobs, or the manager itself. If no argument is specified, -+ properties of the manager will be shown. If a unit name is specified, properties of the unit are shown, and -+ if a job ID is specified, properties of the job are shown. By default, empty properties are suppressed. Use -+ to show those too. To select specific properties to show, use -+ . This command is intended to be used whenever computer-parsable output is -+ required. Use status if you are looking for formatted human-readable output. -+ -+ Many properties shown by systemctl show map directly to configuration settings of -+ the system and service manager and its unit files. Note that the properties shown by the command are -+ generally more low-level, normalized versions of the original configuration settings and expose runtime -+ state in addition to configuration. For example, properties shown for service units include the service's -+ current main process identifier as MainPID (which is runtime state), and time settings -+ are always exposed as properties ending in the …USec suffix even if a matching -+ configuration options end in …Sec, because microseconds is the normalized time unit used -+ internally by the system and service manager. -+ -+ For details about many of these properties, see the documentation of the D-Bus interface -+ backing these properties, see -+ org.freedesktop.systemd15. -+ -+ -+ -+ -+ cat PATTERN -+ -+ -+ Show backing files of one or more units. Prints the -+ "fragment" and "drop-ins" (source files) of units. Each -+ file is preceded by a comment which includes the file -+ name. Note that this shows the contents of the backing files -+ on disk, which may not match the system manager's -+ understanding of these units if any unit files were -+ updated on disk and the daemon-reload -+ command wasn't issued since. -+ -+ -+ -+ -+ help PATTERN…|PID -+ -+ -+ Show manual pages for one or more units, if -+ available. If a PID is given, the manual pages for the unit -+ the process belongs to are shown. -+ -+ -+ -+ -+ -+ list-dependencies -+ UNIT... -+ -+ -+ -+ Shows units required and wanted by the specified -+ units. This recursively lists units following the -+ Requires=, -+ Requisite=, -+ ConsistsOf=, -+ Wants=, BindsTo= -+ dependencies. If no units are specified, -+ default.target is implied. -+ -+ By default, only target units are recursively -+ expanded. When is passed, all other -+ units are recursively expanded as well. -+ -+ Options , -+ , -+ may be used to change what types of dependencies -+ are shown. -+ -+ Note that this command only lists units currently loaded into memory by the service manager. In -+ particular, this command is not suitable to get a comprehensive list at all reverse dependencies on a -+ specific unit, as it won't list the dependencies declared by units currently not loaded. -+ -+ -+ -+ -+ - - start PATTERN - -@@ -325,144 +515,6 @@ Sun 2017-02-26 20:57:49 EST 2h 3min left Sun 2017-02-26 11:56:36 EST 6h ago - processes in the unit's cgroup. - - -- -- is-active PATTERN -- -- -- Check whether any of the specified units are active -- (i.e. running). Returns an exit code -- 0 if at least one is active, or -- non-zero otherwise. Unless is -- specified, this will also print the current unit state to -- standard output. -- -- -- -- is-failed PATTERN -- -- -- Check whether any of the specified units are in a -- "failed" state. Returns an exit code -- 0 if at least one has failed, -- non-zero otherwise. Unless is -- specified, this will also print the current unit state to -- standard output. -- -- -- -- status PATTERN…|PID…] -- -- -- Show terse runtime status information about one or -- more units, followed by most recent log data from the -- journal. If no units are specified, show system status. If -- combined with , also show the status of -- all units (subject to limitations specified with -- ). If a PID is passed, show information -- about the unit the process belongs to. -- -- This function is intended to generate human-readable -- output. If you are looking for computer-parsable output, -- use show instead. By default, this -- function only shows 10 lines of output and ellipsizes -- lines to fit in the terminal window. This can be changed -- with and , -- see above. In addition, journalctl -- --unit=NAME or -- journalctl -- --user-unit=NAME use -- a similar filter for messages and might be more -- convenient. -- -- -- systemd implicitly loads units as necessary, so just running the status will -- attempt to load a file. The command is thus not useful for determining if something was already loaded or -- not. The units may possibly also be quickly unloaded after the operation is completed if there's no reason -- to keep it in memory thereafter. -- -- -- -- Example output from systemctl status -- -- $ systemctl status bluetooth --● bluetooth.service - Bluetooth service -- Loaded: loaded (/usr/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled) -- Active: active (running) since Wed 2017-01-04 13:54:04 EST; 1 weeks 0 days ago -- Docs: man:bluetoothd(8) -- Main PID: 930 (bluetoothd) -- Status: "Running" -- Tasks: 1 -- Memory: 648.0K -- CPU: 435ms -- CGroup: /system.slice/bluetooth.service -- └─930 /usr/lib/bluetooth/bluetoothd -- --Jan 12 10:46:45 example.com bluetoothd[8900]: Not enough free handles to register service --Jan 12 10:46:45 example.com bluetoothd[8900]: Current Time Service could not be registered --Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output error (5) -- -- -- The dot ("●") uses color on supported terminals to summarize the unit state at a glance. White -- indicates an inactive or deactivating state. Red indicates a -- failed or error state and green indicates an -- active, reloading or activating state. -- -- -- The "Loaded:" line in the output will show loaded if the unit has been loaded into -- memory. Other possible values for "Loaded:" include: error if there was a problem -- loading it, not-found if no unit file was found for this unit, -- bad-setting if an essential unit file setting could not be parsed and -- masked if the unit file has been masked. Along with showing the path to the unit file, -- this line will also show the enablement state. Enabled commands start at boot. See the full table of -- possible enablement states — including the definition of masked — in the documentation -- for the is-enabled command. -- -- -- The "Active:" line shows active state. The value is usually active or -- inactive. Active could mean started, bound, plugged in, etc depending on the unit type. -- The unit could also be in process of changing states, reporting a state of activating or -- deactivating. A special failed state is entered when the service -- failed in some way, such as a crash, exiting with an error code or timing out. If the failed state is -- entered the cause will be logged for later reference. -- -- -- -- -- -- show PATTERN…|JOB -- -- -- Show properties of one or more units, jobs, or the manager itself. If no argument is specified, -- properties of the manager will be shown. If a unit name is specified, properties of the unit are shown, and -- if a job ID is specified, properties of the job are shown. By default, empty properties are suppressed. Use -- to show those too. To select specific properties to show, use -- . This command is intended to be used whenever computer-parsable output is -- required. Use status if you are looking for formatted human-readable output. -- -- Many properties shown by systemctl show map directly to configuration settings of -- the system and service manager and its unit files. Note that the properties shown by the command are -- generally more low-level, normalized versions of the original configuration settings and expose runtime -- state in addition to configuration. For example, properties shown for service units include the service's -- current main process identifier as MainPID (which is runtime state), and time settings -- are always exposed as properties ending in the …USec suffix even if a matching -- configuration options end in …Sec, because microseconds is the normalized time unit used -- by the system and service manager. -- -- -- -- cat PATTERN -- -- -- Show backing files of one or more units. Prints the -- "fragment" and "drop-ins" (source files) of units. Each -- file is preceded by a comment which includes the file -- name. Note that this shows the contents of the backing files -- on disk, which may not match the system manager's -- understanding of these units if any unit files were -- updated on disk and the daemon-reload -- command wasn't issued since. -- -- - - set-property UNIT PROPERTY=VALUE - -@@ -499,13 +551,59 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err - - - -- help PATTERN…|PID -+ service-log-level SERVICE [LEVEL] - -- -- Show manual pages for one or more units, if -- available. If a PID is given, the manual pages for the unit -- the process belongs to are shown. -- -+ If the LEVEL argument is not given, print the current -+ log level as reported by service SERVICE. -+ -+ If the optional argument LEVEL is provided, then change the -+ current log level of the service to LEVEL. The log level should be a -+ typical syslog log level, i.e. a value in the range 0…7 or one of the strings -+ emerg, alert, crit, -+ err, warning, notice, -+ info, debug; see syslog3 -+ for details. -+ -+ The service must have the appropriate -+ BusName=destination property and also implement the -+ generic -+ org.freedesktop.LogControl15 -+ interface. (systemctl will use the generic D-Bus protocol to access the -+ org.freedesktop.LogControl1.LogLevel interface for the D-Bus name -+ destination.) -+ -+ -+ -+ service-log-target SERVICE [TARGET] -+ -+ If the TARGET argument is not given, print the current -+ log target as reported by service SERVICE. -+ -+ If the optional argument TARGET is provided, then change the -+ current log target of the service to TARGET. The log target should be -+ one of the strings console (for log output to the service's standard error -+ stream), kmsg (for log output to the kernel log buffer), -+ journal (for log output to -+ systemd-journald.service8 -+ using the native journal protocol), syslog (for log output to the classic -+ syslog socket /dev/log), null (for no log output -+ whatsoever) or auto (for an automatically determined choice, typically -+ equivalent to console if the service is invoked interactively, and -+ journal or syslog otherwise). -+ -+ For most services, only a small subset of log targets make sense. In particular, most -+ "normal" services should only implement console, journal, -+ and null. Anything else is only appropriate for low-level services that -+ are active in very early boot before proper logging is established. -+ -+ The service must have the appropriate -+ BusName=destination property and also implement the -+ generic -+ org.freedesktop.LogControl15 -+ interface. (systemctl will use the generic D-Bus protocol to access the -+ org.freedesktop.LogControl1.LogLevel interface for the D-Bus name -+ destination.) - - - -@@ -525,37 +623,6 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err - to be started again, use this command to make it startable again. - - -- -- -- -- list-dependencies -- UNIT... -- -- -- -- Shows units required and wanted by the specified -- units. This recursively lists units following the -- Requires=, -- Requisite=, -- ConsistsOf=, -- Wants=, BindsTo= -- dependencies. If no units are specified, -- default.target is implied. -- -- By default, only target units are recursively -- expanded. When is passed, all other -- units are recursively expanded as well. -- -- Options , -- , -- may be used to change what types of dependencies -- are shown. -- -- Note that this command only lists units currently loaded into memory by the service manager. In -- particular, this command is not suitable to get a comprehensive list at all reverse dependencies on a -- specific unit, as it won't list the dependencies declared by units currently not loaded. -- -- - - - -@@ -2134,6 +2201,20 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err - - - -+ -+ -+ -+ -+ Takes one of pretty (the default), -+ us, µs, utc. -+ Changes the format of printed timestamps. -+ pretty: Day YYYY-MM-DD HH:MM:SS TZ -+ us or µs: Day YYYY-MM-DD HH:MM:SS.UUUUUU TZ -+ utc: Day YYYY-MM-DD HH:MM:SS UTC -+ us+utc or µs+utc: Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC -+ -+ -+ - - - -diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml -index 3d6de17..c7f72ab 100644 ---- a/man/systemd-analyze.xml -+++ b/man/systemd-analyze.xml -@@ -3,7 +3,7 @@ - "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> - - -- - - -@@ -70,6 +70,12 @@ - exit-status - STATUS - -+ -+ systemd-analyze -+ OPTIONS -+ capability -+ CAPABILITY -+ - - systemd-analyze - OPTIONS -@@ -345,6 +351,30 @@ DATAERR 65 BSD - - - -+ -+ <command>systemd-analyze capability <optional><replaceable>CAPABILITY</replaceable>...</optional></command> -+ -+ This command prints a list of Linux capabilities along with their numeric IDs. See capabilities7 -+ for details. If no argument is specified the full list of capabilities known to the service manager and -+ the kernel is shown. Capabilities defined by the kernel but not known to the service manager are shown -+ as cap_???. Optionally, if arguments are specified they may refer to specific -+ cabilities by name or numeric ID, in which case only the indicated capabilities are shown in the -+ table. -+ -+ -+ <command>Show some example capability names</command> -+ -+ $ systemd-analyze capability 0 1 {30..32} -+NAME NUMBER -+cap_chown 0 -+cap_dac_override 1 -+cap_audit_control 30 -+cap_setfcap 31 -+cap_mac_override 32 -+ -+ -+ - - <command>systemd-analyze condition <replaceable>CONDITION</replaceable>...</command> - -diff --git a/man/systemd-backlight@.service.xml b/man/systemd-backlight@.service.xml -index 6e836d6..682c52e 100644 ---- a/man/systemd-backlight@.service.xml -+++ b/man/systemd-backlight@.service.xml -@@ -23,7 +23,8 @@ - - - systemd-backlight@.service -- /usr/lib/systemd/systemd-backlight -+ /usr/lib/systemd/systemd-backlight save [backlight|leds]:DEVICE -+ /usr/lib/systemd/systemd-backlight load [backlight|leds]:DEVICE - - - -diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml -index 77bdd80..ac5ffa5 100644 ---- a/man/systemd-detect-virt.xml -+++ b/man/systemd-detect-virt.xml -@@ -128,7 +128,7 @@ - - - -- Container -+ Container - openvz - OpenVZ/Virtuozzo - -@@ -172,6 +172,11 @@ - proot - proot userspace chroot/bind mount emulation - -+ -+ -+ pouch -+ Pouch Container Engine -+ - - -
-diff --git a/man/systemd-dissect.xml b/man/systemd-dissect.xml -new file mode 100644 -index 0000000..55e7076 ---- /dev/null -+++ b/man/systemd-dissect.xml -@@ -0,0 +1,253 @@ -+ -+ -+ -+ -+ -+ -+ -+ systemd-dissect -+ systemd -+ -+ -+ -+ systemd-dissect -+ 1 -+ -+ -+ -+ systemd-dissect -+ Dissect file system OS images -+ -+ -+ -+ -+ systemd-dissect OPTIONS IMAGE -+ -+ -+ systemd-dissect OPTIONS IMAGE PATH -+ -+ -+ systemd-dissect OPTIONS IMAGE PATH TARGET -+ -+ -+ systemd-dissect OPTIONS IMAGE SOURCE PATH -+ -+ -+ -+ -+ Description -+ -+ systemd-dissect is a tool for introspecting and interacting with file system OS -+ disk images. It supports four different operations: -+ -+ -+ Show general OS image information, including the image's -+ os-release5 data, -+ machine ID, partition information and more. -+ -+ Mount an OS image to a local directory. In this mode it will dissect the OS image and -+ mount the included partitions according to their designation onto a directory and possibly -+ sub-directories. -+ -+ Copy files and directories in and out of an OS image. -+ -+ -+ The tool may operate on three types of OS images: -+ -+ -+ OS disk images containing a GPT partition table envelope, with partitions marked -+ according to the Discoverable Partitions -+ Specification. -+ -+ OS disk images containing just a plain file-system without an enveloping partition -+ table. (This file system is assumed to be the root file system of the OS.) -+ -+ OS disk images containing a GPT or MBR partition table, with a single -+ partition only. (This partition is assumed to contain the root file system of the OS.) -+ -+ -+ OS images may use any kind of Linux-supported file systems. In addition they may make use of LUKS -+ disk encryption, and contain Verity integrity information. Note that qualifying OS images may be booted -+ with system-nspawn1's -+ switch, and be used as root file system for system service using the -+ RootImage= unit file setting, see -+ system.exec5. -+ -+ -+ -+ Commands -+ -+ If neither of the command switches listed below are passed the specified disk image is opened and -+ general information about the image and the contained partitions and their use is shown. -+ -+ -+ -+ -+ -+ -+ Mount the specified OS image to the specified directory. This will dissect the image, -+ determine the OS root file system — as well as possibly other partitions — and mount them to the -+ specified directory. If the OS image contains multiple partitions marked with the Discoverable Partitions Specification -+ multiple nested mounts are established. This command expects two arguments: a path to an image file -+ and a path to a directory where to mount the image. -+ -+ To unmount an OS image mounted like this use umount8's -+ switch (for recursive operation), so that the OS image and all nested partition -+ mounts are unmounted. -+ -+ When the OS image contains LUKS encrypted or Verity integrity protected file systems -+ appropriate volumes are automatically set up and marked for automatic disassembly when the image is -+ unmounted. -+ -+ The OS image may either be specified as path to an OS image stored in a regular file or may -+ refer to block device node (in the latter case the block device must be the "whole" device, i.e. not -+ a partition device). (The other supported commands described here support this, too.) -+ -+ All mounted file systems are checked with the appropriate fsck8 -+ implementation in automatic fixing mode, unless explicitly turned off () or -+ read-only operation is requested (). -+ -+ -+ -+ -+ -+ This is a shortcut for . -+ -+ -+ -+ -+ -+ -+ Copies a file or directory from the specified OS image into the specified location on -+ the host file system. Expects three arguments: a path to an image file, a source path (relative to -+ the image's root directory) and a destination path (relative to the current working directory, or an -+ absolute path, both outside of the image). If the destination path is omitted or specified as dash -+ (-), the specified file is written to standard output. If the source path in the -+ image file system refers to a regular file it is copied to the destination path. In this case access -+ mode, extended attributes and timestamps are copied as well, but file ownership is not. If the source -+ path in the image refers to a directory, it is copied to the destination path, recursively with all -+ containing files and directories. In this case the file ownership is copied too. -+ -+ -+ -+ -+ -+ -+ Copies a file or directory from the specified location in the host file system into -+ the specified OS image. Expects three arguments: a path to an image file, a source path (relative to -+ the current working directory, or an absolute path, both outside of the image) and a destination path -+ (relative to the image's root directory). If the source path is omitted or specified as dash -+ (-), the data to write is read from standard input. If the source path in the host -+ file system refers to a regular file, it is copied to the destination path. In this case access mode, -+ extended attributes and timestamps are copied as well, but file ownership is not. If the source path -+ in the host file system refers to a directory it is copied to the destination path, recursively with -+ all containing files and directories. In this case the file ownership is copied -+ too. -+ -+ As with file system checks are implicitly run before the copy -+ operation begins. -+ -+ -+ -+ MODE -+ -+ Shows output formatted as JSON. Expects one of short (for the -+ shortest possible output without any redundant whitespace or line breaks), pretty -+ (for a pretty version of the same, with indentation and line breaks) or off (to turn -+ off json output). -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Options -+ -+ The following options are understood: -+ -+ -+ -+ -+ -+ -+ Operate in read-only mode. By default will establish -+ writable mount points. If this option is specified they are established in read-only mode -+ instead. -+ -+ -+ -+ -+ -+ Turn off automatic file system checking. By default when an image is accessed for -+ writing (by or ) the file systems contained in the OS -+ image are automatically checked using the appropriate fsck8 -+ command, in automatic fixing mode. This behavior may be switched off using -+ . -+ -+ -+ -+ -+ -+ If combined with the directory to mount the OS image to is -+ created if it is missing. Note that the directory is not automatically removed when the disk image is -+ unmounted again. -+ -+ -+ -+ -+ -+ Takes one of disabled, loop, -+ all, crypto. If disabled the image is -+ accessed with empty block discarding turned off. if loop discarding is enabled if -+ operating on a regular file. If crypt discarding is enabled even on encrypted file -+ systems. If all discarding is unconditionally enabled. -+ -+ -+ -+ -+ -+ -+ -+ Configure various aspects of Verity data integrity for the OS -+ image. expects a hex-encoding top-level Verity hash to use for setting -+ up the Verity integrity protection. expects the path to a file -+ containing a PKCS#7 signature file for the hash. This signature is passed to the kernel during -+ activation, which will match it against signature keys available in the kernel -+ keyring. expects the path to a file with the Verity data to use for -+ the OS image, in case it is stored in a detached file. It is recommended to embed the Verity data -+ directly in the image, using the Verity mechanisms in the Discoverable Partitions Specification. -+ -+ -+ -+ -+ -+ -+ -+ Exit status -+ -+ On success, 0 is returned, a non-zero failure code -+ otherwise. -+ -+ -+ -+ See Also -+ -+ systemd1, -+ system-nspawn1, -+ system.exec5, -+ Discoverable Partitions Specification, -+ umount8 -+ -+ -+ -+ -diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml -index 78fdacc..7476edc 100644 ---- a/man/systemd-gpt-auto-generator.xml -+++ b/man/systemd-gpt-auto-generator.xml -@@ -1,9 +1,9 @@ -- -- -+ - - -- -+ -+ - - - systemd-gpt-auto-generator -diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml -index 69558ac..1e7e6a8 100644 ---- a/man/systemd-nspawn.xml -+++ b/man/systemd-nspawn.xml -@@ -1402,7 +1402,40 @@ - - Equivalent to . -
-+ -+ -+ -+ Credentials -+ -+ -+ -+ ID:PATH -+ ID:VALUE -+ -+ Pass a credential to the container. These two options correspond to the -+ LoadCredential= and SetCredential= settings in unit files. See -+ systemd.exec5 for -+ details about these concepts, as well as the syntax of the option's arguments. -+ -+ Note: when systemd-nspawn runs as systemd system service it can propagate -+ the credentials it received via LoadCredential=/SetCredential= -+ to the container payload. A systemd service manager running as PID 1 in the container can further -+ propagate them to the services it itself starts. It is thus possible to easily propagate credentials -+ from a parent service manager to a container manager service and from there into its payload. This -+ can even be done recursively. -+ -+ In order to embed binary data into the credential data for -+ use C-style escaping (i.e. \n to embed a newline, or \x00 to -+ embed a NUL byte. Note that the invoking shell might already apply unescaping -+ once, hence this might require double escaping!). -+ - -+ -+ -+ -+ Other -+ -+ - - - -diff --git a/man/systemd-rc-local-generator.xml b/man/systemd-rc-local-generator.xml -index 81744c2..b51f50a 100644 ---- a/man/systemd-rc-local-generator.xml -+++ b/man/systemd-rc-local-generator.xml -@@ -1,10 +1,12 @@ -- -- -+ - -+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ -+ -+%entities; -+]> - -- - -+ - - systemd-rc-local-generator - systemd -@@ -17,7 +19,7 @@ - - - systemd-rc-local-generator -- Compatibility generator for starting /etc/rc.local during boot -+ Compatibility generator for starting &RC_LOCAL_PATH; during boot - - - -@@ -28,17 +30,17 @@ - Description - - systemd-rc-local-generator is a generator that checks whether -- /etc/rc.local exists and is executable, and if it is pulls the -- rc-local.service unit into the boot process. This unit is responsible for running this script -- during late boot. Note that the script will be run with slightly different semantics than the original System V -- version, which was run "last" in the boot process, which is a concept that does not translate to systemd. The -- script is run after network.target, but in parallel with most other regular system -- services. -- -- Support for /etc/rc.local is provided -- for compatibility with specific System V systems only. However, it is strongly recommended to avoid making use of -- this script today, and instead provide proper unit files with appropriate dependencies for any scripts to run -- during the boot process. -+ &RC_LOCAL_PATH; exists and is executable, and if it is pulls the -+ rc-local.service unit into the boot process. This unit is responsible for running -+ this script during late boot. Note that the script will be run with slightly different semantics than the -+ original System V version, which was run "last" in the boot process, which is a concept that does not -+ translate to systemd. The script is run after network.target, but in parallel with -+ most other regular system services. -+ -+ Support for &RC_LOCAL_PATH; is provided for compatibility with specific System -+ V systems only. However, it is strongly recommended to avoid making use of this script today, and instead -+ provide proper unit files with appropriate dependencies for any scripts to run during the boot process. -+ Note that the path to the script is set a compile time and varies between distributions. - - systemd-rc-local-generator implements - systemd.generator7. -@@ -51,5 +53,4 @@ - systemctl1 - - -- - -diff --git a/man/systemd-repart.xml b/man/systemd-repart.xml -index ffa88ba..b234cfe 100644 ---- a/man/systemd-repart.xml -+++ b/man/systemd-repart.xml -@@ -202,13 +202,26 @@ - - - -- Takes a size in bytes, using the usual K, M, G, T suffixes. If used the specified -- device node path must refer to a regular file, which is then grown to the specified size if smaller, -- before any change is made to the partition table. This is not supported if the specified node is a -- block device. This switch has no effect if the file is already as large as the specified size or -- larger. The specified size is implicitly rounded up to multiples of 4096. When used with -- this specifies the initial size of the loopback file to -- create. -+ Takes a size in bytes, using the usual K, M, G, T suffixes, or the special value -+ auto. If used the specified device node path must refer to a regular file, which -+ is then grown to the specified size if smaller, before any change is made to the partition table. If -+ specified as auto the minimal size for the disk image is automatically determined -+ (i.e. the minimal sizes of all partitions are summed up, taking space for additional metadata into -+ account). This switch is not supported if the specified node is a block device. This switch has no -+ effect if the file is already as large as the specified size or larger. The specified size is -+ implicitly rounded up to multiples of 4096. When used with this -+ specifies the initial size of the loopback file to create. -+ -+ The option takes the sizes of pre-existing partitions into -+ account. However, it does not accommodate for partition tables that are not tightly packed: the -+ configured partitions might still not fit into the backing device if empty space exists between -+ pre-existing partitions (or before the first partition) that cannot be fully filled by partitions to -+ grow or create. -+ -+ Also note that the automatic size determination does not take files or directories specified -+ with into account: operation might fail if the specified files or -+ directories require more disk space then the configured per-partition minimal size -+ limit. - - - -@@ -265,6 +278,15 @@ - and graphic illustrating the changes applied. - - -+ -+ MODE -+ -+ Shows output formatted as JSON. Expects one of short (for the -+ shortest possible output without any redundant whitespace or line breaks), pretty -+ (for a pretty version of the same, with indentation and line breaks) or off (to turn -+ off json output). -+ -+ - - - -@@ -274,6 +296,18 @@ - /run/repart.d/*.conf. - - -+ -+ -+ -+ Takes a file system path. Configures the encryption key to use when setting up LUKS2 -+ volumes configured with the Encrypt= setting in partition files. Should refer to a -+ regular file containing the key, or an AF_UNIX stream socket in the file -+ system. In the latter case a connection is made to it and the key read from it. If this switch is not -+ specified the empty key (i.e. zero length key) is used. This behaviour is useful for setting up encrypted -+ partitions during early first boot that receive their user-supplied password only in a later setup -+ step. -+ -+ - - - -diff --git a/man/systemd-run.xml b/man/systemd-run.xml -index a88f60f..c1471e1 100644 ---- a/man/systemd-run.xml -+++ b/man/systemd-run.xml -@@ -463,11 +463,11 @@ Mon Dec 8 20:44:24 KST 2014 - Running as unit: run-71.timer - Will run service as unit: run-71.service - # journalctl -b -u run-71.timer ---- Logs begin at Fri 2014-12-05 19:09:21 KST, end at Mon 2014-12-08 20:44:54 KST. -- -+-- Journal begins at Fri 2014-12-05 19:09:21 KST, ends at Mon 2014-12-08 20:44:54 KST. -- - Dec 08 20:44:38 container systemd[1]: Starting /bin/touch /tmp/foo. - Dec 08 20:44:38 container systemd[1]: Started /bin/touch /tmp/foo. - # journalctl -b -u run-71.service ---- Logs begin at Fri 2014-12-05 19:09:21 KST, end at Mon 2014-12-08 20:44:54 KST. -- -+-- Journal begins at Fri 2014-12-05 19:09:21 KST, ends at Mon 2014-12-08 20:44:54 KST. -- - Dec 08 20:44:48 container systemd[1]: Starting /bin/touch /tmp/foo... - Dec 08 20:44:48 container systemd[1]: Started /bin/touch /tmp/foo. - -diff --git a/man/systemd-sysusers.xml b/man/systemd-sysusers.xml -index cc02625..1e5853a 100644 ---- a/man/systemd-sysusers.xml -+++ b/man/systemd-sysusers.xml -@@ -68,6 +68,19 @@ - paths. -
- -+ -+ -+ -+ Takes a path to a disk image file or block device node. If specified all operations -+ are applied to file system in the indicated disk image. This is similar to -+ but operates on file systems stored in disk images or block devices. The disk image should either -+ contain just a file system or a set of file systems within a GPT partition table, following the -+ Discoverable Partitions -+ Specification. For further information on supported disk images, see -+ systemd-nspawn1's -+ switch of the same name. -+ -+ - - - When this option is given, one ore more positional arguments -diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml -index 998fd09..ec7d12b 100644 ---- a/man/systemd-tmpfiles.xml -+++ b/man/systemd-tmpfiles.xml -@@ -75,7 +75,7 @@ - systemd-tmpfiles-clean.service) also invoke systemd-tmpfiles, but - it reads a separate set of files, which includes user-controlled files under - ~/.config/user-tmpfiles.d/ and ~/.local/share/user-tmpfiles.d/, -- and administrator-controller files under /usr/share/user-tmpfiles.d/. Users may use -+ and administrator-controlled files under /usr/share/user-tmpfiles.d/. Users may use - this to create and clean up files under their control, but the system instance performs global cleanup - and is not influenced by user configuration. Note that this means a time-based cleanup configured in the - system instance, such as the one typically configured for /tmp, will thus also -@@ -149,6 +149,7 @@ - the specified prefix. This option can be specified multiple - times. - -+ - - - Ignore rules with paths that start with the -@@ -156,6 +157,16 @@ - times. - - -+ -+ -+ A shortcut for --exclude-prefix=/dev --exclude-prefix=/proc -+ --exclude-prefix=/run --exclude-prefix=/sys, i.e. exclude the hierarchies typically backed -+ by virtual or memory file systems. This is useful in combination with , if -+ the specified directory tree contains an OS tree without these virtual/memory file systems mounted -+ in, as it is typically not desirable to create any files and directories below these subdirectories -+ if they are supposed to be overmounted during runtime. -+ -+ - - - Takes a directory path as an argument. All paths will be prefixed with the given alternate -@@ -164,7 +175,26 @@ - When this option is used, the libc Name Service Switch (NSS) is bypassed for resolving users - and groups. Instead the files /etc/passwd and /etc/group - inside the alternate root are read directly. This means that users/groups not listed in these files -- will not be resolved, i.e. LDAP NIS and other complex databases are not considered. -+ will not be resolved, i.e. LDAP NIS and other complex databases are not considered. -+ -+ Consider combining this with to ensure the invocation does not create files -+ or directories below mount points in the OS image operated on that are typically overmounted during -+ runtime. -+ -+ -+ -+ -+ -+ Takes a path to a disk image file or block device node. If specified all operations -+ are applied to file system in the indicated disk image. This is similar to -+ but operates on file systems stored in disk images or block devices. The disk image should either -+ contain just a file system or a set of file systems within a GPT partition table, following the -+ Discoverable Partitions -+ Specification. For further information on supported disk images, see -+ systemd-nspawn1's -+ switch of the same name. -+ -+ Implies . - - - -diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml -index 3618b52..d0bb5fc 100644 ---- a/man/systemd.exec.xml -+++ b/man/systemd.exec.xml -@@ -145,6 +145,61 @@ - - - -+ -+ RootImageOptions= -+ -+ Takes a comma-separated list of mount options that will be used on disk images specified by -+ RootImage=. Optionally a partition name can be prefixed, followed by colon, in -+ case the image has multiple partitions, otherwise partition name root is implied. -+ Options for multiple partitions can be specified in a single line with space separators. Assigning an empty -+ string removes previous assignments. Duplicated options are ignored. For a list of valid mount options, please -+ refer to mount8. -+ -+ Valid partition names follow the Discoverable -+ Partitions Specification. -+ -+ -+ Accepted partition names -+ -+ -+ -+ -+ -+ Partition Name -+ -+ -+ -+ -+ root -+ -+ -+ root-secondary -+ -+ -+ home -+ -+ -+ srv -+ -+ -+ esp -+ -+ -+ xbootldr -+ -+ -+ tmp -+ -+ -+ var -+ -+ -+ -+
-+ -+
-+
-+ - - RootHash= - -@@ -212,6 +267,55 @@ - - - -+ -+ ProtectProc= -+ -+ Takes one of noaccess, invisible, -+ ptraceable or default (which it defaults to). When set, this -+ controls the hidepid= mount option of the procfs instance for -+ the unit that controls which directories with process metainformation -+ (/proc/PID) are visible and accessible: when set to -+ noaccess the ability to access most of other users' process metadata in -+ /proc/ is taken away for processes of the service. When set to -+ invisible processes owned by other users are hidden from -+ /proc/. If ptraceable all processes that cannot be -+ ptrace()'ed by a process are hidden to it. If default no -+ restrictions on /proc/ access or visibility are made. For further details see -+ The /proc -+ Filesystem. It is generally recommended to run most system services with this option set to -+ invisible. This option is implemented via file system namespacing, and thus cannot -+ be used with services that shall be able to install mount points in the host file system -+ hierarchy. It also cannot be used for services that need to access metainformation about other users' -+ processes. This option implies MountAPIVFS=. -+ -+ If the kernel doesn't support per-mount point mount options this -+ setting remains without effect, and the unit's processes will be able to access and see other process -+ as if the option was not used. -+ -+ -+ -+ -+ -+ ProcSubset= -+ -+ Takes one of all (the default) and pid. If -+ the latter all files and directories not directly associated with process management and introspection -+ are made invisible in the /proc/ file system configured for the unit's -+ processes. This controls the subset= mount option of the procfs -+ instance for the unit. For further details see The /proc -+ Filesystem. Note that Linux exposes various kernel APIs via /proc/, -+ which are made unavailable with this setting. Since these APIs are used frequently this option is -+ useful only in a few, specific cases, and is not suitable for most non-trivial programs. -+ -+ Much like ProtectProc= above, this is implemented via file system mount -+ namespacing, and hence the same restrictions apply: it is only available to system services, it -+ disables mount propagation to the host mount table, and it implies -+ MountAPIVFS=. Also, like ProtectProc= this setting is gracefully -+ disabled if the used kernel does not support the subset= mount option of -+ procfs. -+ -+ - - BindPaths= - BindReadOnlyPaths= -@@ -248,6 +352,48 @@ - - - -+ -+ MountImages= -+ -+ This setting is similar to RootImage= in that it mounts a file -+ system hierarchy from a block device node or loopback file, but the destination directory can be -+ specified as well as mount options. This option expects a whitespace separated list of mount -+ definitions. Each definition consists of a colon-separated tuple of source path and destination -+ definitions, optionally followed by another colon and a list of mount options. -+ -+ Mount options may be defined as a single comma-separated list of options, in which case they -+ will be implicitly applied to the root partition on the image, or a series of colon-separated tuples -+ of partition name and mount options. Valid partition names and mount options are the same as for -+ RootImageOptions= setting described above. -+ -+ Each mount definition may be prefixed with -, in which case it will be -+ ignored when its source path does not exist. The source argument is a path to a block device node or -+ regular file. If source or destination contain a :, it needs to be escaped as -+ \:. The device node or file system image file needs to follow the same rules as -+ specified for RootImage=. Any mounts created with this option are specific to the -+ unit, and are not visible in the host's mount table. -+ -+ These settings may be used more than once, each usage appends to the unit's list of mount -+ paths. If the empty string is assigned, the entire list of mount paths defined prior to this is -+ reset. -+ -+ Note that the destination directory must exist or systemd must be able to create it. Thus, it -+ is not possible to use those options for mount points nested underneath paths specified in -+ InaccessiblePaths=, or under /home/ and other protected -+ directories if ProtectHome=yes is specified. -+ -+ When DevicePolicy= is set to closed or -+ strict, or set to auto and DeviceAllow= is -+ set, then this setting adds /dev/loop-control with rw mode, -+ block-loop and block-blkext with rwm mode -+ to DeviceAllow=. See -+ systemd.resource-control5 -+ for the details about DevicePolicy= or DeviceAllow=. Also, see -+ PrivateDevices= below, as it may change the setting of -+ DevicePolicy=. -+ -+ -+ - - - -@@ -398,22 +544,28 @@ - - CapabilityBoundingSet= - -- Controls which capabilities to include in the capability bounding set for the executed -- process. See capabilities7 for -- details. Takes a whitespace-separated list of capability names, e.g. CAP_SYS_ADMIN, -- CAP_DAC_OVERRIDE, CAP_SYS_PTRACE. Capabilities listed will be -- included in the bounding set, all others are removed. If the list of capabilities is prefixed with -- ~, all but the listed capabilities will be included, the effect of the assignment -- inverted. Note that this option also affects the respective capabilities in the effective, permitted and -- inheritable capability sets. If this option is not used, the capability bounding set is not modified on process -- execution, hence no limits on the capabilities of the process are enforced. This option may appear more than -- once, in which case the bounding sets are merged by OR, or by AND if -- the lines are prefixed with ~ (see below). If the empty string is assigned to this option, -- the bounding set is reset to the empty capability set, and all prior settings have no effect. If set to -- ~ (without any further argument), the bounding set is reset to the full set of available -- capabilities, also undoing any previous settings. This does not affect commands prefixed with -- +. -+ Controls which capabilities to include in the capability bounding set for the -+ executed process. See capabilities7 -+ for details. Takes a whitespace-separated list of capability names, -+ e.g. CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, -+ CAP_SYS_PTRACE. Capabilities listed will be included in the bounding set, all -+ others are removed. If the list of capabilities is prefixed with ~, all but the -+ listed capabilities will be included, the effect of the assignment inverted. Note that this option -+ also affects the respective capabilities in the effective, permitted and inheritable capability -+ sets. If this option is not used, the capability bounding set is not modified on process execution, -+ hence no limits on the capabilities of the process are enforced. This option may appear more than -+ once, in which case the bounding sets are merged by OR, or by -+ AND if the lines are prefixed with ~ (see below). If the -+ empty string is assigned to this option, the bounding set is reset to the empty capability set, and -+ all prior settings have no effect. If set to ~ (without any further argument), -+ the bounding set is reset to the full set of available capabilities, also undoing any previous -+ settings. This does not affect commands prefixed with +. -+ -+ Use -+ systemd-analyze1's -+ capability command to retrieve a list of capabilities defined on the local -+ system. - - Example: if a unit has the following, - CapabilityBoundingSet=CAP_A CAP_B -@@ -711,12 +863,17 @@ CapabilityBoundingSet=~CAP_B CAP_C - - Controls the file mode creation mask. Takes an access mode in octal notation. See - umask2 for -- details. Defaults to 0022 for system units. For units of the user service manager the default value -- is inherited from the user instance (whose default is inherited from the system service manager, and -- thus also is 0022). Hence changing the default value of a user instance, either via -- UMask= or via a PAM module, will affect the user instance itself and all user -- units started by the user instance unless a user unit has specified its own -- UMask=. -+ details. Defaults to 0022 for system units. For user units the default value is inherited from the -+ per-user service manager (whose default is in turn inherited from the system service manager, and -+ thus typically also is 0022 — unless overriden by a PAM module). In order to change the per-user mask -+ for all user services, consider setting the UMask= setting of the user's -+ user@.service system service instance. The per-user umask may also be set via -+ the umask field of a user's JSON User -+ Record (for users managed by -+ systemd-homed.service8 -+ this field may be controlled via homectl --umask=). It may also be set via a PAM -+ module, such as pam_umask8. - - - -@@ -890,7 +1047,8 @@ CapabilityBoundingSet=~CAP_B CAP_C - - Controls the NUMA node list which will be applied alongside with selected NUMA policy. - Takes a list of NUMA nodes and has the same syntax as a list of CPUs for CPUAffinity= -- option. Note that the list of NUMA nodes is not required for and -+ option or special "all" value which will include all available NUMA nodes in the mask. Note that the list -+ of NUMA nodes is not required for and - policies and for policy we expect a single NUMA node. - - -@@ -1730,7 +1888,8 @@ RestrictNamespaces=~cgroup net - EACCES or EUCLEAN (see errno3 for a - full list). This value will be returned when a deny-listed system call is triggered, instead of -- terminating the processes immediately. This value takes precedence over the one given in -+ terminating the processes immediately. Special setting kill can be used to -+ explicitly specify killing. This value takes precedence over the one given in - SystemCallErrorNumber=, see below. If running in user mode, or in system mode, - but without the CAP_SYS_ADMIN capability (e.g. setting - User=nobody), NoNewPrivileges=yes is implied. This feature -@@ -1884,6 +2043,10 @@ RestrictNamespaces=~cgroup net - @timer - System calls for scheduling operations by time (alarm2, timer_create2, …) - -+ -+ @known -+ All system calls defined by the kernel. This list is defined statically in systemd based on a kernel version that was available when this systmed version was released. It will become progressively more out-of-date as the kernel is updated. -+ - - - -@@ -1936,8 +2099,9 @@ SystemCallErrorNumber=EPERM - return when the system call filter configured with SystemCallFilter= is triggered, - instead of terminating the process immediately. See errno3 for a -- full list of error codes. When this setting is not used, or when the empty string is assigned, the -- process will be terminated immediately when the filter is triggered. -+ full list of error codes. When this setting is not used, or when the empty string or the special -+ setting kill is assigned, the process will be terminated immediately when the -+ filter is triggered. - - - -@@ -1972,6 +2136,21 @@ SystemCallErrorNumber=EPERM - details. - - -+ -+ SystemCallLog= -+ -+ Takes a space-separated list of system call names. If this setting is used, all -+ system calls executed by the unit processes for the listed ones will be logged. If the first -+ character of the list is ~, the effect is inverted: all system calls except the -+ listed system calls will be logged. If running in user mode, or in system mode, but without the -+ CAP_SYS_ADMIN capability (e.g. setting User=nobody), -+ NoNewPrivileges=yes is implied. This feature makes use of the Secure Computing -+ Mode 2 interfaces of the kernel ('seccomp filtering') and is useful for auditing or setting up a -+ minimal sandboxing environment. This option may be specified more than once, in which case the filter -+ masks are merged. If the empty string is assigned, the filter is reset, all prior assignments will -+ have no effect. This does not affect commands prefixed with +. -+ -+ - - - -@@ -2004,11 +2183,13 @@ SystemCallErrorNumber=EPERM - project='man-pages'>environ7 for details - about environment variables. - -- Note that environment variables are not suitable for passing secrets (such as passwords, key material, …) -- to service processes. Environment variables set for a unit are exposed to unprivileged clients via D-Bus IPC, -- and generally not understood as being data that requires protection. Moreover, environment variables are -- propagated down the process tree, including across security boundaries (such as setuid/setgid executables), and -- hence might leak to processes that should not have access to the secret data. -+ Note that environment variables are not suitable for passing secrets (such as passwords, key -+ material, …) to service processes. Environment variables set for a unit are exposed to unprivileged -+ clients via D-Bus IPC, and generally not understood as being data that requires protection. Moreover, -+ environment variables are propagated down the process tree, including across security boundaries -+ (such as setuid/setgid executables), and hence might leak to processes that should not have access to -+ the secret data. Use LoadCredential= (see below) to pass data to unit processes -+ securely. - - - -@@ -2378,7 +2559,9 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy - so that they are automatically established prior to the unit starting up. Note that when this option - is used log output of this service does not appear in the regular - journalctl1 -- output, unless the option is used. -+ output, unless the option is used. -+ -+ - - - -@@ -2472,6 +2655,73 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy - - - -+ -+ Credentials -+ -+ -+ -+ -+ LoadCredential=ID:PATH -+ -+ Pass a credential to the unit. Credentials are limited-size binary or textual objects -+ that may be passed to unit processes. They are primarily used for passing cryptographic keys (both -+ public and private) or certificates, user account information or identity information from host to -+ services. The data is accessible from the unit's processes via the file system, at a read-only -+ location that (if possible and permitted) is backed by non-swappable memory. The data is only -+ accessible to the user associated with the unit, via the -+ User=/DynamicUser= settings (as well as the superuser). When -+ available, the location of credentials is exported as the $CREDENTIALS_DIRECTORY -+ environment variable to the unit's processes. -+ -+ The LoadCredential= setting takes a textual ID to use as name for a -+ credential plus a file system path. The ID must be a short ASCII string suitable as filename in the -+ filesystem, and may be chosen freely by the user. If the specified path is absolute it is opened as -+ regular file and the credential data is read from it. If the absolute path refers to an -+ AF_UNIX stream socket in the file system a connection is made to it and the -+ credential data read from the connection, providing an easy IPC integration point for dynamically -+ providing credentials from other services. If the specified path is not absolute and itself qualifies -+ as valid credential identifier it is understood to refer to a credential that the service manager -+ itself received via the $CREDENTIALS_DIRECTORY environment variable, which may be -+ used to propagate credentials from an invoking environment (e.g. a container manager that invoked the -+ service manager) into a service. The contents of the file/socket may be arbitrary binary or textual -+ data, including newline characters and NUL bytes. This option may be used multiple times, each time -+ defining an additional credential to pass to the unit. -+ -+ The credential files/IPC sockets must be accessible to the service manager, but don't have to -+ be directly accessible to the unit's processes: the credential data is read and copied into separate, -+ read-only copies for the unit that are accessible to appropriately privileged processes. This is -+ particularly useful in combination with DynamicUser= as this way privileged data -+ can be made available to processes running under a dynamic UID (i.e. not a previously known one) -+ without having to open up access to all users. -+ -+ In order to reference the path a credential may be read from within a -+ ExecStart= command line use ${CREDENTIALS_DIRECTORY}/mycred, -+ e.g. ExecStart=cat ${CREDENTIALS_DIRECTORY}/mycred. -+ -+ Currently, an accumulated credential size limit of 1M bytes per unit is -+ enforced. -+ -+ -+ -+ SetCredential=ID:VALUE -+ -+ The SetCredential= setting is similar to -+ LoadCredential= but accepts a literal value to use as data for the credential, -+ instead of a file system path to read the data from. Do not use this option for data that is supposed -+ to be secret, as it is accessible to unprivileged processes via IPC. It's only safe to use this for -+ user IDs, public key material and similar non-sensitive data. For everything else use -+ LoadCredential=. In order to embed binary data into the credential data use -+ C-style escaping (i.e. \n to embed a newline, or \x00 to embed -+ a NUL byte). -+ -+ If a credential of the same ID is listed in both LoadCredential= and -+ SetCredential=, the latter will act as default if the former cannot be -+ retrieved. In this case not being able to retrieve the credential from the path specified in -+ LoadCredential= is not considered fatal. -+ -+ -+ -+ - - System V Compatibility - -@@ -2627,6 +2877,16 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy - - - -+ -+ $CREDENTIALS_DIRECTORY -+ -+ An absolute path to the per-unit directory with credentials configured via -+ LoadCredential=/SetCredential=. The directory is marked -+ read-only and is placed in unswappable memory (if supported and permitted), and is only accessible to -+ the UID associated with the unit via User= or DynamicUser= (and -+ the superuser). -+ -+ - - $MAINPID - -@@ -3228,7 +3488,11 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy - EXIT_NUMA_POLICY - Failed to set up unit's NUMA memory policy. See NUMAPolicy= and NUMAMask= above. - -- -+ -+ 243 -+ EXIT_CREDENTIALS -+ Failed to set up unit's credentials. See LoadCredential= and SetCredential= above. -+ - - - -diff --git a/man/systemd.network.xml b/man/systemd.network.xml -index 7798619..d0666c7 100644 ---- a/man/systemd.network.xml -+++ b/man/systemd.network.xml -@@ -408,36 +408,48 @@ - - IPv6Token= - -- Specifies an optional address generation mode and a required IPv6 address. If -- the mode is present, the two parts must be separated with a colon -- mode:address. The -- address generation mode may be either prefixstable or -- static. If not specified, static is assumed. -- -- When the mode is set to static, or unspecified, the lower bits of -- the supplied address are combined with the upper bits of a prefix received in a Router Advertisement -- message to form a complete address. Note that if multiple prefixes are received in an RA message, or in -- multiple RA messages, addresses will be formed from each of them using the supplied address. This -- mode implements SLAAC but uses a static interface identifier instead of an identifier generated -- using the EUI-64 algorithm. Because the interface identifier is static, if Duplicate Address Detection -- detects that the computed address is a duplicate (in use by another node on the link), then this -- mode will fail to provide an address for that prefix. -- -- When the mode is set to prefixstable the RFC 7217 algorithm for generating -- interface identifiers will be used, but only when a prefix received in an RA message matches the supplied address. -- See RFC 7217. Prefix matching will be attempted -- against each prefixstable IPv6Token variable provided in the configuration; if a received -- prefix does not match any of the provided addresses, then the EUI-64 algorithm will be used to form -- an interface identifier for that prefix. This mode is also SLAAC, but with a potentially stable interface -- identifier which does not directly map to the interface's hardware address. -- -- Note that the prefixstable algorithm includes both the interface's name and -- MAC address in the hash used to compute the interface identifier, so if either of those are changed the resulting -- interface identifier (and address) will change, even if the prefix received in the RA message has not changed. -- -- Note that if multiple prefixstable IPv6Token variables are supplied with addresses that -- match a prefix received in an RA message, only the first one will be used to generate addresses. -- -+ Specifies an optional address generation mode for the Stateless Address -+ Autoconfiguration (SLAAC). Supported modes are prefixstable and -+ static. -+ -+ When the mode is set to static, an IPv6 address must be -+ specified after a colon (:), and the lower bits of the supplied -+ address are combined with the upper bits of a prefix received in a Router Advertisement -+ (RA) message to form a complete address. Note that if multiple prefixes are received in an -+ RA message, or in multiple RA messages, addresses will be formed from each of them using -+ the supplied address. This mode implements SLAAC but uses a static interface identifier -+ instead of an identifier generated by using the EUI-64 algorithm. Because the interface -+ identifier is static, if Duplicate Address Detection detects that the computed address is a -+ duplicate (in use by another node on the link), then this mode will fail to provide an -+ address for that prefix. If an IPv6 address without mode is specified, then -+ static mode is assumed. -+ -+ When the mode is set to prefixstable the -+ RFC 7217 algorithm for generating -+ interface identifiers will be used. This mode can optionally take an IPv6 address separated -+ with a colon (:). If an IPv6 address is specified, then an interface -+ identifier is generated only when a prefix received in an RA message matches the supplied -+ address. -+ -+ If no address generation mode is specified (which is the default), or a received -+ prefix does not match any of the addresses provided in prefixstable -+ mode, then the EUI-64 algorithm will be used to form an interface identifier for that -+ prefix. This mode is also SLAAC, but with a potentially stable interface identifier which -+ does not directly map to the interface's hardware address. -+ -+ Note that the prefixstable algorithm uses both the interface -+ name and MAC address as input to the hash to compute the interface identifier, so if either -+ of those are changed the resulting interface identifier (and address) will change, even if -+ the prefix received in the RA message has not changed. -+ -+ This setting can be specified multiple times. If an empty string is assigned, then -+ the all previous assignments are cleared. -+ -+ Examples: -+ IPv6Token=::1a:2b:3c:4d -+IPv6Token=static:::1a:2b:3c:4d -+IPv6Token=prefixstable -+IPv6Token=prefixstable:2002:da8:1:: - - - -@@ -2526,6 +2538,26 @@ - - - -+ -+ [BridgeMDB] Section Options -+ The [BridgeMDB] section manages the multicast membership entries forwarding database table of a port and accepts the following -+ keys. Specify several [BridgeMDB] sections to configure several permanent multicast membership entries. -+ -+ -+ -+ MulticastGroupAddress= -+ -+ Specifies the IPv4 or IPv6 multicast group address to add. This setting is mandatory. -+ -+ -+ -+ VLANId= -+ -+ The VLAN ID for the new entry. Valid ranges are 0 (no VLAN) to 4094. Optional, defaults to 0. -+ -+ -+ -+ - - - [LLDP] Section Options -@@ -3533,10 +3565,7 @@ DHCP=ipv6 - Name=enp2s0 - - [Network] --IPv6PrefixDelegation=dhcpv6 -- --[DHCPv6] --AssignAcquiredDelegatedPrefixAddress=yes -+IPv6PrefixDelegation=dhcpv6 - - This will enable IPv6 PD on the interface enp1s0 as an upstream interface where the - DHCPv6 client is running and enp2s0 as a downstream interface where the prefix is delegated to. -diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml -index 3ccb5c4..d72f904 100644 ---- a/man/systemd.resource-control.xml -+++ b/man/systemd.resource-control.xml -@@ -261,53 +261,42 @@ - - - -- MemoryMin=bytes -+ MemoryMin=bytes, MemoryLow=bytes - - -- Specify the memory usage protection of the executed processes in this unit. If the memory usages of -- this unit and all its ancestors are below their minimum boundaries, this unit's memory won't be reclaimed. -- -- Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is -- parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a -- percentage value may be specified, which is taken relative to the installed physical memory on the -- system. If assigned the special value infinity, all available memory is protected, which may be -- useful in order to always inherit all of the protection afforded by ancestors. -- This controls the memory.min control group attribute. For details about this -- control group attribute, see Memory Interface Files. -- -- This setting is supported only if the unified control group hierarchy is used and disables -- MemoryLimit=. -- -- Units may have their children use a default memory.min value by specifying -- DefaultMemoryMin=, which has the same semantics as MemoryMin=. This setting -- does not affect memory.min in the unit itself. -- -- -- -- -- MemoryLow=bytes -- -- -- Specify the best-effort memory usage protection of the executed processes in this unit. If the memory -- usages of this unit and all its ancestors are below their low boundaries, this unit's memory won't be -- reclaimed as long as memory can be reclaimed from unprotected units. -+ Specify the memory usage protection of the executed processes in this unit. -+ When reclaiming memory, the unit is treated as if it was using less memory resulting in memory -+ to be preferentially reclaimed from unprotected units. -+ Using MemoryLow= results in a weaker protection where memory may still -+ be reclaimed to avoid invoking the OOM killer in case there is no other reclaimable memory. -+ -+ For a protection to be effective, it is generally required to set a corresponding -+ allocation on all ancestors, which is then distributed between children -+ (with the exception of the root slice). -+ Any MemoryMin= or MemoryLow= allocation that is not -+ explicitly distributed to specific children is used to create a shared protection for all children. -+ As this is a shared protection, the children will freely compete for the memory. - - Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is - parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a - percentage value may be specified, which is taken relative to the installed physical memory on the - system. If assigned the special value infinity, all available memory is protected, which may be - useful in order to always inherit all of the protection afforded by ancestors. -- This controls the memory.low control group attribute. For details about this -- control group attribute, see memory.min or memory.low control group attribute. -+ For details about this control group attribute, see Memory Interface Files. - - This setting is supported only if the unified control group hierarchy is used and disables - MemoryLimit=. - -- Units may have their children use a default memory.low value by specifying -- DefaultMemoryLow=, which has the same semantics as MemoryLow=. This setting -- does not affect memory.low in the unit itself. -+ Units may have their children use a default memory.min or -+ memory.low value by specifying DefaultMemoryMin= or -+ DefaultMemoryLow=, which has the same semantics as -+ MemoryMin= and MemoryLow=. -+ This setting does not affect memory.min or memory.low -+ in the unit itself. -+ Using it to set a default child allocation is only useful on kernels older than 5.7, -+ which do not support the memory_recursiveprot cgroup2 mount option. - - - -diff --git a/man/systemd.service.xml b/man/systemd.service.xml -index 4e281ec..d11e37d 100644 ---- a/man/systemd.service.xml -+++ b/man/systemd.service.xml -@@ -217,7 +217,7 @@ - this notification message has been sent. If this option is used, NotifyAccess= (see - below) should be set to open access to the notification socket provided by systemd. If - NotifyAccess= is missing or set to , it will be forcibly set to -- . -+ . - - Behavior of is very similar to ; however, - actual execution of the service program is delayed until all active jobs are dispatched. This may be used -@@ -292,10 +292,11 @@ - - BusName= - -- Takes a D-Bus bus name that this service is -- reachable as. This option is mandatory for services where -- Type= is set to -- . -+ Takes a D-Bus destination name that this service shall use. This option is mandatory -+ for services where Type= is set to . It is recommended to -+ always set this property if known to make it easy to map the service name to the D-Bus destination. -+ In particular, systemctl service-log-level/service-log-target verbs make use of -+ this. - - - -@@ -898,7 +899,7 @@ - - A service with the <varname>SuccessExitStatus=</varname> setting - -- SuccessExitStatus=TEMPFAIL 250 SIGUSR1 -+ SuccessExitStatus=TEMPFAIL 250 SIGKILL - - Exit status 75 (TEMPFAIL), 250, and the termination signal - SIGKILL are considered clean service terminations. -@@ -1028,20 +1029,24 @@ - - - FileDescriptorStoreMax= -- Configure how many file descriptors may be stored in the service manager for the service using -+ Configure how many file descriptors may be stored in the service manager for the -+ service using - sd_pid_notify_with_fds3's -- FDSTORE=1 messages. This is useful for implementing services that can restart after an -- explicit request or a crash without losing state. Any open sockets and other file descriptors which should not -- be closed during the restart may be stored this way. Application state can either be serialized to a file in -- /run, or better, stored in a -- memfd_create2 memory file -- descriptor. Defaults to 0, i.e. no file descriptors may be stored in the service manager. All file descriptors -- passed to the service manager from a specific service are passed back to the service's main process on the next -- service restart. Any file descriptors passed to the service manager are automatically closed when -- POLLHUP or POLLERR is seen on them, or when the service is fully -- stopped and no job is queued or being executed for it. If this option is used, NotifyAccess= -- (see above) should be set to open access to the notification socket provided by systemd. If -- NotifyAccess= is not set, it will be implicitly set to -+ FDSTORE=1 messages. This is useful for implementing services that can restart -+ after an explicit request or a crash without losing state. Any open sockets and other file -+ descriptors which should not be closed during the restart may be stored this way. Application state -+ can either be serialized to a file in /run, or better, stored in a -+ memfd_create2 -+ memory file descriptor. Defaults to 0, i.e. no file descriptors may be stored in the service -+ manager. All file descriptors passed to the service manager from a specific service are passed back -+ to the service's main process on the next service restart (see -+ sd_listen_fds3 for -+ details about the precise protocol used and the order in which the file descriptors are passed). Any -+ file descriptors passed to the service manager are automatically closed when -+ POLLHUP or POLLERR is seen on them, or when the service is -+ fully stopped and no job is queued or being executed for it. If this option is used, -+ NotifyAccess= (see above) should be set to open access to the notification socket -+ provided by systemd. If NotifyAccess= is not set, it will be implicitly set to - . - - -diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml -index f989b99..733977b 100644 ---- a/man/systemd.socket.xml -+++ b/man/systemd.socket.xml -@@ -81,16 +81,14 @@ - services, as well as parallelized starting of services. See the - blog stories linked at the end for an introduction. - -- Note that the daemon software configured for socket -- activation with socket units needs to be able to accept sockets -- from systemd, either via systemd's native socket passing interface -- (see -- sd_listen_fds3 -- for details) or via the traditional -- inetd8-style -- socket passing (i.e. sockets passed in via standard input and -- output, using StandardInput=socket in the -- service file). -+ Note that the daemon software configured for socket activation with socket units needs to be able -+ to accept sockets from systemd, either via systemd's native socket passing interface (see -+ sd_listen_fds3 for -+ details about the precise protocol used and the order in which the file descriptors are passed) or via -+ traditional inetd8-style -+ socket passing (i.e. sockets passed in via standard input and output, using -+ StandardInput=socket in the service file). - - All network sockets allocated through .socket units are allocated in the host's network - namespace (see - - If the address string is a string in the format -- v.w.x.y:z, it is read as IPv4 specifier for listening on an -- address v.w.x.y on a port z. -+ v.w.x.y:z, it is interpreted -+ as IPv4 address v.w.x.y and port z. - -- If the address string is a string in the format [x]:y, -- it is read as IPv6 address x on a port y. Note that this might -- make the service available via IPv4, too, depending on the -- BindIPv6Only= setting (see below). -- -+ If the address string is a string in the format -+ [x]:y, it is interpreted as -+ IPv6 address x and port y. An optional -+ interface scope (interface name or number) may be specified after a % symbol: -+ [x]:y%dev. -+ Interface scopes are only useful with link-local addresses, because the kernel ignores them in other -+ cases. Note that if an address is specified as IPv6, it might still make the service available via -+ IPv4 too, depending on the BindIPv6Only= setting (see below). - - If the address string is a string in the format -- vsock:x:y, it is read as CID x on -- a port y address in the -- AF_VSOCK family. The CID is a unique 32-bit -- integer identifier in AF_VSOCK analogous to an IP -- address. Specifying the CID is optional, and may be set to the empty -- string. -+ vsock:x:y, it is read as CID -+ x on a port y address in the -+ AF_VSOCK family. The CID is a unique 32-bit integer identifier in -+ AF_VSOCK analogous to an IP address. Specifying the CID is optional, and may be -+ set to the empty string. - - Note that SOCK_SEQPACKET (i.e. - ListenSequentialPacket=) is only available -@@ -429,6 +429,18 @@ - false, in read-only mode. Defaults to false. - - -+ -+ FlushPending= -+ Takes a boolean argument. May only be used when -+ . If yes, the socket's buffers are cleared after the -+ triggered service exited. This causes any pending data to be -+ flushed and any pending incoming connections to be rejected. If no, the -+ socket's buffers won't be cleared, permitting the service to handle any -+ pending connections after restart, which is the usually expected behaviour. -+ Defaults to . -+ -+ -+ - - MaxConnections= - The maximum number of connections to -@@ -556,26 +568,23 @@ - - - IPTOS= -- Takes an integer argument controlling the IP -- Type-Of-Service field for packets generated from this socket. -- This controls the IP_TOS socket option (see -- ip7 -- for details.). Either a numeric string or one of -- , , -- or may -- be specified. -+ Takes an integer argument controlling the IP Type-Of-Service field for packets -+ generated from this socket. This controls the IP_TOS socket option (see -+ ip7 for -+ details.). Either a numeric string or one of , , -+ or may be specified. - - - - IPTTL= -- Takes an integer argument controlling the IPv4 -- Time-To-Live/IPv6 Hop-Count field for packets generated from -- this socket. This sets the IP_TTL/IPV6_UNICAST_HOPS socket -- options (see -- ip7 -- and -- ipv67 -- for details.) -+ Takes an integer argument controlling the IPv4 Time-To-Live/IPv6 Hop-Count field for -+ packets generated from this socket. This sets the -+ IP_TTL/IPV6_UNICAST_HOPS socket options (see ip7 and -+ ipv67 for -+ details.) - - - -@@ -650,20 +659,18 @@ - - - FreeBind= -- Takes a boolean value. Controls whether the -- socket can be bound to non-local IP addresses. This is useful -- to configure sockets listening on specific IP addresses before -- those IP addresses are successfully configured on a network -- interface. This sets the IP_FREEBIND socket option. For -- robustness reasons it is recommended to use this option -- whenever you bind a socket to a specific IP address. Defaults -- to . -+ Takes a boolean value. Controls whether the socket can be bound to non-local IP -+ addresses. This is useful to configure sockets listening on specific IP addresses before those IP -+ addresses are successfully configured on a network interface. This sets the -+ IP_FREEBIND/IPV6_FREEBIND socket option. For robustness -+ reasons it is recommended to use this option whenever you bind a socket to a specific IP -+ address. Defaults to . - - - - Transparent= - Takes a boolean value. Controls the -- IP_TRANSPARENT socket option. Defaults to -+ IP_TRANSPARENT/IPV6_TRANSPARENT socket option. Defaults to - . - - -diff --git a/man/systemd.time.xml b/man/systemd.time.xml -index 5b7800e..79fe973 100644 ---- a/man/systemd.time.xml -+++ b/man/systemd.time.xml -@@ -75,6 +75,16 @@ - One can use the timespan command of - systemd-analyze1 - to normalise a textual time span for testing and validation purposes. -+ -+ Internally, systemd generally operates with microsecond time granularity, while the default time -+ unit in user-configurable time spans is usually seconds (see above). This disparity becomes visible when -+ comparing the same settings in the (high-level) unit file syntax with the matching (more low-level) D-Bus -+ properties (which are what -+ systemctl1's -+ show command displays). The former typically are suffixed with …Sec -+ to indicate the default unit of seconds, the latter are typically suffixed with …USec -+ to indicate the underlying low-level time unit, even if they both encapsulate the very same -+ settings. - - - -diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml -index 5822402..32f7814 100644 ---- a/man/systemd.timer.xml -+++ b/man/systemd.timer.xml -@@ -297,9 +297,10 @@ - - Takes a boolean argument. If true, the time when the service unit was last triggered - is stored on disk. When the timer is activated, the service unit is triggered immediately if it -- would have been triggered at least once during the time when the timer was inactive. This is useful -- to catch up on missed runs of the service when the system was powered down. Note that this setting -- only has an effect on timers configured with OnCalendar=. Defaults to -+ would have been triggered at least once during the time when the timer was inactive. Such triggering -+ is nonetheless subject to the delay imposed by RandomizedDelaySec=. -+ This is useful to catch up on missed runs of the service when the system was powered down. Note that -+ this setting only has an effect on timers configured with OnCalendar=. Defaults to - false. - - Use systemctl clean --what=state … on the timer unit to remove the timestamp -@@ -334,18 +335,14 @@ - - RemainAfterElapse= - -- Takes a boolean argument. If true, an elapsed -- timer will stay loaded, and its state remains queryable. If -- false, an elapsed timer unit that cannot elapse anymore is -- unloaded. Turning this off is particularly useful for -- transient timer units that shall disappear after they first -- elapse. Note that this setting has an effect on repeatedly -- starting a timer unit that only elapses once: if -- RemainAfterElapse= is on, it will not be -- started again, and is guaranteed to elapse only once. However, -- if RemainAfterElapse= is off, it might be -- started again if it is already elapsed, and thus be triggered -- multiple times. Defaults to -+ Takes a boolean argument. If true, a timer will stay loaded, and its state remains -+ queryable even after it elapsed and the associated unit (as configured with Unit=, -+ see above) deactivated again. If false, an elapsed timer unit that cannot elapse anymore is unloaded -+ once its associated unit deactivated again. Turning this off is particularly useful for transient -+ timer units. Note that this setting has an effect when repeatedly starting a timer unit: if -+ RemainAfterElapse= is on, starting the timer a second time has no effect. However, -+ if RemainAfterElapse= is off and the timer unit was already unloaded, it can be -+ started again, and thus the service can be triggered multiple times. Defaults to - yes. - - -diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml -index b3deb28..80057e2 100644 ---- a/man/systemd.unit.xml -+++ b/man/systemd.unit.xml -@@ -839,11 +839,10 @@ - - IgnoreOnIsolate= - -- Takes a boolean argument. If , this unit -- will not be stopped when isolating another unit. Defaults to -- for service, target, socket, busname, timer, and path -- units, and for slice, scope, device, swap, mount, and -- automount units. -+ Takes a boolean argument. If , this unit will not be stopped -+ when isolating another unit. Defaults to for service, target, socket, timer, -+ and path units, and for slice, scope, device, swap, mount, and automount -+ units. - - - -@@ -1092,9 +1091,6 @@ - Except for ConditionPathIsSymbolicLink=, all path checks follow symlinks. - - -- -- - - ConditionArchitecture= - -@@ -1169,6 +1165,7 @@ - rkt, - wsl, - proot, -+ pouch, - acrn to test - against a specific implementation, or - private-users to check whether we are running in a user namespace. See -diff --git a/man/sysusers.d.xml b/man/sysusers.d.xml -index 38a95d6..2d5023d 100644 ---- a/man/sysusers.d.xml -+++ b/man/sysusers.d.xml -@@ -27,12 +27,12 @@ - /usr/lib/sysusers.d/*.conf - - --#Type Name ID GECOS Home directory Shell --u user_name uid "User Description" /path/to/shell --u user_name uid:gid - - --u user_name /file/owned/by/user - - --g group_name gid "Group Description" --g group_name /file/owned/by/group - -+#Type Name ID GECOS Home directory Shell -+u user_name uid "User Description" /home/dir /path/to/shell -+u user_name uid:gid "User Description" /home/dir /path/to/shell -+u user_name /file/owned/by/user "User Description" /home/dir /path/to/shell -+g group_name gid -+g group_name /file/owned/by/group - m user_name group_name - r - lowest-highest - -diff --git a/man/tc.xml b/man/tc.xml -index f312ac2..da24c08 100644 ---- a/man/tc.xml -+++ b/man/tc.xml -@@ -39,7 +39,7 @@ - - ClassId= - -- Configues the unique identifier of the class. It is specified as the major and minor numbers in -+ Configures the unique identifier of the class. It is specified as the major and minor numbers in - hexadecimal in the range 0x1–Oxffff separated with a colon (major:minor). - Defaults to unset. - -diff --git a/man/telinit.xml b/man/telinit.xml -index 43871eb..0fffd51 100644 ---- a/man/telinit.xml -+++ b/man/telinit.xml -@@ -3,7 +3,7 @@ - "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> - - -- - - -@@ -148,5 +148,4 @@ - wall1 - - -- - -diff --git a/man/udev_device_has_tag.xml b/man/udev_device_has_tag.xml -index 9c64a4b..2e5b67e 100644 ---- a/man/udev_device_has_tag.xml -+++ b/man/udev_device_has_tag.xml -@@ -21,9 +21,11 @@ - - - udev_device_has_tag -+ udev_device_has_current_tag - udev_device_get_devlinks_list_entry - udev_device_get_properties_list_entry - udev_device_get_tags_list_entry -+ udev_device_get_current_tags_list_entry - udev_device_get_sysattr_list_entry - udev_device_get_property_value - udev_device_get_sysattr_value -@@ -36,6 +38,18 @@ - - #include <libudev.h> - -+ -+ int udev_device_has_tag -+ struct udev_device *udev_device -+ const char *tag -+ -+ -+ -+ int udev_device_has_current_tag -+ struct udev_device *udev_device -+ const char *tag -+ -+ - - struct udev_list_entry *udev_device_get_devlinks_list_entry - struct udev_device *udev_device -@@ -52,20 +66,19 @@ - - - -- struct udev_list_entry *udev_device_get_sysattr_list_entry -+ struct udev_list_entry *udev_device_get_current_tags_list_entry - struct udev_device *udev_device - - - -- const char *udev_device_get_property_value -+ struct udev_list_entry *udev_device_get_sysattr_list_entry - struct udev_device *udev_device -- const char *key - - - -- int udev_device_has_tag -+ const char *udev_device_get_property_value - struct udev_device *udev_device -- const char *tag -+ const char *key - - - -@@ -84,22 +97,40 @@ - - - -- -+ udev_device_has_tag() returns a valuer larger than zero if the specified -+ device object has the indicated tag assigned to it, and zero otherwise. See -+ udev7 for details on -+ the tags concept. udev_device_has_current_tag() executes a similar check, however -+ only determines whether the indicated tag was set as result of the most recent event seen for the -+ device. Tags are "sticky", i.e. once set for a device they remain on the device until the device is -+ unplugged, even if the rules run for later events of the same device do not set them anymore. Any tag for -+ which udev_device_has_current_tag() returns true will hence also return true when -+ passed to udev_device_has_tag(), but the opposite might not be true, in case a tag is -+ no longer configured by the rules applied to the most recent device even. -+ -+ udev_device_get_tags_list_entry() returns a a -+ udev_list_entry object, encapsulating a list of tags set for the specified -+ device. Similar, udev_device_get_current_tags_list_entry() returns a list of tags -+ set for the specified device as effect of the most recent device event seen (see above for details on the -+ difference). -+ - - - Return Value - -- On success, -- udev_device_get_devlinks_list_entry(), -+ On success, udev_device_has_tag() and -+ udev_device_has_current_tag() return positive or 0, depending -+ on whether the device has the given tag or not. On failure, a negative error code is returned. -+ -+ On success, udev_device_get_devlinks_list_entry(), - udev_device_get_properties_list_entry(), -- udev_device_get_tags_list_entry() and -- udev_device_get_sysattr_list_entry() return -- a pointer to the first entry of the retrieved list. If that list -- is empty, or if an error occurred, NULL is -+ udev_device_get_tags_list_entry(), -+ udev_device_get_current_tags_list_entry() and -+ udev_device_get_sysattr_list_entry() return a pointer to the first entry of the -+ retrieved list. If that list is empty, or if an error occurred, NULL is - returned. - - On success, -@@ -119,17 +150,13 @@ - contain NUL bytes should not be set with - this function; instead, write them directly to the files within - the device's syspath. -- -- On success, udev_device_has_tag() -- returns 1 or 0, -- depending on whether the device has the given tag or not. -- On failure, a negative error code is returned. - - - - See Also - - -+ udev7, - udev_new3, - udev_device_new_from_syspath3, - udev_device_get_syspath3, -diff --git a/man/userdbctl.xml b/man/userdbctl.xml -index 9a69f33..c869377 100644 ---- a/man/userdbctl.xml -+++ b/man/userdbctl.xml -@@ -59,7 +59,13 @@ - user friendly, human readable output is generated; if table a minimal, tabular - output is generated; if json a JSON formatted output is generated. Defaults to - friendly if a user/group is specified on the command line, -- table otherwise. -+ table otherwise. -+ -+ Note that most output formats do not show all available information. In particular, -+ classic and table show only the most important fields. Various -+ modes also do not show password hashes. Use json to view all fields, including -+ any authentication fields. -+ - - - -diff --git a/meson.build b/meson.build -index dbbddb6..e680490 100644 ---- a/meson.build -+++ b/meson.build -@@ -14,7 +14,7 @@ project('systemd', 'c', - ) - - libsystemd_version = '0.29.0' --libudev_version = '1.6.18' -+libudev_version = '1.7.0' - - # We need the same data in two different formats, ugh! - # Also, for hysterical reasons, we use different variable -@@ -38,6 +38,9 @@ relative_source_path = run_command('realpath', - project_source_root).stdout().strip() - conf.set_quoted('RELATIVE_SOURCE_PATH', relative_source_path) - -+conf.set10('DEVELOPER_MODE', get_option('mode') == 'developer', -+ description : 'enable additional checks only suitable in development') -+ - want_ossfuzz = get_option('oss-fuzz') - want_libfuzzer = get_option('llvm-fuzz') - if want_ossfuzz + want_libfuzzer > 1 -@@ -198,7 +201,7 @@ endif - - pamconfdir = get_option('pamconfdir') - if pamconfdir == '' -- pamconfdir = join_paths(sysconfdir, 'pam.d') -+ pamconfdir = join_paths(prefixdir, 'lib/pam.d') - endif - - memory_accounting_default = get_option('memory-accounting-default') -@@ -209,7 +212,7 @@ conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR', join_paths(pkgsysc - conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir) - conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path) - conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) --conf.set_quoted('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) -+conf.set_quoted('RC_LOCAL_PATH', get_option('rc-local')) - - conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper()) - -@@ -227,6 +230,7 @@ conf.set_quoted('SYSTEMCTL_BINARY_PATH', join_paths(rootbin - conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent')) - conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH', join_paths(bindir, 'systemd-stdio-bridge')) - conf.set_quoted('ROOTPREFIX', rootprefixdir) -+conf.set_quoted('ROOTPREFIX_NOSLASH', rootprefixdir_noslash) - conf.set_quoted('RANDOM_SEED_DIR', randomseeddir) - conf.set_quoted('RANDOM_SEED', join_paths(randomseeddir, 'random-seed')) - conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', join_paths(rootlibexecdir, 'systemd-cryptsetup')) -@@ -295,7 +299,7 @@ substs.set('CERTIFICATEROOT', get_option('certif - substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed')) - substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path) - substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) --substs.set('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) -+substs.set('RC_LOCAL_PATH', get_option('rc-local')) - substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no') - substs.set('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default) - substs.set('HIGH_RLIMIT_NOFILE', conf.get('HIGH_RLIMIT_NOFILE')) -@@ -791,7 +795,7 @@ tty_gid = get_option('tty-gid') - conf.set('TTY_GID', tty_gid) - substs.set('TTY_GID', tty_gid) - --# Ensure provided GID argument is numeric, otherwise fallback to default assignment -+# Ensure provided GID argument is numeric, otherwise fall back to default assignment - users_gid = get_option('users-gid') - substs.set('USERS_GID', users_gid < 0 ? '-' : users_gid) - -@@ -890,6 +894,7 @@ libmount = dependency('mount', - want_libfdisk = get_option('fdisk') - if want_libfdisk != 'false' and not skip_deps - libfdisk = dependency('fdisk', -+ version : '>= 2.33', - required : want_libfdisk == 'true') - have = libfdisk.found() - else -@@ -1414,42 +1419,43 @@ else - endif - conf.set10('ENABLE_REMOTE', have) - --foreach term : ['utmp', -- 'hibernate', -- 'environment-d', -+foreach term : ['analyze', -+ 'backlight', - 'binfmt', - 'coredump', -- 'pstore', -- 'resolve', -- 'logind', -+ 'efi', -+ 'environment-d', -+ 'firstboot', -+ 'gshadow', -+ 'hibernate', - 'hostnamed', -+ 'hwdb', -+ 'idn', -+ 'ima', -+ 'initrd', -+ 'ldconfig', - 'localed', -+ 'logind', - 'machined', -- 'portabled', -- 'userdb', - 'networkd', -- 'timedated', -- 'timesyncd', -- 'firstboot', -- 'randomseed', -- 'backlight', -- 'vconsole', -+ 'nss-myhostname', -+ 'nss-systemd', -+ 'portabled', -+ 'pstore', - 'quotacheck', -+ 'randomseed', -+ 'resolve', -+ 'rfkill', -+ 'smack', - 'sysusers', -+ 'timedated', -+ 'timesyncd', - 'tmpfiles', -- 'hwdb', -- 'rfkill', -- 'xdg-autostart', -- 'ldconfig', -- 'efi', - 'tpm', -- 'ima', -- 'smack', -- 'gshadow', -- 'idn', -- 'initrd', -- 'nss-myhostname', -- 'nss-systemd'] -+ 'userdb', -+ 'utmp', -+ 'vconsole', -+ 'xdg-autostart'] - have = get_option(term) - name = 'ENABLE_' + term.underscorify().to_upper() - conf.set10(name, have) -@@ -1623,8 +1629,16 @@ install_libsystemd_static = static_library( - libgcrypt], - c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC'])) - --# Generate autosuspend rules -+############################################################ -+ -+autosuspend_update_sh = find_program('tools/autosuspend-update.sh') -+hwdb_update_sh = find_program('tools/hwdb-update.sh') - make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py') -+make_directive_index_py = find_program('tools/make-directive-index.py') -+make_man_index_py = find_program('tools/make-man-index.py') -+syscall_names_update_sh = find_program('tools/syscall-names-update.sh') -+xml_helper_py = find_program('tools/xml_helper.py') -+update_dbus_docs_py = find_program('tools/update-dbus-docs.py') - - ############################################################ - -@@ -1766,7 +1780,7 @@ public_programs += executable( - libmount, - libblkid], - install_rpath : rootlibexecdir, -- install : get_option('analyze')) -+ install : conf.get('ENABLE_ANALYZE')) - - executable( - 'systemd-journald', -@@ -1799,11 +1813,11 @@ public_programs += executable( - include_directories : includes, - link_with : [libshared], - dependencies : [threads, -- libqrencode, -+ libdl, - libxz, - liblz4, -- libpcre2, -- libzstd], -+ libzstd, -+ libdl], - install_rpath : rootlibexecdir, - install : true, - install_dir : rootbindir) -@@ -1898,8 +1912,7 @@ if conf.get('HAVE_BLKID') == 1 - include_directories : includes, - link_with : [libshared], - install_rpath : rootlibexecdir, -- install : true, -- install_dir : rootlibexecdir) -+ install : true) - endif - - if conf.get('ENABLE_RESOLVE') == 1 -@@ -2174,8 +2187,7 @@ if conf.get('ENABLE_HOMED') == 1 - link_with : [libshared], - dependencies : [threads, - libcrypt, -- libopenssl, -- libpwquality], -+ libopenssl], - install_rpath : rootlibexecdir, - install : true, - install_dir : rootlibexecdir) -@@ -2190,7 +2202,7 @@ if conf.get('ENABLE_HOMED') == 1 - libopenssl, - libp11kit, - libfido2, -- libpwquality], -+ libdl], - install_rpath : rootlibexecdir, - install : true, - install_dir : rootbindir) -@@ -2261,8 +2273,8 @@ executable( - if conf.get('HAVE_LIBCRYPTSETUP') == 1 - systemd_cryptsetup_sources = files(''' - src/cryptsetup/cryptsetup-pkcs11.h -- src/cryptsetup/cryptsetup-util.c -- src/cryptsetup/cryptsetup-util.h -+ src/cryptsetup/cryptsetup-keyfile.c -+ src/cryptsetup/cryptsetup-keyfile.h - src/cryptsetup/cryptsetup.c - '''.split()) - -@@ -2286,7 +2298,6 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 - 'src/cryptsetup/cryptsetup-generator.c', - include_directories : includes, - link_with : [libshared], -- dependencies : [libcryptsetup], - install_rpath : rootlibexecdir, - install : true, - install_dir : systemgeneratordir) -@@ -2306,7 +2317,6 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1 - 'src/veritysetup/veritysetup-generator.c', - include_directories : includes, - link_with : [libshared], -- dependencies : [libcryptsetup], - install_rpath : rootlibexecdir, - install : true, - install_dir : systemgeneratordir) -@@ -2661,13 +2671,13 @@ if conf.get('ENABLE_REPART') == 1 - include_directories : includes, - link_with : [libshared], - dependencies : [threads, -- libcryptsetup, - libblkid, - libfdisk, - libopenssl], - install_rpath : rootlibexecdir, - install : true, - install_dir : rootbindir) -+ public_programs += exe - - if want_tests != 'false' - test('test-repart', -@@ -2743,7 +2753,6 @@ executable('systemd-growfs', - 'src/partition/growfs.c', - include_directories : includes, - link_with : [libshared], -- dependencies : [libcryptsetup], - install_rpath : rootlibexecdir, - install : true, - install_dir : rootlibexecdir) -@@ -3329,12 +3338,6 @@ run_target( - - ############################################################ - --make_directive_index_py = find_program('tools/make-directive-index.py') --make_man_index_py = find_program('tools/make-man-index.py') --xml_helper_py = find_program('tools/xml_helper.py') --hwdb_update_sh = find_program('tools/hwdb-update.sh') --autosuspend_update_sh = find_program('tools/autosuspend-update.sh') -- - subdir('sysctl.d') - subdir('sysusers.d') - subdir('tmpfiles.d') -@@ -3682,7 +3685,7 @@ foreach tuple : [ - ['link-networkd-shared', get_option('link-networkd-shared')], - ['link-timesyncd-shared', get_option('link-timesyncd-shared')], - ['kernel-install', get_option('kernel-install')], -- ['systemd-analyze', get_option('analyze')], -+ ['systemd-analyze', conf.get('ENABLE_ANALYZE') == 1], - ] - - if tuple.length() >= 2 -diff --git a/meson_options.txt b/meson_options.txt -index fd73d5e..1ad0969 100644 ---- a/meson_options.txt -+++ b/meson_options.txt -@@ -4,6 +4,9 @@ - option('version-tag', type : 'string', - description : 'override the git version string') - -+option('mode', type : 'combo', choices : ['default', 'developer'], -+ description : 'enable additional checks suitable for systemd development') -+ - option('split-usr', type : 'combo', choices : ['auto', 'true', 'false'], - description : '''/bin, /sbin aren't symlinks into /usr''') - option('split-bin', type : 'combo', choices : ['auto', 'true', 'false'], -diff --git a/po/.gitignore b/po/.gitignore -deleted file mode 100644 -index 46202f3..0000000 ---- a/po/.gitignore -+++ /dev/null -@@ -1 +0,0 @@ --/systemd.pot -diff --git a/po/be.po b/po/be.po -index 65e5064..3286e1a 100644 ---- a/po/be.po -+++ b/po/be.po -@@ -8,7 +8,7 @@ msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2016-06-09 19:54+0300\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2016-06-09 19:47+0300\n" - "Last-Translator: Viktar Vaŭčkievič \n" - "Language-Team: \n" -@@ -20,40 +20,40 @@ msgstr "" - "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" - "X-Generator: Lokalize 2.0\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Адправіць пароль назад сістэме" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "Неабходна аўтэнтыфікацыя для адпраўкі пароля назад сістэме." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Кіраваць сэрвісамі і іншымі сістэмнымі адзінкамі" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" - "Неабходна аўтэнтыфікацыя для кіравання сэрвісамі і іншымі сістэмнымі " - "адзінкамі." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Кіраваць файламі сэрвісаў і іншых сістэмных адзінак" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" - "Неабходна аўтэнтыфікацыя для кіравання файламі сэрвісаў і іншых сістэмных " - "адзінак." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "Усталяваць або скінуць зменныя асяроддзя сістэмнага мэнэджэра" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -61,27 +61,95 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для ўсталявання або скіду зменных асяроддзя " - "сістэмнага мэнэджэра." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Перачытаць стан systemd" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "Неабходна аўтэнтыфікацыя для перачытання стану systemd." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Неабходна аўтэнтыфікацыя для перачытання стану systemd." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Неабходна аўтэнтыфікацыя для перачытання стану systemd." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Неабходна аўтэнтыфікацыя для кіравання актыўнымі сесіямі, карыстальнікамі і " -+"месцамі." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "Неабходна аўтэнтыфікацыя для далучэння прылад да працоўных месцаў." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўсеагульнага паведамлення" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Неабходна аўтэнтыфікацыя для кіравання актыўнымі сесіямі, карыстальнікамі і " -+"месцамі." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Усталяваць імя вузла" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Неабходна аўтэнтыфікацыя для ўсталявання імя вузла." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Усталяваць статычнае імя вузла" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -89,101 +157,111 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для ўсталявання як статычнага так і прыгожага імя " - "вузла." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Усталяваць інфармацыю аб машыне" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "" - "Неабходна аўтэнтыфікацыя для ўсталявання інфармацыі аб лакальнай машыне." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Неабходна аўтэнтыфікацыя для перачытання стану '$(unit)'." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Імпартаваць вобраз ВМ або кантэйнера" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "Неабходна аўтэнтыфікацыя для імпарту вобраза ВМ або кантэйнера" - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "Экспартаваць вобраз ВМ або кантэйнера" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "Неабходна аўтэнтыфікацыя для экспарту вобраза ВМ або кантэйнера" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "Спампаваць вобраз ВМ або кантэйнера" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "Неабходна аўтэнтыфікацыя для спампоўкі вобраза ВМ або кантэйнера" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Усталяваць сістэмную лакаль" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнай лакалі." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Усталяваць сістэмныя налады клавіятуры" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмных налад клавіятуры." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Дазволіць праграмам перашкаджаць выключэнню сістэмы" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць выключэнню " - "сістэмы." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Дазволіць праграмам затрымліваць выключэнне сістэмы" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "Неабходна аўтэнтыфікацыя для дазволу праграмам затрымліваць выключэнне " - "сістэмы." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Дазволіць праграмам перашкаджаць засыпанню сістэмы" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць засыпанню " - "сістэмы." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Дазволіць праграмам затрымліваць засыпанне сістэмы" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "Неабходна аўтэнтыфікацыя для дазволу праграмам затрымліваць засыпанне " - "сістэмы." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "Дазволіць праграмам перашкаджаць аўтаматычнаму прыпыненню сістэмы" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -191,12 +269,12 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць аўтаматычнаму " - "прыпыненню сістэмы." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" - "Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу выключэння" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." -@@ -204,12 +282,12 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " - "апрацоўваць клавішу выключэння." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" - "Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу прыпынення" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." -@@ -217,12 +295,12 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " - "апрацоўваць клавішу прыпынення." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" - "Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу гібернацыі" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -230,12 +308,12 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " - "апрацоўваць клавішу гібернацыі." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" - "Дазволіць праграмам перашкаджаць сістэме апрацоўваць закрыццё крышкі ноўтбука" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -243,58 +321,57 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " - "апрацоўваць закрыццё крышкі ноўтбука." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" - msgstr "" - "Дазволіць карыстальніку, якія яшчэ не ўвайшоў у сістэму, выконваць праграмы" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" - "Неабходны відавочны запыт для выканання праграм карыстальніка, які яшчэ не " - "ўвайшоў у сістэму." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "" - "Дазволіць карыстальнікам, якія яшчэ не ўвайшлі ў сістэму, выконваць праграмы" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Неабходна аўтэнтыфікацыя для выканання праграм карыстальніка, які яшчэ не " - "ўвайшоў у сістэму." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Дазволіць далучаць прылады да працоўных месцаў" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "Неабходна аўтэнтыфікацыя для далучэння прылад да працоўных месцаў." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Адключаць прылады ад працоўных месцаў" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "Неабходна аўтэнтыфікацыя для адключэння прылад ад працоўных месцаў." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Выключыць сістэму" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Неабходна аўтэнтыфікацыя для выключэння сістэмы." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Выключыць сістэму пры прысутнасці іншых карыстальнікаў" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -302,63 +379,111 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для выключэння сістэмы пры прысутнасці іншых " - "карыстальнікаў." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "Выключыць сістэму, калі праграмы перашкаджаюць гэтаму" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Неабходна аўтэнтыфікацыя для выключэння сістэмы, калі праграмы перашкаджаюць " - "гэтаму." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Перазагрузіць сістэму" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Перазагрузіць сістэму пры прысутнасці іншых карыстальнікаў" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы пры прысутнасці іншых " - "карыстальнікаў." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "Перазагрузіць сістэму, калі праграмы перашкаджаюць гэтаму" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы, калі праграмы " - "перашкаджаюць гэтаму." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "Гібернаваць сістэму" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "Гібернаваць сістэму пры прысутнасці іншых карыстальнікаў" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"Неабходна аўтэнтыфікацыя для гібернацыі сістэмы пры прысутнасці іншых " -+"карыстальнікаў." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "Гібернаваць сістэму, калі праграмы перашкаджаюць гэтаму" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"Неабходна аўтэнтыфікацыя для гібернацыі сістэмы, калі праграмы перашкаджаюць " -+"гэтаму." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Прыпыніць сістэму" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Неабходна аўтэнтыфікацыя для прыпынення сістэмы." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Прыпыніць сістэму пры прысутнасці іншых карыстальнікаў" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -366,31 +491,31 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для прыпынення сістэмы пры прысутнасці іншых " - "карыстальнікаў." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "Прыпыніць сістэму, калі праграмы перашкаджаюць гэтаму" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Неабходна аўтэнтыфікацыя для прыпынення сістэмы, калі праграмы перашкаджаюць " - "гэтаму." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Гібернаваць сістэму" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "Гібернаваць сістэму пры прысутнасці іншых карыстальнікаў" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -398,124 +523,175 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы пры прысутнасці іншых " - "карыстальнікаў." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "Гібернаваць сістэму, калі праграмы перашкаджаюць гэтаму" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы, калі праграмы перашкаджаюць " - "гэтаму." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Кіраваць актыўнымі сесіямі, карыстальнікамі і працоўнымі месцамі" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Неабходна аўтэнтыфікацыя для кіравання актыўнымі сесіямі, карыстальнікамі і " - "месцамі." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Блакаваць або разблакаваць актыўную сесію" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "" - "Неабходна аўтэнтыфікацыя для блакіроўкі або разблакіроўкі актыўнай сесіі." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часавога поясу." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "Дазволіць указанне прашыўцы на загрузку інтэрфейсу налад" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." - msgstr "" - "Неабходна аўтэнтыфікацыя для ўказання прашыўцы на загрузку інтэрфейсу налад." - --#: ../src/login/org.freedesktop.login1.policy.in.h:57 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Неабходна аўтэнтыфікацыя для ўказання прашыўцы на загрузку інтэрфейсу налад." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Неабходна аўтэнтыфікацыя для ўказання прашыўцы на загрузку інтэрфейсу налад." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Усталяваць усеагульнае паведамленне" - --#: ../src/login/org.freedesktop.login1.policy.in.h:58 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўсеагульнага паведамлення" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання імя вузла." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Увайсці ў лакальны кантэйнер" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "Неабходна аўтэнтыфікацыя для ўваходу ў лакальны кантэйнер." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Увайсці ў лакальны вузел" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "Неабходна аўтэнтыфікацыя для ўваходу ў лакальны вузел." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Атрымаць абалонку на лакальным кантэйнеры" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" - "Неабходна аўтэнтыфікацыя для атрымання абалонкі на лакальным кантэйнеры." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Атрымаць абалонку на лакальным вузле" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "Неабходна аўтэнтыфікацыя для атрымання абалонкі на лакальным вузле." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Атрымаць псеўда TTY на лакальным кантэйнеры" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" - "Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным кантэйнеры." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Атрымаць псеўда TTY на лакальным вузле" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным вузле." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Кіраваць лакальнымі віртуальнымі машынамі або кантэйнерамі" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" - "Неабходна аўтэнтыфікацыя для кіравання лакальнымі віртуальнымі машынамі і " - "кантэйнерамі." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Кіраваць вобразамі лакальных віртуальных машын і кантэйнераў" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." -@@ -523,27 +699,255 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для кіравання вобразамі лакальных віртуальных машын " - "і кантэйнераў." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часу." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часу." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Неабходна аўтэнтыфікацыя для спынення '$(unit)'." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання імя вузла." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Неабходна аўтэнтыфікацыя для ўваходу ў лакальны вузел." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання імя вузла." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнай лакалі." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часу." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часу." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўсеагульнага паведамлення" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўсеагульнага паведамлення" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Неабходна аўтэнтыфікацыя для перачытання стану systemd." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "Неабходна аўтэнтыфікацыя для імпарту вобраза ВМ або кантэйнера" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "Неабходна аўтэнтыфікацыя для далучэння прылад да працоўных месцаў." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "Неабходна аўтэнтыфікацыя для спампоўкі вобраза ВМ або кантэйнера" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўсеагульнага паведамлення" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўсеагульнага паведамлення" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмных налад клавіятуры." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Усталяваць сістэмны час" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часу." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Усталяваць сістэмны часавы пояс" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часавога поясу." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "Усталяваць часавы пояс (мясцовы або UTC), у якім RTC захоўвае час" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -551,11 +955,11 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для ўсталявання часавога поясу (мясцовы або UTC), у " - "якім захоўваецца час у RTC." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Уключыць або выключыць сінхранізацыю часу па сетцы" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -563,30 +967,54 @@ msgstr "" - "Неабходна аўтэнтыфікацыя для ўключэння або выключэння сінхранізацыі часу па " - "сетцы." - --#: ../src/core/dbus-unit.c:450 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Неабходна аўтэнтыфікацыя для запуску '$(unit)'." - --#: ../src/core/dbus-unit.c:451 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Неабходна аўтэнтыфікацыя для спынення '$(unit)'." - --#: ../src/core/dbus-unit.c:452 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Неабходна аўтэнтыфікацыя для перачытання стану '$(unit)'." - --#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Неабходна аўтэнтыфікацыя для перазапуску '$(unit)'." - --#: ../src/core/dbus-unit.c:560 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Неабходна аўтэнтыфікацыя для забойства '$(unit)'." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўласцівасцей '$(unit)'." - --#: ../src/core/dbus-unit.c:590 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'." - --#: ../src/core/dbus-unit.c:622 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўласцівасцей '$(unit)'." -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Неабходна аўтэнтыфікацыя для забойства '$(unit)'." -diff --git a/po/be@latin.po b/po/be@latin.po -index 1ce3efa..ff57007 100644 ---- a/po/be@latin.po -+++ b/po/be@latin.po -@@ -8,7 +8,7 @@ msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2016-06-09 19:54+0300\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2016-06-09 19:50+0300\n" - "Last-Translator: Viktar Vaŭčkievič \n" - "Language-Team: \n" -@@ -20,40 +20,40 @@ msgstr "" - "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" - "X-Generator: Lokalize 2.0\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Adpravić paroĺ nazad sistemie" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "Nieabchodna aŭtentyfikacyja dlia adpraŭki parolia nazad sistemie." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Kiravać servisami i inšymi sistemnymi adzinkami" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia kiravannia servisami i inšymi sistemnymi " - "adzinkami." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Kiravać fajlami servisaŭ i inšych sistemnych adzinak" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia kiravannia fajlami servisaŭ i inšych " - "sistemnych adzinak." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "Ustaliavać abo skinuć zmiennyja asiaroddzia sistemnaha menedžera" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -61,27 +61,97 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia abo skidu zmiennych " - "asiaroddzia sistemnaha menedžera." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Pieračytać stan systemd" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu systemd." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu systemd." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu systemd." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia kiravannia aktyŭnymi siesijami, " -+"karystaĺnikami i miescami." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia dalučennia prylad da pracoŭnych miescaŭ." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭsieahuĺnaha paviedamliennia" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia kiravannia aktyŭnymi siesijami, " -+"karystaĺnikami i miescami." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Ustaliavać imia vuzla" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia imia vuzla." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Ustaliavać statyčnaje imia vuzla" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -89,103 +159,113 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia jak statyčnaha tak i " - "pryhožaha imia vuzla." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Ustaliavać infarmacyju ab mašynie" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia infarmacyi ab lakaĺnaj " - "mašynie." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu '$(unit)'." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Impartavać vobraz VM abo kantejniera" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "Nieabchodna aŭtentyfikacyja dlia impartu vobraza VM abo kantejniera" - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "Ekspartavać vobraz VM abo kantejniera" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "Nieabchodna aŭtentyfikacyja dlia ekspartu vobraza VM abo kantejniera" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "Spampavać vobraz VM abo kantejniera" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "Nieabchodna aŭtentyfikacyja dlia spampoŭki vobraza VM abo kantejniera" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Ustaliavać sistemnuju lakaĺ" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaj lakali." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Ustaliavać sistemnyja nalady klavijatury" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnych nalad klavijatury." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Dazvolić prahramam pieraškadžać vykliučenniu sistemy" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać vykliučenniu " - "sistemy." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Dazvolić prahramam zatrymlivać vykliučennie sistemy" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam zatrymlivać vykliučennie " - "sistemy." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Dazvolić prahramam pieraškadžać zasypanniu sistemy" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać zasypanniu " - "sistemy." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Dazvolić prahramam zatrymlivać zasypannie sistemy" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam zatrymlivać zasypannie " - "sistemy." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "Dazvolić prahramam pieraškadžać aŭtamatyčnamu prypynienniu sistemy" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -193,12 +273,12 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać " - "aŭtamatyčnamu prypynienniu sistemy." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" - "Dazvolić prahramam pieraškadžać sistemie apracoŭvać klavišu vykliučennia" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." -@@ -206,12 +286,12 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " - "apracoŭvać klavišu vykliučennia." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" - "Dazvolić prahramam pieraškadžać sistemie apracoŭvać klavišu prypyniennia" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." -@@ -219,12 +299,12 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " - "apracoŭvać klavišu prypyniennia." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" - "Dazvolić prahramam pieraškadžać sistemie apracoŭvać klavišu hibiernacyi" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -232,12 +312,12 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " - "apracoŭvać klavišu hibiernacyi." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" - "Dazvolić prahramam pieraškadžać sistemie apracoŭvać zakryccio kryški noŭtbuka" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -245,60 +325,59 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " - "apracoŭvać zakryccio kryški noŭtbuka." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" - msgstr "" - "Dazvolić karystaĺniku, jakija jašče nie ŭvajšoŭ u sistemu, vykonvać prahramy" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" - "Nieabchodny vidavočny zapyt dlia vykanannia prahram karystaĺnika, jaki jašče " - "nie ŭvajšoŭ u sistemu." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "" - "Dazvolić karystaĺnikam, jakija jašče nie ŭvajšli ŭ sistemu, vykonvać prahramy" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia vykanannia prahram karystaĺnika, jaki jašče " - "nie ŭvajšoŭ u sistemu." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Dazvolić dalučać prylady da pracoŭnych miescaŭ" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia dalučennia prylad da pracoŭnych miescaŭ." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Adkliučać prylady ad pracoŭnych miescaŭ" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia adkliučennia prylad ad pracoŭnych miescaŭ." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Vykliučyć sistemu" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Vykliučyć sistemu pry prysutnasci inšych karystaĺnikaŭ" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -306,63 +385,111 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy pry prysutnasci inšych " - "karystaĺnikaŭ." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "Vykliučyć sistemu, kali prahramy pieraškadžajuć hetamu" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy, kali prahramy " - "pieraškadžajuć hetamu." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Pierazahruzić sistemu" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Pierazahruzić sistemu pry prysutnasci inšych karystaĺnikaŭ" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy pry prysutnasci " - "inšych karystaĺnikaŭ." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "Pierazahruzić sistemu, kali prahramy pieraškadžajuć hetamu" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy, kali prahramy " - "pieraškadžajuć hetamu." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "Hibiernavać sistemu" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "Hibiernavać sistemu pry prysutnasci inšych karystaĺnikaŭ" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy pry prysutnasci inšych " -+"karystaĺnikaŭ." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "Hibiernavać sistemu, kali prahramy pieraškadžajuć hetamu" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy, kali prahramy " -+"pieraškadžajuć hetamu." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Prypynić sistemu" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Prypynić sistemu pry prysutnasci inšych karystaĺnikaŭ" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -370,31 +497,31 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy pry prysutnasci inšych " - "karystaĺnikaŭ." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "Prypynić sistemu, kali prahramy pieraškadžajuć hetamu" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy, kali prahramy " - "pieraškadžajuć hetamu." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Hibiernavać sistemu" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "Hibiernavać sistemu pry prysutnasci inšych karystaĺnikaŭ" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -402,44 +529,56 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy pry prysutnasci inšych " - "karystaĺnikaŭ." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "Hibiernavać sistemu, kali prahramy pieraškadžajuć hetamu" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy, kali prahramy " - "pieraškadžajuć hetamu." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Kiravać aktyŭnymi siesijami, karystaĺnikami i pracoŭnymi miescami" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia kiravannia aktyŭnymi siesijami, " - "karystaĺnikami i miescami." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Blakavać abo razblakavać aktyŭnuju siesiju" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia blakiroŭki abo razblakiroŭki aktyŭnaj " - "siesii." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha časavoha pojasu." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "Dazvolić ukazannie prašyŭcy na zahruzku interfiejsu nalad" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -447,85 +586,127 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭkazannia prašyŭcy na zahruzku interfiejsu " - "nalad." - --#: ../src/login/org.freedesktop.login1.policy.in.h:57 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭkazannia prašyŭcy na zahruzku interfiejsu " -+"nalad." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭkazannia prašyŭcy na zahruzku interfiejsu " -+"nalad." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Ustaliavać usieahuĺnaje paviedamliennie" - --#: ../src/login/org.freedesktop.login1.policy.in.h:58 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭsieahuĺnaha paviedamliennia" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia imia vuzla." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Uvajsci ŭ lakaĺny kantejnier" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "Nieabchodna aŭtentyfikacyja dlia ŭvachodu ŭ lakaĺny kantejnier." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Uvajsci ŭ lakaĺny vuziel" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "Nieabchodna aŭtentyfikacyja dlia ŭvachodu ŭ lakaĺny vuziel." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Atrymać abalonku na lakaĺnym kantejniery" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia atrymannia abalonki na lakaĺnym kantejniery." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Atrymać abalonku na lakaĺnym vuzlie" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia atrymannia abalonki na lakaĺnym vuzlie." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Atrymać psieŭda TTY na lakaĺnym kantejniery" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia atrymannia psieŭda TTY na lakaĺnym " - "kantejniery." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Atrymać psieŭda TTY na lakaĺnym vuzlie" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia atrymannia psieŭda TTY na lakaĺnym vuzlie." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Kiravać lakaĺnymi virtuaĺnymi mašynami abo kantejnierami" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia kiravannia lakaĺnymi virtuaĺnymi mašynami i " - "kantejnierami." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Kiravać vobrazami lakaĺnych virtuaĺnych mašyn i kantejnieraŭ" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." -@@ -533,28 +714,262 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia kiravannia vobrazami lakaĺnych virtuaĺnych " - "mašyn i kantejnieraŭ." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha času." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha času." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Nieabchodna aŭtentyfikacyja dlia spyniennia '$(unit)'." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia imia vuzla." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Nieabchodna aŭtentyfikacyja dlia ŭvachodu ŭ lakaĺny vuziel." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia imia vuzla." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaj lakali." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha času." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha času." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭsieahuĺnaha paviedamliennia" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭsieahuĺnaha paviedamliennia" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu systemd." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "Nieabchodna aŭtentyfikacyja dlia impartu vobraza VM abo kantejniera" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia dalučennia prylad da pracoŭnych miescaŭ." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "Nieabchodna aŭtentyfikacyja dlia spampoŭki vobraza VM abo kantejniera" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭsieahuĺnaha paviedamliennia" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭsieahuĺnaha paviedamliennia" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnych nalad klavijatury." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Ustaliavać sistemny čas" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha času." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Ustaliavać sistemny časavy pojas" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha časavoha pojasu." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "Ustaliavać časavy pojas (miascovy abo UTC), u jakim RTC zachoŭvaje čas" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -562,11 +977,11 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia časavoha pojasu (miascovy abo " - "UTC), u jakim zachoŭvajecca čas u RTC." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Ukliučyć abo vykliučyć sinchranizacyju času pa sietcy" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -574,32 +989,59 @@ msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭkliučennia abo vykliučennia sinchranizacyi " - "času pa sietcy." - --#: ../src/core/dbus-unit.c:450 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Nieabchodna aŭtentyfikacyja dlia zapusku '$(unit)'." - --#: ../src/core/dbus-unit.c:451 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Nieabchodna aŭtentyfikacyja dlia spyniennia '$(unit)'." - --#: ../src/core/dbus-unit.c:452 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu '$(unit)'." - --#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Nieabchodna aŭtentyfikacyja dlia pierazapusku '$(unit)'." - --#: ../src/core/dbus-unit.c:560 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Nieabchodna aŭtentyfikacyja dlia zabojstva '$(unit)'." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭlascivasciej '$(unit)'." - --#: ../src/core/dbus-unit.c:590 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia anuliavannia pamylkovaha stanu '$(unit)'." - --#: ../src/core/dbus-unit.c:622 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "" - "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭlascivasciej '$(unit)'." -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia anuliavannia pamylkovaha stanu '$(unit)'." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Nieabchodna aŭtentyfikacyja dlia anuliavannia pamylkovaha stanu '$(unit)'." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Nieabchodna aŭtentyfikacyja dlia zabojstva '$(unit)'." -diff --git a/po/bg.po b/po/bg.po -index 0e1f507..cb7eaac 100644 ---- a/po/bg.po -+++ b/po/bg.po -@@ -8,7 +8,7 @@ msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2016-05-14 13:28+0300\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2016-05-14 13:28+0300\n" - "Last-Translator: Alexander Shopov \n" - "Language-Team: Bulgarian \n" -@@ -18,41 +18,41 @@ msgstr "" - "Content-Transfer-Encoding: 8bit\n" - "Plural-Forms: nplurals=2; plural=(n != 1);\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Изпращане на паролата към системата" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "За изпращане на паролата към системата е необходима идентификация." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Управление на услугите или другите модули" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" - "За управление на услугите или другите модули е необходима идентификация." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Управление на файловете за услугите или другите модули" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" - "За управление на файловете за услугите или другите модули е необходима " - "идентификация." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "" - "Задаване или изтриване на променливи на средата за системата и управлението " - "на услугите" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -60,136 +60,216 @@ msgstr "" - "За задаване или изтриване на променливи на средата за системата и " - "управлението на услугите е необходима идентификация." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Презареждане на състоянието на systemd" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "За презареждане на състоянието на systemd е необходима идентификация." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "За презареждане на състоянието на systemd е необходима идентификация." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "За презареждане на състоянието на systemd е необходима идентификация." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"За управление на работещите сесии, потребители и работни места е необходима " -+"идентификация." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"За позволяване на закачане на устройства към работните места е необходима " -+"идентификация." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "За задаване на системно съобщение „wall“ е необходима идентификация." -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"За управление на работещите сесии, потребители и работни места е необходима " -+"идентификация." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Задаване на име на машината" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "За задаване на име на локалната машина е необходима идентификация." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Задаване на статично име на машината" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." - msgstr "" - "За задаване на статично име на локалната машина е необходима идентификация." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Задаване на информация за машината" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "" - "За задаване на информация за локалната машина е необходима идентификация." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "За презареждане на „$(unit)“ е необходима идентификация." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Внасяне на изображение на виртуална машина или контейнер" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "" - "За внасяне на изображение на виртуална машина или контейнер е необходима " - "идентификация." - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "Изнасяне на изображение на виртуална машина или контейнер" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "" - "За изнасяне на изображение на виртуална машина или контейнер е необходима " - "идентификация." - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "Изтегляне на изображение на виртуална машина или контейнер" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "" - "За изтегляне на изображение на виртуална машина или контейнер е необходима " - "идентификация." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Задаване на локала на системата" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "За задаване на локала на системата е необходима идентификация." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Задаване на настройките на клавиатурата" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "За задаване на настройките на клавиатурата е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Позволяване на програмите да предотвратяват спирането на системата" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - "За позволяване на програмите да предотвратяват спирането на системата е " - "необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Позволяване на програмите да забавят спирането на системата" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "За позволяване на програмите да забавят спирането на системата е необходима " - "идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Позволяване на програмите да предотвратяват приспиването на системата" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "За позволяване на програмите да предотвратяват приспиването на системата е " - "необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Позволяване на програмите да забавят приспиването на системата" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "За позволяване на програмите да забавят приспиването на системата е " - "необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "" - "Позволяване на програмите да предотвратяват автоматичното приспиване на " - "системата" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -197,13 +277,13 @@ msgstr "" - "За позволяване на програмите да предотвратяват автоматичното приспиване на " - "системата е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" - "Позволяване на програмите да предотвратяват реакцията на системата при " - "натискане на клавиша за захранване" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." -@@ -211,13 +291,13 @@ msgstr "" - "За позволяване на програмите да предотвратяват реакцията на системата при " - "натискане на клавиша за захранване е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" - "Позволяване на програмите да предотвратяват реакцията на системата при " - "натискане на клавиша за приспиване" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." -@@ -225,13 +305,13 @@ msgstr "" - "За позволяване на програмите да предотвратяват реакцията на системата при " - "натискане на клавиша за приспиване е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" - "Позволяване на програмите да предотвратяват реакцията на системата при " - "натискане на клавиша за дълбоко приспиване" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -239,13 +319,13 @@ msgstr "" - "За позволяване на програмите да предотвратяват реакцията на системата при " - "натискане на клавиша за дълбоко приспиване е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" - "Позволяване на програмите да предотвратяват реакцията на системата при " - "затваряне на екрана" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -253,64 +333,63 @@ msgstr "" - "За позволяване на програмите да предотвратяват реакцията на системата при " - "затваряне на екрана е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" - msgstr "" - "Позволяване на потребители, които не са се идентифицирали, да изпълняват " - "програми" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" - "За позволяване на потребители, които не са се идентифицирали, да изпълняват " - "програми е необходима изрична заявка." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "" - "Позволяване на потребители, които не са се идентифицирали, да изпълняват " - "програми" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "За позволяване на потребители, които не са се идентифицирали, да изпълняват " - "програми е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Позволяване на закачане на устройства към работните места" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "" - "За позволяване на закачане на устройства към работните места е необходима " - "идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Изчистване на връзките между устройствата и работните места" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "За изчистване на връзките между устройствата и работните места е необходима " - "идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Изключване на системата" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "За изключване на системата е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Изключване на системата, дори когато има други вписани потребители" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -318,64 +397,115 @@ msgstr "" - "За изключване на системата, дори когато има други вписани потребители, е " - "необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "Изключване на системата, дори когато програма иска да предотврати това" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "За изключване на системата, дори когато програма иска да предотврати това, е " - "необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Рестартиране на системата" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "За рестартиране на системата е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Рестартиране на системата, дори когато има други вписани потребители" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "За рестартиране на системата, дори когато има други вписани потребители, е " - "необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "" - "Рестартиране на системата, дори когато програма иска да предотврати това" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "За рестартиране на системата, дори когато програма иска да предотврати това, " - "е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "Дълбоко приспиване на системата" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "За дълбоко приспиване на системата е необходима идентификация." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "" -+"Дълбоко приспиване на системата, дори когато има други вписани потребители" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"За дълбоко приспиване на системата, дори когато има други вписани " -+"потребители, е необходима идентификация." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "" -+"Дълбоко приспиване на системата, дори когато програма иска да предотврати " -+"това" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"За дълбоко приспиване на системата, дори когато програма иска да предотврати " -+"това, е необходима идентификация." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Приспиване на системата" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "За приспиване на системата е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Приспиване на системата, дори когато има други вписани потребители" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -383,32 +513,32 @@ msgstr "" - "За приспиване на системата, дори когато има други вписани потребители, е " - "необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "Приспиване на системата, дори когато програма иска да предотврати това" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "За приспиване на системата, дори когато програма иска да предотврати това, е " - "необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Дълбоко приспиване на системата" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "За дълбоко приспиване на системата е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "" - "Дълбоко приспиване на системата, дори когато има други вписани потребители" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -416,46 +546,57 @@ msgstr "" - "За дълбоко приспиване на системата, дори когато има други вписани " - "потребители, е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "" - "Дълбоко приспиване на системата, дори когато програма иска да предотврати " - "това" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "За дълбоко приспиване на системата, дори когато програма иска да предотврати " - "това, е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Управление на работещите сесии, потребители и работни места" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "За управление на работещите сесии, потребители и работни места е необходима " - "идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Заключване или отключване на работещите сесии" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "" - "За заключване или отключване на работещите сесии е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "За задаване на часовия пояс на системата е необходима идентификация." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "" - "Позволяване на заявки към фърмуера да стартира с интерфейса за управление" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -463,83 +604,125 @@ msgstr "" - "За позволяване на заявки към фърмуера да стартира с интерфейса за управление " - "е необходима идентификация." - --#: ../src/login/org.freedesktop.login1.policy.in.h:57 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"За позволяване на заявки към фърмуера да стартира с интерфейса за управление " -+"е необходима идентификация." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"За позволяване на заявки към фърмуера да стартира с интерфейса за управление " -+"е необходима идентификация." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Задаване на системно съобщение „wall“" - --#: ../src/login/org.freedesktop.login1.policy.in.h:58 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "За задаване на системно съобщение „wall“ е необходима идентификация." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "За задаване на име на локалната машина е необходима идентификация." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Вписване в локален контейнер" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "За вписване в локален контейнер е необходима идентификация." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Вписване в локалната машина" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "За вписване в локалната машина е необходима идентификация." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Достъп до обвивка в локален контейнер" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "За достъп до обвивка в локален контейнер е необходима идентификация." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Достъп до обвивка на локалната машина" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "За достъп до обвивка на локалната машина е необходима идентификация." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Получаване на псевдо терминал в локален контейнер" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" - "За получаване на псевдо терминал в локален контейнер е необходима " - "идентификация." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Получаване на псевдо терминал на локалната машина" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "" - "За получаване на псевдо терминал на локалната машина е необходима " - "идентификация." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Управление на локалните виртуални машини и контейнери" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" - "За управление на локалните виртуални машини и контейнери е необходима " - "идентификация." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Управление на изображения на виртуални машини или контейнери" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." -@@ -547,27 +730,261 @@ msgstr "" - "За управление на изображения на виртуални машини или е необходима " - "идентификация." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "За задаване на времето на системата е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "За задаване на времето на системата е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "За спиране на „$(unit)“ е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "За задаване на име на локалната машина е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "За дълбоко приспиване на системата е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "За вписване в локалната машина е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "За задаване на име на локалната машина е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "За дълбоко приспиване на системата е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "За задаване на локала на системата е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "За задаване на времето на системата е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "За задаване на времето на системата е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "За задаване на системно съобщение „wall“ е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "За задаване на системно съобщение „wall“ е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "За презареждане на състоянието на systemd е необходима идентификация." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "За рестартиране на системата е необходима идентификация." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "" -+"За внасяне на изображение на виртуална машина или контейнер е необходима " -+"идентификация." -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "" -+"За позволяване на закачане на устройства към работните места е необходима " -+"идентификация." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "" -+"За изтегляне на изображение на виртуална машина или контейнер е необходима " -+"идентификация." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "За задаване на системно съобщение „wall“ е необходима идентификация." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "За задаване на системно съобщение „wall“ е необходима идентификация." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "За задаване на настройките на клавиатурата е необходима идентификация." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Задаване на времето на системата" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "За задаване на времето на системата е необходима идентификация." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Задаване на часовия пояс на системата" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "За задаване на часовия пояс на системата е необходима идентификация." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "Превключване на системния часовник между местния часови пояс и UTC" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -575,11 +992,11 @@ msgstr "" - "За превключване на системния часовник между местния часови пояс и UTC е " - "необходима идентификация." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Превключване на синхронизацията на времето по мрежата" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -587,32 +1004,60 @@ msgstr "" - "За превключване на синхронизацията на времето по мрежата е необходима " - "идентификация." - --#: ../src/core/dbus-unit.c:450 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "За стартиране на „$(unit)“ е необходима идентификация." - --#: ../src/core/dbus-unit.c:451 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "За спиране на „$(unit)“ е необходима идентификация." - --#: ../src/core/dbus-unit.c:452 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "За презареждане на „$(unit)“ е необходима идентификация." - --#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "За рестартиране на „$(unit)“ е необходима идентификация." - --#: ../src/core/dbus-unit.c:560 --msgid "Authentication is required to kill '$(unit)'." --msgstr "За убиване на „$(unit)“ е необходима идентификация." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "За задаване на свойствата на „$(unit)“ е необходима идентификация." - --#: ../src/core/dbus-unit.c:590 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "За премахване на състоянието за неуспех на „$(unit)“ е необходима " - "идентификация." - --#: ../src/core/dbus-unit.c:622 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "За задаване на свойствата на „$(unit)“ е необходима идентификация." -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"За премахване на състоянието за неуспех на „$(unit)“ е необходима " -+"идентификация." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"За премахване на състоянието за неуспех на „$(unit)“ е необходима " -+"идентификация." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "За убиване на „$(unit)“ е необходима идентификация." -diff --git a/po/ca.po b/po/ca.po -index 68123ca..76b2c60 100644 ---- a/po/ca.po -+++ b/po/ca.po -@@ -1,5 +1,5 @@ - # SPDX-License-Identifier: LGPL-2.1+ --# -+# - # Catalan translation for systemd. - # Walter Garcia-Fontes , 2016. - # Robert Antoni Buj Gelonch , 2018. #zanata -@@ -7,14 +7,14 @@ msgid "" - msgstr "" - "Project-Id-Version: systemd\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2018-02-19 13:32+0100\n" --"MIME-Version: 1.0\n" --"Content-Type: text/plain; charset=UTF-8\n" --"Content-Transfer-Encoding: 8bit\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2018-02-27 04:18-0500\n" - "Last-Translator: Robert Antoni Buj Gelonch \n" - "Language-Team: Català \n" - "Language: ca\n" -+"MIME-Version: 1.0\n" -+"Content-Type: text/plain; charset=UTF-8\n" -+"Content-Transfer-Encoding: 8bit\n" - "Plural-Forms: nplurals=2; plural=(n != 1);\n" - "X-Generator: Zanata 3.9.6\n" - -@@ -25,10 +25,8 @@ msgstr "Retorna la frase de pas al sistema" - #: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." --"" - msgstr "" - "Es requereix autenticació per retornar la frase de pas introduïda al sistema." --"" - - #: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" -@@ -50,13 +48,13 @@ msgstr "" - "Es requereix autenticació per gestionar un servei del sistema o bé fitxers " - "d'unitats." - --#: src/core/org.freedesktop.systemd1.policy.in:53 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "" - "Estableix o desestableix les variables d'entorn del gestor de serveis o del " - "sistema" - --#: src/core/org.freedesktop.systemd1.policy.in:54 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -64,27 +62,96 @@ msgstr "" - "Es requereix autenticació per establir o desestablir les variables d'entorn " - "del gestor de serveis o del sistema." - --#: src/core/org.freedesktop.systemd1.policy.in:63 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Torna a carregar l'estat de systemd" - --#: src/core/org.freedesktop.systemd1.policy.in:64 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "Es requereix autenticació per tornar a carregar l'estat de systemd." - --#: src/hostname/org.freedesktop.hostname1.policy:22 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Es requereix autenticació per tornar a carregar l'estat de systemd." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Es requereix autenticació per tornar a carregar l'estat de systemd." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Es requereix autenticació per gestionar les sessions, usuaris i llocs de " -+"treball actius." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"Es requereix autenticació per annexar un dispositiu a un lloc de treball." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Es requereix autenticació per establir un missatge de mur" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Es requereix autenticació per gestionar les sessions, usuaris i llocs de " -+"treball actius." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Estableix el nom d'amfitrió" - --#: src/hostname/org.freedesktop.hostname1.policy:23 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Es requereix autenticació per establir el nom d'amfitrió local." - --#: src/hostname/org.freedesktop.hostname1.policy:32 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Estableix el nom d'amfitrió estàtic" - --#: src/hostname/org.freedesktop.hostname1.policy:33 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -92,15 +159,25 @@ msgstr "" - "Es requereix autenticació per establir el nom d'amfitrió local configurat " - "estàticament, així com el nom bonic d'amfitrió." - --#: src/hostname/org.freedesktop.hostname1.policy:43 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Estableix la informació de la màquina" - --#: src/hostname/org.freedesktop.hostname1.policy:44 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "" - "Es requereix autenticació per establir la informació de la màquina local." - -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Es requereix autenticació per tornar a carregar «$(unit)»." -+ - #: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Importa una màquina virtual o una imatge de contenidor" -@@ -165,8 +242,7 @@ msgid "Allow applications to delay system shutdown" - msgstr "Permet a les aplicacions endarrerir l'apagada del sistema" - - #: src/login/org.freedesktop.login1.policy:34 --msgid "" --"Authentication is required for an application to delay system shutdown." -+msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "Es requereix autenticació perquè una aplicació endarrereixi l'apagada del " - "sistema." -@@ -292,8 +368,7 @@ msgid "Flush device to seat attachments" - msgstr "Allibera els dispositius a les annexions dels llocs de treball" - - #: src/login/org.freedesktop.login1.policy:149 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Es requereix autenticació per restablir com s'annexionen els dispositius als " - "llocs de treball." -@@ -324,8 +399,8 @@ msgstr "Apaga el sistema mentre hi ha una aplicació que ha demanat inhibir-ho" - - #: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Es requereix autenticació per apagar el sistema mentre hi ha una aplicació " - "que ha demanat inhibir-ho." -@@ -344,8 +419,8 @@ msgstr "Reinicia el sistema mentre hi ha usuaris amb la sessió iniciada" - - #: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Es requereix autenticació per reiniciar el sistema mentre hi ha usuaris amb " - "la sessió iniciada." -@@ -357,8 +432,8 @@ msgstr "" - - #: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Es requereix autenticació per reiniciar el sistema mentre hi ha una " - "aplicació que ha demanat inhibir-ho." -@@ -377,8 +452,8 @@ msgstr "Atura el sistema mentre hi ha altres usuaris amb la sessió iniciada" - - #: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "" - "Es requereix autenticació per aturar el sistema mentre hi ha altres usuaris " - "amb la sessió iniciada." -@@ -389,11 +464,15 @@ msgstr "" - "Atura el sistema mentre hi ha una aplicació que ha demanat d'inhibir-ho" - - #: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." -+"Authentication is required to halt the system while an application is " -+"inhibiting this." - msgstr "" --"Es requereix autenticació per aturar el sistema mentre hi ha una aplicació " -+"Es requereix autenticació per hibernar el sistema mentre hi ha una aplicació " - "que ha demanat d'inhibir-ho." - - #: src/login/org.freedesktop.login1.policy:257 -@@ -423,8 +502,8 @@ msgstr "" - - #: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Es requereix autenticació per suspendre el sistema mentre hi ha una " - "aplicació que ha demanat d'inhibir-ho." -@@ -456,8 +535,8 @@ msgstr "" - - #: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Es requereix autenticació per hibernar el sistema mentre hi ha una aplicació " - "que ha demanat d'inhibir-ho." -@@ -467,8 +546,7 @@ msgid "Manage active sessions, users and seats" - msgstr "Gestiona les sessions, usuaris i llocs de treball actius" - - #: src/login/org.freedesktop.login1.policy:322 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Es requereix autenticació per gestionar les sessions, usuaris i llocs de " - "treball actius." -@@ -483,12 +561,24 @@ msgstr "" - "Es requereix autenticació per bloquejar o desbloquejar les sessions actives." - - #: src/login/org.freedesktop.login1.policy:341 --msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Es requereix autenticació per establir la zona horària del sistema." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "" - "Permet la indicació al microprogramari en l'arrencada perquè prepari la " - "interfície" - --#: src/login/org.freedesktop.login1.policy:342 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -496,22 +586,63 @@ msgstr "" - "Es requereix autenticació per indicar al microprogramari en l'arrencada " - "perquè prepari la interfície." - --#: src/login/org.freedesktop.login1.policy:351 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Es requereix autenticació per indicar al microprogramari en l'arrencada " -+"perquè prepari la interfície." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Es requereix autenticació per indicar al microprogramari en l'arrencada " -+"perquè prepari la interfície." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Estableix un missatge de mur" - --#: src/login/org.freedesktop.login1.policy:352 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Es requereix autenticació per establir un missatge de mur" - -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to halt the system." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Es requereix autenticació per aturar el sistema." -+ - #: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Inicia la sessió a un contenidor local" - - #: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." --msgstr "" --"Es requereix autenticació per iniciar la sessió a un contenidor local." -+msgstr "Es requereix autenticació per iniciar la sessió a un contenidor local." - - #: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" -@@ -580,6 +711,212 @@ msgstr "" - "Es requereix autenticació per gestionar les màquines virtuals i les imatges " - "dels contenidors locals." - -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Es requereix autenticació per establir l'hora del sistema." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+#, fuzzy -+#| msgid "Register a DNS-SD service" -+msgid "Set DNS servers" -+msgstr "Registra un servei DNS-SD" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to set DNS servers." -+msgstr "Es requereix autenticació per registrar un servei DNS-SD" -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Es requereix autenticació per aturar «$(unit)»." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Es requereix autenticació per establir el nom d'amfitrió local." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Es requereix autenticació per hibernar el sistema." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Es requereix autenticació per iniciar la sessió a l'amfitrió local." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Es requereix autenticació per registrar un servei DNS-SD" -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Es requereix autenticació per hibernar el sistema." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "" -+"Es requereix autenticació per establir la configuració regional del sistema." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Es requereix autenticació per establir l'hora del sistema." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Es requereix autenticació per establir l'hora del sistema." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Es requereix autenticació per establir un missatge de mur" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Es requereix autenticació per establir un missatge de mur" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Es requereix autenticació per tornar a carregar l'estat de systemd." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Es requereix autenticació per reiniciar el sistema." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "" -+"Es requereix autenticació per importar una màquina virtual o una imatge de " -+"contenidor" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "" -+"Es requereix autenticació per annexar un dispositiu a un lloc de treball." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "" -+"Es requereix autenticació per baixar una màquina virtual o una imatge de " -+"contenidor" -+ - #: src/resolve/org.freedesktop.resolve1.policy:22 - msgid "Register a DNS-SD service" - msgstr "Registra un servei DNS-SD" -@@ -596,6 +933,17 @@ msgstr "Desregistra un servei DNS-SD" - msgid "Authentication is required to unregister a DNS-SD service" - msgstr "Es requereix autenticació per desregistrar un servei DNS-SD" - -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Es requereix autenticació per establir els ajusts del teclat del sistema." -+ - #: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Estableix l'hora del sistema" -@@ -624,11 +972,11 @@ msgstr "" - "Es requereix autenticació per controlar si el rellotge del sistema " - "emmagatzema l'hora local o l'UTC." - --#: src/timedate/org.freedesktop.timedate1.policy:54 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Activa o desactiva la sincronització de l'hora de xarxa" - --#: src/timedate/org.freedesktop.timedate1.policy:55 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -636,32 +984,61 @@ msgstr "" - "Es requereix autenticació per controlar si s'ha d'activar la sincronització " - "de l'hora de xarxa." - --#: src/core/dbus-unit.c:496 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Es requereix autenticació per iniciar «$(unit)»." - --#: src/core/dbus-unit.c:497 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Es requereix autenticació per aturar «$(unit)»." - --#: src/core/dbus-unit.c:498 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Es requereix autenticació per tornar a carregar «$(unit)»." - --#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Es requereix autenticació per reiniciar «$(unit)»." - --#: src/core/dbus-unit.c:607 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Es requereix autenticació per matar «$(unit)»." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "Es requereix autenticació per establir les propietats a «$(unit)»." - --#: src/core/dbus-unit.c:638 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." --msgstr "" --"Es requereix autenticació per restablir l'estat «failed» de «$(unit)»." -+msgstr "Es requereix autenticació per restablir l'estat «failed» de «$(unit)»." - --#: src/core/dbus-unit.c:671 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Es requereix autenticació per establir les propietats a «$(unit)»." - -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "Es requereix autenticació per restablir l'estat «failed» de «$(unit)»." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "Es requereix autenticació per restablir l'estat «failed» de «$(unit)»." -+ -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "" -+#~ "Es requereix autenticació per aturar el sistema mentre hi ha una " -+#~ "aplicació que ha demanat d'inhibir-ho." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Es requereix autenticació per matar «$(unit)»." -diff --git a/po/cs.po b/po/cs.po -index 8805dce..ee48ee7 100644 ---- a/po/cs.po -+++ b/po/cs.po -@@ -6,8 +6,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2020-05-30 13:27+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2020-07-01 16:40+0200\n" - "Last-Translator: Daniel Rusek \n" - "Language-Team: Czech\n" -@@ -861,37 +861,37 @@ msgid "" - "shall be enabled." - msgstr "Pro kontrolu synchronizace času ze sítě je vyžadováno ověření." - --#: src/core/dbus-unit.c:358 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Pro spuštění „$(unit)” je vyžadováno ověření." - --#: src/core/dbus-unit.c:359 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Pro vypnutí „$(unit)” je vyžadováno ověření." - --#: src/core/dbus-unit.c:360 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Pro opětovné načtení „$(unit)” je vyžadováno ověření." - --#: src/core/dbus-unit.c:361 src/core/dbus-unit.c:362 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Pro restart „$(unit)” je vyžadováno ověření." - --#: src/core/dbus-unit.c:534 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." - msgstr "Pro odeslání UNIX signálu procesům „$(unit)” je vyžadováno ověření." - --#: src/core/dbus-unit.c:565 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "Pro resetování chybného stavu „$(unit)” je vyžadováno ověření." - --#: src/core/dbus-unit.c:598 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Pro nastavení vlastností na „$(unit)” je vyžadováno ověření." - --#: src/core/dbus-unit.c:707 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." -@@ -899,7 +899,7 @@ msgstr "" - "Pro odstranění souborů nebo adresářů souvisejících s „$(unit)” je vyžadováno " - "ověření." - --#: src/core/dbus-unit.c:756 -+#: src/core/dbus-unit.c:760 - msgid "" - "Authentication is required to freeze or thaw the processes of '$(unit)' unit." - msgstr "" -diff --git a/po/da.po b/po/da.po -index 276c9e1..8537a21 100644 ---- a/po/da.po -+++ b/po/da.po -@@ -6,8 +6,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2015-10-07 19:30+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2015-10-07 19:30+0200\n" - "Last-Translator: Daniel Machon \n" - "Language-Team: Danish\n" -@@ -17,67 +17,142 @@ msgstr "" - "Content-Transfer-Encoding: 8bit\n" - "Plural-Forms: nplurals=2; plural=(n != 1);\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Send adgangssætning tilbage til systemet" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "" --"Autentificering er nødvendig for at sende adgangssætning tilbage til systemet." -+"Autentificering er nødvendig for at sende adgangssætning tilbage til " -+"systemet." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Håndtér system services eller andre enheder" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" --"Autentificering er nødvendig for at håndtere system services og andre enheder." -+"Autentificering er nødvendig for at håndtere system services og andre " -+"enheder." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Håndtér system services eller enhedsfiler" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" --"Autentificering er nødvendig for at håndtere system service eller enhedsfiler." -+"Autentificering er nødvendig for at håndtere system service eller " -+"enhedsfiler." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" --msgstr "" --"Sæt eller fjern system- og service-forvalter miljøvariabler" -+msgstr "Sæt eller fjern system- og service-forvalter miljøvariabler" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." --msgstr "Autentificering er nødvendig for at sætte eller fjerne system- " --"og service-forvalter miljøvariabler." -+msgstr "" -+"Autentificering er nødvendig for at sætte eller fjerne system- og service-" -+"forvalter miljøvariabler." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Genindlæs systemd tilstand" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+# www.freedesktop.org/wiki/Software/systemd/multiseat/ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Autentificering er nødvendig for at håndtere aktive sessioner, brugere og " -+"arbejdsstationer." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+# www.freedesktop.org/wiki/Software/systemd/multiseat/ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"Autentificering er nødvendig for at montere en enhed til en arbejdsstation." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Autentificering er nødvendig for at sætte en broadcast-besked" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+# www.freedesktop.org/wiki/Software/systemd/multiseat/ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Autentificering er nødvendig for at håndtere aktive sessioner, brugere og " -+"arbejdsstationer." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Sæt værtsnavn" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Autentificering er nødvendig for at sætte værtsnavn." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Sæt statisk værstnavn" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -85,104 +160,116 @@ msgstr "" - "Autentificering er nødvendig for at sætte det statisk konfigurerede lokale " - "værtsnavn, lige så vel som det pæne værtsnavn." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Sæt maskininformation." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "Autentificering er nødvendig for at sætte lokal maskininformation." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Autentificering er nødvendig for at genindlæse '$(unit)'." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Importér en VM eller container billede" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "" --"Autentificering er nødvendig for at importére en VM eller " --"container billeder." -+"Autentificering er nødvendig for at importére en VM eller container billeder." - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "Exportér en VM eller container billede" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" --msgstr "Autentificering er nødvendig for at exportére en VM eller container billede" -+msgstr "" -+"Autentificering er nødvendig for at exportére en VM eller container billede" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "Hent en VM eller container billede" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" --msgstr "Autentificering er nødvendig for at hente en VM eller container billede" -+msgstr "" -+"Autentificering er nødvendig for at hente en VM eller container billede" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Sæt sprogindstillinger for systemet" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "" --"Autentificering er nødvendig for at sætte sprogindstillinger " --"for systemet." -+"Autentificering er nødvendig for at sætte sprogindstillinger for systemet." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Sæt tastaturindstillinger for systemet." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" --"Autentificering er nødvendig for at sætte tastaturindstillinger " --"for systemet." -+"Autentificering er nødvendig for at sætte tastaturindstillinger for systemet." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Tillad applikationer at hæmme system nedlukning" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" --"Autentificering er nødvendig for at en applikation kan hæmme " --"system nedlukning." -+"Autentificering er nødvendig for at en applikation kan hæmme system " -+"nedlukning." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Tillad applikationer at forsinke system nedlukning" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" --"Autentificering er nødvendig for at en applikation kan forsinke " --"system nedlukning." -+"Autentificering er nødvendig for at en applikation kan forsinke system " -+"nedlukning." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Tillad applikationer at hæmme system dvale" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 --msgid "Authentication is required for an application to inhibit system sleep" --msgstr "Autentificering er nødvendig for at en applikation kan hæmme system dvale" -+#: src/login/org.freedesktop.login1.policy:45 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required for an application to inhibit system sleep" -+msgid "Authentication is required for an application to inhibit system sleep." -+msgstr "" -+"Autentificering er nødvendig for at en applikation kan hæmme system dvale" - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Tillad applikationer at forsinke system dvale" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" --"Autentificering er nødvendig for at en applikation kan forsinke system " --"dvale." -+"Autentificering er nødvendig for at en applikation kan forsinke system dvale." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "Tillad applikationer at hæmme automatisk system standby" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -190,35 +277,35 @@ msgstr "" - "Autentificering er nødvendig for at en applikation kan hæmme automatisk " - "system standby." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "Tillad applikationer at hæmme systemhåndtering af tænd/sluk-knappen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." - msgstr "" --"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering " --"af tænd/sluk-knappen." -+"Autentificering er nødvendig for at en applikation kan hæmme " -+"systemhåndtering af tænd/sluk-knappen." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "Tillad applikationer at hæmme systemhåndtering af standby-knappen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." - msgstr "" --"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering " --"af standby-knappen." -+"Autentificering er nødvendig for at en applikation kan hæmme " -+"systemhåndtering af standby-knappen." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "Tillad applikationer at hæmme systemhåndtering af dvale-knappen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -226,133 +313,191 @@ msgstr "" - "Autentificering er nødvendig for at en applikation kan hæmme " - "systemhåndtering af dvale-knappen." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" --msgstr "" --"Tillad applikationer at hæmme systemhåndtering af skærmlukning" -+msgstr "Tillad applikationer at hæmme systemhåndtering af skærmlukning" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." - msgstr "" --"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering " --"af skærmlukning." -+"Autentificering er nødvendig for at en applikation kan hæmme " -+"systemhåndtering af skærmlukning." -+ -+#: src/login/org.freedesktop.login1.policy:117 -+#, fuzzy -+#| msgid "Allow non-logged-in users to run programs" -+msgid "Allow non-logged-in user to run programs" -+msgstr "Tillad brugere der ikke er logget ind, at køre programmer" -+ -+#: src/login/org.freedesktop.login1.policy:118 -+#, fuzzy -+#| msgid "Authentication is required to run programs as a non-logged-in user." -+msgid "Explicit request is required to run programs as a non-logged-in user." -+msgstr "" -+"Autentificering er nødvendig for at brugere, som ikke er logget ind, kan " -+"køre programmer." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "Tillad brugere der ikke er logget ind, at køre programmer" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Autentificering er nødvendig for at brugere, som ikke er logget ind, kan " - "køre programmer." - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Tillad at montere af enheder til arbejdsstationer" - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "" --"Autentificering er nødvendig for at montere en enhed til en " --"arbejdsstation." -+"Autentificering er nødvendig for at montere en enhed til en arbejdsstation." - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Nulstil enhed monteret til en arbejdsstation" - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:24 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Autentificering er nødvendig for at nulstille måden enheder er monteret " - "arbejdsstationer." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Sluk for systemet" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Autentificering er nødvendig for at slukke systemet" - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Sluk systemet mens andre brugere er logget på" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." - msgstr "" --"Autentificering er nødvendig for at slukke systemet mens andre brugere " --"er logget på." -+"Autentificering er nødvendig for at slukke systemet mens andre brugere er " -+"logget på." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" --msgstr "" --"Sluk for systemet mens en applikation har forespurgt at hæmme det" -+msgstr "Sluk for systemet mens en applikation har forespurgt at hæmme det" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Autentificering er nødvendig for at slukke systemet mens en applikation har " - "forespurgt at hæmme det." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Genstart systemet" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Autentificering er nødvendig for at genstarte systemet." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Genstart systemet mens andre brugere er logget ind" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" --"Autentificering er nødvendig for at genstarte systemet mens andre brugere " --"er logget ind." -+"Autentificering er nødvendig for at genstarte systemet mens andre brugere er " -+"logget ind." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" --msgstr "" --"Genstart systemet mens en applikation har forespurgt at hæmme det" -+msgstr "Genstart systemet mens en applikation har forespurgt at hæmme det" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Autentificering er nødvendig for at genstarte systemet mens en applikation " - "har forespurgt at hæmme det." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "Sæt systemet i dvale" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "Autentificering er nødvendig for at sætte systemet i dvale-tilstand." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "Sæt systemet i dvale-tilstand mens andre brugere er logget på" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"Autentificering er nødvendig for at sætte systemet i dvale-tilstand, mens " -+"andre brugere er logget på." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "" -+"Sæt systemet i dvale-tilstand mens en applikation har forespurgt at hæmme det" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"Autentificering er nødvendig for at sætte systemet i dvale tilstand, mens en " -+"applikation har forespurgt at hæmme det." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Sæt systemet på standby" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Autentificering er nødvendig for at sætte systemet på standby" - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Sæt systemet på standby mens andre brugere er logget på" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -360,35 +505,31 @@ msgstr "" - "Autentificering er nødvendig for at sætte systemet på standby, mens andre " - "brugere er logget på." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" --msgstr "" --"Sæt systemet på standby mens en applikation har forespurgt at hæmme" --"det" -+msgstr "Sæt systemet på standby mens en applikation har forespurgt at hæmmedet" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Autentificering er nødvendig for at sætte systemet på standby, mens en " - "applikation har forespurgt at hæmme det." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Sæt systemet i dvale" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." --msgstr "" --"Autentificering er nødvendig for at sætte systemet i dvale-tilstand." -+msgstr "Autentificering er nødvendig for at sætte systemet i dvale-tilstand." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" --msgstr "" --"Sæt systemet i dvale-tilstand mens andre brugere er logget på" -+msgstr "Sæt systemet i dvale-tilstand mens andre brugere er logget på" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -396,131 +537,185 @@ msgstr "" - "Autentificering er nødvendig for at sætte systemet i dvale-tilstand, mens " - "andre brugere er logget på." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" --msgstr "Sæt systemet i dvale-tilstand mens en applikation har forespurgt at " --"hæmme det" -+msgstr "" -+"Sæt systemet i dvale-tilstand mens en applikation har forespurgt at hæmme det" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" --"Autentificering er nødvendig for at sætte systemet i dvale tilstand, mens " --"en applikation har forespurgt at hæmme det." -+"Autentificering er nødvendig for at sætte systemet i dvale tilstand, mens en " -+"applikation har forespurgt at hæmme det." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Håndtér aktive sessioner, brugere og arbejdsstationer" - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:50 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" --"Autentificering er nødvendig for at håndtere aktive sessioner, brugere " --"og arbejdsstationer." -+"Autentificering er nødvendig for at håndtere aktive sessioner, brugere og " -+"arbejdsstationer." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Lås eller oplås aktive sessioner" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "" - "Autentificering er nødvendig for at låse eller oplåse aktive sessioner." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 --msgid "Allow indication to the firmware to boot to setup interface" --msgstr "Tillad meddelelse til firmwaren om at starte op i opsætningsgrænseflade" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Autentificering er nødvendig for at sætte tidszonen for systemet." - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" -+msgstr "" -+"Tillad meddelelse til firmwaren om at starte op i opsætningsgrænseflade" -+ -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." --msgstr "Autentificering er nødvendig for at meddele firmwaren om at starte " --"op i opsætningsgrænseflade." -+msgstr "" -+"Autentificering er nødvendig for at meddele firmwaren om at starte op i " -+"opsætningsgrænseflade." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Autentificering er nødvendig for at meddele firmwaren om at starte op i " -+"opsætningsgrænseflade." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Autentificering er nødvendig for at meddele firmwaren om at starte op i " -+"opsætningsgrænseflade." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Sæt broadcast-besked" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Autentificering er nødvendig for at sætte en broadcast-besked" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Autentificering er nødvendig for at sætte værtsnavn." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Log på en lokal container" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "Autentificering er nødvendig for at logge på en lokal container." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Log på den lokale vært" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "Auitentificering er nødvendig for at logge på den lokale vært." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Anskaf en shell i en lokal container" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" --"Autentificering er nødvendig for at anskaffe en shell i en lokal " --"container." -+"Autentificering er nødvendig for at anskaffe en shell i en lokal container." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Anskaf en shell på den lokale vært" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "" - "Autentificering er nødvendig for at anskaffe en shell på den lokale vært." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Anskaf en pseudo-TTY i en lokal container" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" - "Autentificering er nødvendig for at anskaffe en pseudo-TTY i en lokal " - "container." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Anskaf en pseudo-TTY på den lokale vært" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "" --"Autentificering er nødvendig for at anskaffe en pseudo-TTY på den " --"lokale vært." -+"Autentificering er nødvendig for at anskaffe en pseudo-TTY på den lokale " -+"vært." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Håndtér lokale virtuelle maskiner og containere" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" - "Autentificering er nødvendig for at håndtere lokale virtuelle maskiner og " - "containere." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Håndtér lokal virtuel maskine- og container billeder" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." -@@ -528,39 +723,273 @@ msgstr "" - "Autentificering er nødvendig for at håndtere lokal virtuel maskine- og " - "container billeder." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Autentificering er nødvendig for at sætte tiden for systemet." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "Autentificering er nødvendig for at sætte tiden for systemet." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Autentificering er nødvendig for at stoppe '$(unit)'." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Autentificering er nødvendig for at sætte værtsnavn." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Autentificering er nødvendig for at sætte systemet i dvale-tilstand." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Auitentificering er nødvendig for at logge på den lokale vært." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Autentificering er nødvendig for at sætte værtsnavn." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Autentificering er nødvendig for at sætte systemet i dvale-tilstand." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "" -+"Autentificering er nødvendig for at sætte sprogindstillinger for systemet." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Autentificering er nødvendig for at sætte tiden for systemet." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Autentificering er nødvendig for at sætte tiden for systemet." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Autentificering er nødvendig for at sætte en broadcast-besked" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Autentificering er nødvendig for at sætte en broadcast-besked" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Autentificering er nødvendig for at genstarte systemet." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "" -+"Autentificering er nødvendig for at importére en VM eller container billeder." -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+# www.freedesktop.org/wiki/Software/systemd/multiseat/ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "" -+"Autentificering er nødvendig for at montere en enhed til en arbejdsstation." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "" -+"Autentificering er nødvendig for at hente en VM eller container billede" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "Autentificering er nødvendig for at sætte en broadcast-besked" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "Autentificering er nødvendig for at sætte en broadcast-besked" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Autentificering er nødvendig for at sætte tastaturindstillinger for systemet." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Sæt tiden for systemet" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "Autentificering er nødvendig for at sætte tiden for systemet." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Sæt tidszone for systemet" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "Autentificering er nødvendig for at sætte tidszonen for systemet." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "Sæt RTC til lokal tidszone eller UTC" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." - msgstr "" --"Autentificering er nødvendig for at kontrollere hvorvidt RTC'en gemmer " --"den lokale tid eller UTC tid." -+"Autentificering er nødvendig for at kontrollere hvorvidt RTC'en gemmer den " -+"lokale tid eller UTC tid." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Slå synkronisering af netværkstid til eller fra" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -568,35 +997,63 @@ msgstr "" - "Autentificering er nødvendig for at kontrollere hvorvidt synkronisering af " - "netværkstid skal aktiveres" - --#: ../src/core/dbus-unit.c:428 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Autentificering er nødvendig for at starte '$(unit)'." - --#: ../src/core/dbus-unit.c:429 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Autentificering er nødvendig for at stoppe '$(unit)'." - --#: ../src/core/dbus-unit.c:430 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Autentificering er nødvendig for at genindlæse '$(unit)'." - --#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Autentificering at nødvendig for at genstarte '$(unit)'." - --#: ../src/core/dbus-unit.c:535 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Autentificering er nødvendig for at eliminere '$(unit)'." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "Autentificering er nødvendig for at sætte egenskaber på '$(unit)'." - --#: ../src/core/dbus-unit.c:565 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" --"Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på '$(unit)'." -+"Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på " -+"'$(unit)'." - --#: ../src/core/dbus-unit.c:597 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." -+msgstr "Autentificering er nødvendig for at sætte egenskaber på '$(unit)'." -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." - msgstr "" --"Autentificering er nødvendig for at sætte egenskaber på '$(unit)'." -+"Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på " -+"'$(unit)'." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på " -+"'$(unit)'." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Autentificering er nødvendig for at eliminere '$(unit)'." - - #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" - #~ msgstr "" -diff --git a/po/de.po b/po/de.po -index c5c753b..eac78e7 100644 ---- a/po/de.po -+++ b/po/de.po -@@ -8,8 +8,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2015-09-19 12:09+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2015-09-19 20:02+0200\n" - "Last-Translator: Bernd Homuth \n" - "Language-Team: Deutsch \n" -@@ -20,69 +20,142 @@ msgstr "" - "Plural-Forms: nplurals=2; plural=(n != 1);\n" - "X-Generator: Gtranslator 2.91.6\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Passphrase zurück an das System senden" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "" - "Legitimierung ist zum Senden des eingegebenen Kennworts zurück an das System " - "notwendig." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Systemdienste und andere Einheiten verwalten" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" - "Legitimierung ist notwendig für die Verwaltung von Systemdiensten und " - "anderen Einheiten." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Systemdienste und Einheitendateien verwalten" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" - "Legitimierung ist notwendig für die Verwaltung von Systemdiensten und " - "Einheitendateien." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "" - "Umgebungsvariablen der System- und Dienstverwaltung festlegen oder entfernen" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." - msgstr "Legitimierung ist notwendig für die System- und Dienstverwaltung." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Den systemd-Zustand neu laden" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "Legitimierung ist zum erneuten Laden des systemd-Zustands notwendig." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Legitimierung ist zum erneuten Laden des systemd-Zustands notwendig." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Legitimierung ist zum erneuten Laden des systemd-Zustands notwendig." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+# www.freedesktop.org/wiki/Software/systemd/multiseat/ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Legitimierung ist zur Verwaltung aktiver Sitzungen, Benutzern und " -+"Arbeitsstationen notwendig." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+# www.freedesktop.org/wiki/Software/systemd/multiseat/ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"Legitimierung ist zum Anschließen eines Geräts an eine Arbeitsstation " -+"notwendig." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+# www.freedesktop.org/wiki/Software/systemd/multiseat/ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Legitimierung ist zur Verwaltung aktiver Sitzungen, Benutzern und " -+"Arbeitsstationen notwendig." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Rechnername festlegen" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Legitimierung ist zum Festlegen des lokalen Rechnernamens notwendig" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Statischen Rechnernamen festlegen" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -90,112 +163,122 @@ msgstr "" - "Authentifizierung ist erforderlich, um den statisch geänderten, lokalen " - "Rechnernamen, sowie den beschönigten Rechnernamen festzulegen." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Maschinen-Information festlegen" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "" - "Legitimierung ist zum Festlegen der lokalen Maschinen-Information " - "erforderlich." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Legitimierung ist zum erneuten Laden von »$(unit)« notwendig." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Abbild einer VM oder eines Containers importieren" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "" - "Legitimierung ist zum Importieren eines VM- oder Containerabbilds " - "erforderlich" - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "Abbild einer VM oder eines Containers exportieren" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "" - "Legitimierung ist zum Exportieren eines VM- oder Containerabbilds " - "erforderlich" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "Abbild einer VM oder eines Containers herunterladen" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "" - "Legitimierung ist zum Herunterladen eines VM- oder Containerabbilds " - "erforderlich" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Die lokale Sprachumgebung festlegen" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "" - "Legitimierung ist zum Festlegen der systemweiten Spracheinstellungen " - "erforderlich." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Tastatureinstellungen des Systems festlegen" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" - "Legitimierung ist zum Festlegen der Tastatureinstellungen des Systems " - "erforderlich." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Anwendungen dürfen das Herunterfahren des Systems unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - "Legitimierung ist notwendig, um Anwendungen das Herunterfahren des Systems " - "zu erlauben." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Anwendungen dürfen das Herunterfahren des Systems verzögern" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "Legitimierung ist notwendig, um Anwendungen das Verzögern des Herunterfahren " - "des Systems zu erlauben." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Anwendungen dürfen den Bereitschaftsmodus unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "Legitimierung ist erforderlich, um Anwendungen das Unterbinden des " - "Bereitschaftsmodus zu erlauben." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Anwendungen dürfen den Bereitschaftsmodus verzögern" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "Legitimierung ist erforderlich, um Anwendungen das Verzögern des " - "Bereitschaftsmodus zu erlauben." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "Anwendungen dürfen den automatischen Bereitschaftsmodus unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -203,13 +286,13 @@ msgstr "" - "Legitimierung ist notwendig, um Anwendungen das Unterbinden des " - "automatischen Bereitschaftsmodus zu erlauben." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" - "Anwendungen dürfen das Auswerten des Ein-/Ausschaltknopfs des Systems " - "unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." -@@ -217,13 +300,13 @@ msgstr "" - "Legitmierung ist erforderlich, um Anwendungen das Unterbinden der Auswertung " - "der Ein-/Ausschaltknopfs des Systems zu erlauben." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" - "Anwendungen dürfen das Auswerten des Bereitschaftsknopfs des Systems " - "unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." -@@ -231,12 +314,12 @@ msgstr "" - "Legitimierung ist erforderlich, um Anwendungen das Unterbinden der " - "Auswertung des Bereitschaftsknopfes des Systems zu erlauben." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" - "Anwendungen dürfen das Auswerten des Knopfs für den Ruhezustand unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -244,12 +327,12 @@ msgstr "" - "Legitimierung ist erforderlich, um Anwendungen das Unterbinden der " - "Auswertung des Knopfs für den Ruhezustand zu erlauben." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" - "Anwendungen dürfen das Auswerten des Notebookdeckelschalters unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -257,54 +340,67 @@ msgstr "" - "Legitimierung ist erforderlich, um Anwendungen das Unterbinden der " - "Auswertung des Notebookdeckelschalters des Systems zu erlauben." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 -+#, fuzzy -+#| msgid "Allow non-logged-in users to run programs" -+msgid "Allow non-logged-in user to run programs" -+msgstr "Nicht angemeldete Benutzer dürfen Programme ausführen" -+ -+#: src/login/org.freedesktop.login1.policy:118 -+#, fuzzy -+#| msgid "Authentication is required to run programs as a non-logged-in user." -+msgid "Explicit request is required to run programs as a non-logged-in user." -+msgstr "" -+"Legitimierung ist erforderlich, damit nicht angemeldete Benutzer Programme " -+"ausführen dürfen." -+ -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "Nicht angemeldete Benutzer dürfen Programme ausführen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Legitimierung ist erforderlich, damit nicht angemeldete Benutzer Programme " - "ausführen dürfen." - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Das Anschließen von Geräten an Arbeitsstationen erlauben" - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "" - "Legitimierung ist zum Anschließen eines Geräts an eine Arbeitsstation " - "notwendig." - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Zurücksetzen der an eine Arbeitsstation angeschlossenen Geräte" - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:24 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Legitimierung ist zum Zurücksetzen notwendig, wie Geräte an eine " - "Arbeitsstation angeschlossen werden." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Das System ausschalten" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Legitimierung ist zum Ausschalten des Systems notwendig." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Das System herunter fahren, während andere Benutzer angemeldet sind" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -312,67 +408,120 @@ msgstr "" - "Legitimierung ist zum Herunterfahren des Systems notwendig, während andere " - "Benutzer angemeldet sind." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "" - "Das System ausschalten, während eine Anwendung anfordert es zu unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Legitimierung ist zum Ausschalten des Systems notwendig, während eine " - "Anwendung anfordert es zu unterbinden." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Das System neu starten" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Legitimierung ist zum Neustart des Systems notwendig." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Das Systems neu starten, während andere Benutzer angemeldet sind" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Legitimierung ist zum Neustart des Systems notwendig, während andere " - "Benutzer angemeldet sind." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "" - "Das System neu starten, während eine Anwendung anfordert es zu unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Legitimierung ist zum Neustart des Systems notwendig, während eine Anwendung " - "anforderte es zu unterbinden." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "Den Ruhezustand des Systems aktivieren" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "" -+"Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "" -+"Den Ruhezustand des Systems aktivieren, während andere Benutzer angemeldet " -+"sind" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig, " -+"während andere Benutzer angemeldet sind." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "" -+"Das System in den Ruhezustand versetzen, während eine Anwendung wünscht dies " -+"zu verhindern" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"Legitimierung ist zum Versetzen des System in den Ruhezustand notwendig, " -+"während eine Anwendung wünscht dies zu verhindern." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Das System in Bereitschaft versetzen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "" - "Das System in Bereitschaft versetzen, während andere Benutzer angemeldet " - "sind." - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -380,36 +529,36 @@ msgstr "" - "Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig, " - "während andere Benutzer angemeldet sind." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "" - "Das System in Bereitschaft versetzen, während eine Anwendung anfordert dies " - "zu unterbinden" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig, " - "während eine Anwendung anfordert dies zu unterbinden." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Den Ruhezustand des Systems aktivieren" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "" - "Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "" - "Den Ruhezustand des Systems aktivieren, während andere Benutzer angemeldet " - "sind" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -417,48 +566,59 @@ msgstr "" - "Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig, " - "während andere Benutzer angemeldet sind." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "" - "Das System in den Ruhezustand versetzen, während eine Anwendung wünscht dies " - "zu verhindern" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Legitimierung ist zum Versetzen des System in den Ruhezustand notwendig, " - "während eine Anwendung wünscht dies zu verhindern." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Aktive Sitzungen, Benutzer und Arbeitsstationen verwalten" - - # www.freedesktop.org/wiki/Software/systemd/multiseat/ --#: ../src/login/org.freedesktop.login1.policy.in.h:50 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Legitimierung ist zur Verwaltung aktiver Sitzungen, Benutzern und " - "Arbeitsstationen notwendig." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Aktive Sitzungen sperren und entsperren" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "" - "Legitimierung ist zum Sperren und Entsperren aktiver Sitzungen notwendig." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Legitimierung ist zum Festlegen der Systemzeitzone notwendig." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "" - "Mitteilungen an die Firmware zum Starten in die Einrichtungsoberfläche " - "zulassen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -466,86 +626,128 @@ msgstr "" - "Legitimierung ist zum Starten der Firmware in die Einrichtungsoberfläche " - "notwendig." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Legitimierung ist zum Starten der Firmware in die Einrichtungsoberfläche " -+"notwendig." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Legitimierung ist zum Starten der Firmware in die Einrichtungsoberfläche " -+"notwendig." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Nachricht an alle einstellen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Legitimierung ist zum Festlegen des lokalen Rechnernamens notwendig" -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "In einem lokalen Container anmelden" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "Legitimierung ist zum Anmelden in einem lokalen Container notwendig." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Am lokalen Rechner anmelden" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "Legitimierung ist zum Anmelden am lokalen Rechner notwendig." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Eine Shell in einem lokalen Container erhalten" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" - "Legitimierung ist zum Erhalten einer Shell in einem lokalen Container " - "notwendig." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Eine Shell auf dem lokalen Rechner erhalten" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "" - "Legitimierung ist zum Erhalten einer Shell auf dem lokalen Rechner notwendig." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Ein Pseudo-TTY in einem lokalen Container erhalten" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" - "Legitimierung ist zum Erhalten eines Pseudo-TTY in einem lokalen Container " - "notwendig." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Ein Pseudo-TTY auf dem lokalen Rechner erhalten" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "" - "Legitimierung ist zum Erhalten eines Pseudo-TTY auf dem lokalen Rechner " - "notwendig." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Lokale virtuelle Maschinen und Container verwalten" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" - "Legitimierung ist zum Verwalten lokaler virtueller Maschinen und Container " - "erforderlich." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Lokale virtuelle Maschinen und Containerabbilder verwalten" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." -@@ -553,27 +755,268 @@ msgstr "" - "Legitimierung ist zum Verwalten lokaler virtueller Maschinen und " - "Containerabbildern erforderlich." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Legitimierung ist zum Festlegen der Systemzeit notwendig." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "Legitimierung ist zum Festlegen der Systemzeit notwendig." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Legitimierung ist zum Stoppen von »$(unit)« notwendig." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Legitimierung ist zum Festlegen des lokalen Rechnernamens notwendig" -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "" -+"Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Legitimierung ist zum Anmelden am lokalen Rechner notwendig." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Legitimierung ist zum Festlegen des lokalen Rechnernamens notwendig" -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "" -+"Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "" -+"Legitimierung ist zum Festlegen der systemweiten Spracheinstellungen " -+"erforderlich." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Legitimierung ist zum Festlegen der Systemzeit notwendig." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Legitimierung ist zum Festlegen der Systemzeit notwendig." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Legitimierung ist zum erneuten Laden des systemd-Zustands notwendig." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Legitimierung ist zum Neustart des Systems notwendig." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "" -+"Legitimierung ist zum Importieren eines VM- oder Containerabbilds " -+"erforderlich" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+# www.freedesktop.org/wiki/Software/systemd/multiseat/ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "" -+"Legitimierung ist zum Anschließen eines Geräts an eine Arbeitsstation " -+"notwendig." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "" -+"Legitimierung ist zum Herunterladen eines VM- oder Containerabbilds " -+"erforderlich" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Legitimierung ist zum Festlegen der Tastatureinstellungen des Systems " -+"erforderlich." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Die Systemzeit festlegen" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "Legitimierung ist zum Festlegen der Systemzeit notwendig." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Die Systemzeitzone festlegen" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "Legitimierung ist zum Festlegen der Systemzeitzone notwendig." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "Echtzeituhr auf lokale Zeitzone oder UTC setzen" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -581,11 +1024,11 @@ msgstr "" - "Legitimierung ist notwendig zum Festlegen, ob die Echtzeituhr auf lokale " - "Zeitzone oder UTC eingestellt ist." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Netzwerkzeitabgeich ein- oder ausschalten" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -593,37 +1036,66 @@ msgstr "" - "Legitimierung ist zum Festlegen, ob Netzwerkzeitabgeich eingeschaltet sein " - "soll, erforderlich." - --#: ../src/core/dbus-unit.c:428 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Legitimierung ist zum Starten von »$(unit)« notwendig." - --#: ../src/core/dbus-unit.c:429 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Legitimierung ist zum Stoppen von »$(unit)« notwendig." - --#: ../src/core/dbus-unit.c:430 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Legitimierung ist zum erneuten Laden von »$(unit)« notwendig." - --#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Legitimierung ist zum Neustarten von »$(unit)« notwendig." - --#: ../src/core/dbus-unit.c:535 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Legitimierung ist zum Eliminieren von »$(unit)« notwendig." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "" -+"Legitimierung ist zum Festlegen der Eigenschaften von »$(unit)« notwendig." - --#: ../src/core/dbus-unit.c:565 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Legitimierung ist zum Zurücksetzen des Status »fehlgeschlagen« von »$(unit)« " - "notwendig" - --#: ../src/core/dbus-unit.c:597 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "" - "Legitimierung ist zum Festlegen der Eigenschaften von »$(unit)« notwendig." - -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"Legitimierung ist zum Zurücksetzen des Status »fehlgeschlagen« von »$(unit)« " -+"notwendig" -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Legitimierung ist zum Zurücksetzen des Status »fehlgeschlagen« von »$(unit)« " -+"notwendig" -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Legitimierung ist zum Eliminieren von »$(unit)« notwendig." -+ - #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" - #~ msgstr "Strg+C drücken um laufende Dateisystem-Prüfungen abzubrechen" - -diff --git a/po/el.po b/po/el.po -index c422533..535216f 100644 ---- a/po/el.po -+++ b/po/el.po -@@ -7,7 +7,7 @@ msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2015-11-22 16:37+0100\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2014-04-29 09:17+0300\n" - "Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) \n" - "Language-Team: team@lists.gnome.gr\n" -@@ -18,45 +18,45 @@ msgstr "" - "Plural-Forms: nplurals=2; plural=(n != 1);\n" - "X-Generator: Virtaal 0.7.0\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Αποστολή του συνθηματικού πίσω στο σύστημα" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "" - "Απαιτείται πιστοποίηση για αποστολή του εισερχόμενου συνθηματικού πίσω στο " - "σύστημα." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - #, fuzzy - msgid "Authentication is required to manage system services or other units." - msgstr "" - "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και " - "υπηρεσιών." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - #, fuzzy - msgid "Authentication is required to manage system service or unit files." - msgstr "" - "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και " - "υπηρεσιών." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - #, fuzzy - msgid "Set or unset system and service manager environment variables" - msgstr "Προνομιούχος πρόσβαση διαχειριστή συστήματος και υπηρεσίας" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - #, fuzzy - msgid "" - "Authentication is required to set or unset system and service manager " -@@ -65,29 +65,89 @@ msgstr "" - "Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και " - "υπηρεσιών." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - #, fuzzy - msgid "Reload the systemd state" - msgstr "Επανεκκίνηση του συστήματος" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - #, fuzzy - msgid "Authentication is required to reload the systemd state." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+msgid "Authentication is required to create a user's home area." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+msgid "Authentication is required to remove a user's home area." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+msgid "Authentication is required to resize a user's home area." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Ορισμός ονόματος οικοδεσπότη" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Ορισμός στατικού ονόματος οικοδεσπότη" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -95,110 +155,119 @@ msgstr "" - "Απαιτείται πιστοποίηση για να ορίσετε το στατικά ρυθμισμένο όνομα τοπικού " - "οικοδεσπότη, καθώς και το pretty όνομα οικοδεσπότη." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Ορισμός πληροφοριών μηχανής" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+msgid "Authentication is required to get product UUID." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - #, fuzzy - msgid "Authentication is required to import a VM or container image" - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - #, fuzzy - msgid "Authentication is required to export a VM or container image" - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - #, fuzzy - msgid "Authentication is required to download a VM or container image" - msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Ορισμός τοπικών ρυθμίσεων συστήματος" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "" - "Απαιτείται πιστοποίηση για να ορίσετε τις τοπικές ρυθμίσεις του συστήματος." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Ορισμός ρυθμίσεων πληκτρολογίου συστήματος" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" - "Απαιτείται πιστοποίηση για να ορίσετε τις ρυθμίσεις πληκτρολογίου του " - "συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "" - "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τον τερματισμό του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει τον " - "τερματισμό του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "" - "Να επιτρέπεται στις εφαρμογές να καθυστερούν τον τερματισμό του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να καθυστερήσει " - "τον τερματισμό του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Να επιτρέπεται στις εφαρμογές να αποτρέπουν την ύπνωση του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " - "ύπνωση του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Να επιτρέπεται στις εφαρμογές να καθυστερούν την ύπνωση του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να καθυστερήσει " - "την ύπνωση του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "" - "Να επιτρέπεται στις εφαρμογές να αποτρέπουν την αυτόματη αναστολή του " - "συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -206,13 +275,13 @@ msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " - "αυτόματη αναστολή του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" - "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου " - "ενεργοποίησης του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." -@@ -220,13 +289,13 @@ msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " - "διαχείριση του πλήκτρου ενεργοποίησης του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" - "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου " - "αναστολής του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." -@@ -234,13 +303,13 @@ msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " - "διαχείριση του πλήκτρου αναστολής του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" - "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου " - "αδρανοποίησης του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -248,13 +317,13 @@ msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " - "διαχείριση του πλήκτρου αδρανοποίησης του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" - "Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του διακόπτη " - "καλύμματος του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -262,49 +331,62 @@ msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " - "διαχείριση του διακόπτη καλύμματος του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 -+#, fuzzy -+#| msgid "Allow non-logged-in users to run programs" -+msgid "Allow non-logged-in user to run programs" -+msgstr "Να επιτρέπεται σε μη συνδεμένους χρήστες να εκτελούν προγράμματα" -+ -+#: src/login/org.freedesktop.login1.policy:118 -+#, fuzzy -+#| msgid "Authentication is required to run programs as a non-logged-in user." -+msgid "Explicit request is required to run programs as a non-logged-in user." -+msgstr "" -+"Απαιτείται πιστοποίηση για να επιτρέπεται σε μη συνδεμένους χρήστες να " -+"εκτελούν προγράμματα." -+ -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "Να επιτρέπεται σε μη συνδεμένους χρήστες να εκτελούν προγράμματα" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Απαιτείται πιστοποίηση για να επιτρέπεται σε μη συνδεμένους χρήστες να " - "εκτελούν προγράμματα." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Να επιτρέπεται η προσάρτηση συσκευών στους σταθμούς εργασίας" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "" - "Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Αφαίρεση συσκευής από προσαρτήσεις σταθμού εργασίας" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Απαιτείται πιστοποίηση για επαναφορά του τρόπου που οι συσκευές προσαρτώνται " - "στους σταθμούς εργασίας." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Σβήσιμο του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Απαιτείται πιστοποίηση για την σβήσιμο του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Σβήσιμο του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -312,63 +394,111 @@ msgstr "" - "Απαιτείται πιστοποίηση για σβήσιμο του συστήματος ενώ άλλοι χρήστες είναι " - "συνδεμένοι." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "Απενεργοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί." - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Απαιτείται πιστοποίηση για απενεργοποίηση του συστήματος ενώ μια εφαρμογή " - "ζήτησε να αποτραπεί." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Επανεκκίνηση του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Επανεκκίνηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος ενώ άλλοι χρήστες " - "είναι συνδεμένοι." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "Επανεκκίνηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος ενώ μια εφαρμογή " - "ζήτησε να αποτραπεί." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "Αδρανοποίηση του συτήματος" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "Αδρανοποίηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ άλλοι χρήστες " -+"είναι συνδεμένοι." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "Αδρανοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ μια εφαρμογή " -+"ζήτησε να αποτραπεί." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Αναστολή του συστήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Απαιτείται πιστοποίηση για την αναστολή του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Αναστολή του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -376,31 +506,31 @@ msgstr "" - "Απαιτείται πιστοποίηση για αναστολή του συστήματος ενώ άλλοι χρήστες είναι " - "συνδεμένοι." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "Αναστολή του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Απαιτείται πιστοποίηση για αναστολή του συστήματος ενώ μια εφαρμογή ζήτησε " - "να αποτραπεί." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Αδρανοποίηση του συτήματος" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "Αδρανοποίηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -408,157 +538,422 @@ msgstr "" - "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ άλλοι χρήστες " - "είναι συνδεμένοι." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "Αδρανοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ μια εφαρμογή " - "ζήτησε να αποτραπεί." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 -+#: src/login/org.freedesktop.login1.policy:322 - #, fuzzy --msgid "" --"Authentication is required to manage active sessions, users and seats." -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 -+#: src/login/org.freedesktop.login1.policy:332 - #, fuzzy - msgid "Authentication is required to lock or unlock active sessions." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα ζώνης του συστήματος." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+msgid "Indicate to the firmware to boot to setup interface" -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/login/org.freedesktop.login1.policy:353 - #, fuzzy - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:386 - #, fuzzy - msgid "Authentication is required to set a wall message" - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - #, fuzzy - msgid "Authentication is required to log into a local container." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - #, fuzzy - msgid "Authentication is required to log into the local host." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - #, fuzzy - msgid "Acquire a shell in a local container" - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - #, fuzzy - msgid "Authentication is required to acquire a shell in a local container." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - #, fuzzy - msgid "Authentication is required to acquire a shell on the local host." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - #, fuzzy - msgid "Acquire a pseudo TTY in a local container" - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - #, fuzzy - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - #, fuzzy - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - #, fuzzy - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - #, fuzzy - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+msgid "Authentication is required to set domains." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "" -+"Απαιτείται πιστοποίηση για να ορίσετε τις τοπικές ρυθμίσεις του συστήματος." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+msgid "Authentication is required to send force renew message." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+msgid "Authentication is required to reload network settings." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+msgid "Authentication is required to inspect a portable service image." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "" -+"Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Απαιτείται πιστοποίηση για να ορίσετε τις ρυθμίσεις πληκτρολογίου του " -+"συστήματος." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Ορισμός ώρας συστήματος" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Ορισμός ζώνης ώρας συστήματος" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα ζώνης του συστήματος." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "Ορισμός RTC στην τοπική ζώνη ώρας ή UTC" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -566,11 +961,11 @@ msgstr "" - "Απαιτείται πιστοποίηση για να ελέγξετε αν το RTC αποθηκεύει την τοπική ή την " - "ώρα UTC." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Ενεργοποίηση/Απενεργοποίηση συγχρονισμού ώρας δικτύου" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -578,37 +973,56 @@ msgstr "" - "Απαιτείται πιστοποίηση για να ελέγξετε αν ο συγχρονισμός ώρας δικτύου θα " - "ενεργοποιηθεί." - --#: ../src/core/dbus-unit.c:428 -+#: src/core/dbus-unit.c:362 - #, fuzzy - msgid "Authentication is required to start '$(unit)'." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." - --#: ../src/core/dbus-unit.c:429 -+#: src/core/dbus-unit.c:363 - #, fuzzy - msgid "Authentication is required to stop '$(unit)'." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." - --#: ../src/core/dbus-unit.c:430 -+#: src/core/dbus-unit.c:364 - #, fuzzy - msgid "Authentication is required to reload '$(unit)'." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." - --#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - #, fuzzy - msgid "Authentication is required to restart '$(unit)'." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." - --#: ../src/core/dbus-unit.c:535 -+#: src/core/dbus-unit.c:538 - #, fuzzy --msgid "Authentication is required to kill '$(unit)'." --msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." - --#: ../src/core/dbus-unit.c:565 -+#: src/core/dbus-unit.c:569 - #, fuzzy - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." - --#: ../src/core/dbus-unit.c:597 -+#: src/core/dbus-unit.c:602 - #, fuzzy - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -+ -+#, fuzzy -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." -diff --git a/po/es.po b/po/es.po -index adfe827..d1bcd18 100644 ---- a/po/es.po -+++ b/po/es.po -@@ -4,602 +4,1053 @@ - # Alex Puchades , 2015. - # Daniel Mustieles , 2015. - # Álex Puchades , 2015. --# -+# Adolfo Jayme Barrientos , 2020. - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2015-11-22 16:37+0100\n" --"PO-Revision-Date: 2016-06-07 15:41-0400\n" --"Last-Translator: Pablo Lezaeta Reyes \n" --"Language-Team: Español; Castellano \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" -+"PO-Revision-Date: 2020-08-24 07:29+0000\n" -+"Last-Translator: Adolfo Jayme Barrientos \n" -+"Language-Team: Spanish \n" - "Language: es\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" --"Plural-Forms: nplurals=2; plural=(n != 1);\n" --"X-Generator: Poedit 1.8.7.1\n" -+"Plural-Forms: nplurals=2; plural=n != 1;\n" -+"X-Generator: Weblate 4.2.1\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Devolver contraseña al sistema" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "" --"Se requiere autenticación para devolver la contraseña introducida al sistema." -+"Necesita autenticarse para devolver la contraseña introducida al sistema." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Administrar servicios del sistema u otras unidades" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" --"Se requiere autenticación para administrar los servicios de sistema u otras " -+"Necesita autenticarse para administrar los servicios de sistema u otras " - "unidades." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Administrar servicio del sistema o archivos de unidad" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" --"Se requiere autenticación para administrar el servicio de sistema o los " --"archivos de unidad." -+"Necesita autenticarse para administrar el servicio de sistema o los archivos " -+"de unidad." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "Administrar variables de entorno del sistema y del gestor de servicios" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." - msgstr "" --"Se requiere autenticación para administrar las variables de entorno del " --"sistema y del gestor de servicios." -+"Necesita autenticarse para administrar las variables de entorno del sistema " -+"y del gestor de servicios." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Recargar el estado de systemd" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." -+msgstr "Necesita autenticarse para recargar el estado de systemd." -+ -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Se requiere autenticación para recargar el estado de systemd." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." - msgstr "Se requiere autenticación para recargar el estado de systemd." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Se requiere autenticación para administrar las sesiones activas, usuarios y " -+"puestos de trabajo." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"Se requiere autenticación para conectar un dispositivo a un puesto de " -+"trabajo." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Se requiere autenticación para establecer un muro de texto" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Se requiere autenticación para administrar las sesiones activas, usuarios y " -+"puestos de trabajo." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Establecer el nombre del equipo" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." --msgstr "Se requiere autenticación para establecer el nombre del equipo local." -+msgstr "Necesita autenticarse para establecer el nombre del equipo local." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Establecer nombre estático del equipo" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." - msgstr "" --"Se requiere autenticación para establecer el nombre estático de equipo " --"local, así como el nombre visible del equipo." -+"Necesita autenticarse para establecer el nombre estático de equipo local, " -+"así como el nombre visible del equipo." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Establecer información del sistema" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." -+msgstr "Necesita autenticarse para establecer la información de sistema local." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" - msgstr "" --"Se requiere autenticación para establecer la información de sistema local." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Se requiere autenticación para recargar '$(unit)'." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Importar una imagen de máquina virtual o de contenedor" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "" --"Se requiere autenticación para importar una imagen de máquina virtual o de " -+"Necesita autenticarse para importar una imagen de máquina virtual o de " - "contenedor" - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "Exportar imagen de máquina virtual o de contenedor" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "" --"Se requiere autenticación para exportar una imagen de máquina virtual o de " -+"Necesita autenticarse para exportar una imagen de máquina virtual o de " - "contenedor" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "Descargar una imagen de máquina virtual o de contenedor" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "" --"Se requiere autenticación para descargar una imagen de máquina virtual o de " -+"Necesita autenticarse para descargar una imagen de máquina virtual o de " - "contenedor" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Establecer región del sistema" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." --msgstr "Se requiere autenticación para establecer la región del sistema." -+msgstr "Necesita autenticarse para establecer la región del sistema." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Configurar teclado" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." --msgstr "Se requiere autenticación para configurar el teclado del sistema." -+msgstr "Necesita autenticarse para configurar el teclado del sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Permitir que las aplicaciones impidan el apagado del sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" --"Se requiere autenticación para que una aplicación impida el apagado del " --"sistema." -+"Necesita autenticarse para que una aplicación impida el apagado del sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Permitir a las aplicaciones retrasar el apagado del sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" --"Se requiere autenticación para que una aplicación retrase el apagado del " --"sistema." -+"Necesita autenticarse para que una aplicación retrase el apagado del sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Permitir a las aplicaciones impedir la hibernación del sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" --"Se requiere autenticación para que una aplicación impida la hibernación del " -+"Necesita autenticarse para que una aplicación impida la hibernación del " - "sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Permitir a las aplicaciones retrasar la hibernación del sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" --"Se requiere autenticación para que una aplicación retrase la hibernación del " -+"Necesita autenticarse para que una aplicación retrase la hibernación del " - "sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "" - "Permitir a las aplicaciones impedir la suspensión automática del sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." - msgstr "" --"Se requiere autenticación para que una aplicación impida la suspensión " -+"Necesita autenticarse para que una aplicación impida la suspensión " - "automática del sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" - "Permitir a las aplicaciones impedir el manejo de la tecla de encendido/" - "apagado por parte del sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." - msgstr "" --"Se requiere autenticación para que una aplicación impida el manejo de la " --"tecla de encendido/apagado por parte del sistema." -+"Necesita autenticarse para que una aplicación impida el manejo de la tecla " -+"de encendido/apagado por parte del sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" - "Permitir a las aplicaciones impedir el manejo de la tecla de suspensión por " - "parte del sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." - msgstr "" --"Se requiere autenticación para que una aplicación impida el manejo de la " --"tecla de suspensión por parte del sistema." -+"Necesita autenticarse para que una aplicación impida el manejo de la tecla " -+"de suspensión por parte del sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" - "Permitir a las aplicaciones impedir el manejo de la tecla de hibernación por " - "parte del sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." - msgstr "" --"Se requiere autenticación para que una aplicación impida el manejo de la " --"tecla de hibernación por parte del sistema." -+"Necesita autenticarse para que una aplicación impida el manejo de la tecla " -+"de hibernación por parte del sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" - "Permitir a las aplicaciones impedir el manejo del cierre de la tapa del " - "portátil por parte del sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." - msgstr "" --"Se requiere autenticación para que una aplicación impida el manejo del " --"cierre de la tapa del portátil por parte del sistema." -+"Necesita autenticarse para que una aplicación impida el manejo del cierre de " -+"la tapa del portátil por parte del sistema." -+ -+#: src/login/org.freedesktop.login1.policy:117 -+#, fuzzy -+#| msgid "Allow non-logged-in users to run programs" -+msgid "Allow non-logged-in user to run programs" -+msgstr "Permitir la ejecución de programas a usuarios no conectados" -+ -+#: src/login/org.freedesktop.login1.policy:118 -+#, fuzzy -+#| msgid "Authentication is required to run programs as a non-logged-in user." -+msgid "Explicit request is required to run programs as a non-logged-in user." -+msgstr "" -+"Se requiere autenticación para la ejecución de programas por usuarios no " -+"conectados." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "Permitir la ejecución de programas a usuarios no conectados" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" --"Se requiere autenticación para la ejecución de programas por usuarios no " -+"Necesita autenticarse para la ejecución de programas por usuarios no " - "conectados." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Permitir la conexión de dispositivos a los puestos de trabajo" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "" --"Se requiere autenticación para conectar un dispositivo a un puesto de " --"trabajo." -+"Necesita autenticarse para conectar un dispositivo a un puesto de trabajo." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Refrescar los dispositivos asociados a cada puesto de trabajo" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" --"Se requiere autenticación para reconfigurar los dispositivos asociados a " --"cada puesto de trabajo." -+"Necesita autenticarse para reconfigurar los dispositivos asociados a cada " -+"puesto de trabajo." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Apagar el sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." --msgstr "Se requiere autenticación para apagar el sistema." -+msgstr "Necesita autenticarse para apagar el sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Apagar el sistema mientras todavía hay usuarios conectados" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." - msgstr "" --"Se requiere autenticación para apagar el sistema mientras todavía hay " --"usuarios conectados." -+"Necesita autenticarse para apagar el sistema mientras todavía hay usuarios " -+"conectados." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "Apagar el sistema a pesar de que una aplicación lo impide" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" --"Se requiere autenticación para apagar el sistema a pesar de que una " --"aplicación lo impide." -+"Necesita autenticarse para apagar el sistema a pesar de que una aplicación " -+"lo impide." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Reiniciar el sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." --msgstr "Se requiere autenticación para reiniciar el sistema." -+msgstr "Necesita autenticarse para reiniciar el sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Reiniciar el sistema mientras todavía hay usuarios conectados" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" --"Se requiere autenticación para reiniciar el sistema mientras todavía hay " -+"Necesita autenticarse para reiniciar el sistema mientras todavía hay " - "usuarios conectados." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "Reiniciar el sistema a pesar de que una aplicación lo impide" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" --"Se requiere autenticación para reiniciar el sistema a pesar de que una " -+"Necesita autenticarse para reiniciar el sistema a pesar de que una " - "aplicación lo impide." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "Hibernar el sistema" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "Se requiere autenticación para hibernar el sistema." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "Hibernar el sistema mientras todavía hay usuarios conectados" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"Se requiere autenticación para hibernar el sistema mientras todavía hay " -+"usuarios conectados." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "Hibernar el sistema a pesar de que una aplicación lo impide" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"Se requiere autenticación para hibernar el sistema a pesar de que una " -+"aplicación lo impide." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Suspender el sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." --msgstr "Se requiere autenticación para suspender el sistema." -+msgstr "Necesita autenticarse para suspender el sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Suspender el sistema mientras todavía hay usuarios conectados" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." - msgstr "" --"Se requiere autenticación para suspender el sistema mientras todavía hay " -+"Necesita autenticarse para suspender el sistema mientras todavía hay " - "usuarios conectados." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "Suspender el sistema a pesar de que una aplicación lo impide" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" --"Se requiere autenticación para suspender el sistema a pesar de que una " -+"Necesita autenticarse para suspender el sistema a pesar de que una " - "aplicación lo impide." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Hibernar el sistema" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." --msgstr "Se requiere autenticación para hibernar el sistema." -+msgstr "Necesita autenticarse para hibernar el sistema." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "Hibernar el sistema mientras todavía hay usuarios conectados" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." - msgstr "" --"Se requiere autenticación para hibernar el sistema mientras todavía hay " --"usuarios conectados." -+"Necesita autenticarse para hibernar el sistema mientras todavía hay usuarios " -+"conectados." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "Hibernar el sistema a pesar de que una aplicación lo impide" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" --"Se requiere autenticación para hibernar el sistema a pesar de que una " --"aplicación lo impide." -+"Necesita autenticarse para hibernar el sistema a pesar de que una aplicación " -+"lo impide." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Administrar sesiones activas, usuarios y puestos de trabajo" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" --"Se requiere autenticación para administrar las sesiones activas, usuarios y " -+"Necesita autenticarse para administrar las sesiones activas, usuarios y " - "puestos de trabajo." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Bloquear/desbloquear sesiones activas" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." --msgstr "Se requiere autenticación para bloquear/desbloquear sesiones activas." -+msgstr "Necesita autenticarse para bloquear/desbloquear sesiones activas." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Se requiere autenticación para establecer la zona horaria del sistema." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "" - "Permitir indicación al firmware para arrancar la interfaz de configuración" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." - msgstr "" -+"Necesita autenticarse para indicar al firmware que arranque la interfaz de " -+"configuración." -+ -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Se requiere autenticación para indicar al firmware que arranque la interfaz " -+"de configuración." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" - "Se requiere autenticación para indicar al firmware que arranque la interfaz " - "de configuración." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Establecer muro de texto" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" --msgstr "Se requiere autenticación para establecer un muro de texto" -+msgstr "Necesita autenticarse para establecer un muro de texto" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Se requiere autenticación para establecer el nombre del equipo local." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Conectarse a un contenedor local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." --msgstr "Se requiere autenticación para conectarse a un contenedor local." -+msgstr "Necesita autenticarse para conectarse a un contenedor local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Conectarse al equipo local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." --msgstr "Se requiere autenticación para conectarse al equipo local." -+msgstr "Necesita autenticarse para conectarse al equipo local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Se adquiere un intérprete de órdenes en un contenedor local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" --"Se requiere autenticación para adquirir un intérprete de órdenes en un " -+"Necesita autenticarse para adquirir un intérprete de órdenes en un " - "contenedor local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Se adquiere un intérprete de órdenes en el equipo local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "" --"Se requiere autenticación para adquirir un intérprete de órdenes del equipo " -+"Necesita autenticarse para adquirir un intérprete de órdenes del equipo " - "local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Se adquiere un seudo-TTY en el contenedor local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" --"Se requiere autenticación para adquirir un seudo-TTY en el contenedor local." -+"Necesita autenticarse para adquirir un seudo-TTY en el contenedor local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Se adquiere un seudo-TTY en el equipo local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." --msgstr "" --"Se requiere autenticación para adquirir un seudo-TTY en el equipo local." -+msgstr "Necesita autenticarse para adquirir un seudo-TTY en el equipo local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Administrar máquinas virtuales y contenedores locales" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" --"Se requiere autenticación para administrar las máquinas virtuales y los " -+"Necesita autenticarse para administrar las máquinas virtuales y los " - "contenedores locales." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Administrar imágenes de máquina virtual y de contenedores locales" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." - msgstr "" --"Se requiere autenticación para administrar las imágenes de máquina virtual y " --"de contenedores locales." -+"Necesita autenticarse para administrar las imágenes de máquina virtual y de " -+"contenedores locales." -+ -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Se requiere autenticación para detener '$(unit)'." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Se requiere autenticación para establecer el nombre del equipo local." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Se requiere autenticación para hibernar el sistema." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Se requiere autenticación para conectarse al equipo local." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Se requiere autenticación para establecer el nombre del equipo local." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Se requiere autenticación para hibernar el sistema." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Se requiere autenticación para establecer la región del sistema." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Se requiere autenticación para establecer un muro de texto" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Se requiere autenticación para establecer un muro de texto" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Se requiere autenticación para recargar el estado de systemd." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Se requiere autenticación para reiniciar el sistema." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "" -+"Se requiere autenticación para importar una imagen de máquina virtual o de " -+"contenedor" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "" -+"Se requiere autenticación para conectar un dispositivo a un puesto de " -+"trabajo." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "" -+"Se requiere autenticación para descargar una imagen de máquina virtual o de " -+"contenedor" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "Se requiere autenticación para establecer un muro de texto" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "Se requiere autenticación para establecer un muro de texto" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "Se requiere autenticación para configurar el teclado del sistema." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Establecer fecha y hora del sistema" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." --msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." -+msgstr "Necesita autenticarse para establecer la fecha y hora del sistema." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Establecer la zona horaria del sistema" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." --msgstr "Se requiere autenticación para establecer la zona horaria del sistema." -+msgstr "Necesita autenticarse para establecer la zona horaria del sistema." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "Establecer reloj del sistema en formato de hora local/tiempo UTC" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." - msgstr "" --"Se requiere autenticación para establecer el reloj del sistema en formato de " -+"Necesita autenticarse para establecer el reloj del sistema en formato de " - "hora local o tiempo UTC." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Activar/desactivar la sincronización de hora por red" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." - msgstr "" --"Se requiere autenticación para activar/desactivar la sincronización de hora " --"por red." -+"Necesita autenticarse para activar/desactivar la sincronización de hora por " -+"red." - --#: ../src/core/dbus-unit.c:428 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." --msgstr "Se requiere autenticación para iniciar '$(unit)'." -+msgstr "Necesita autenticarse para iniciar «$(unit)»." - --#: ../src/core/dbus-unit.c:429 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." --msgstr "Se requiere autenticación para detener '$(unit)'." -+msgstr "Necesita autenticarse para detener «$(unit)»." - --#: ../src/core/dbus-unit.c:430 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." --msgstr "Se requiere autenticación para recargar '$(unit)'." -+msgstr "Necesita autenticarse para recargar «$(unit)»." - --#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." --msgstr "Se requiere autenticación para reiniciar '$(unit)'." -+msgstr "Necesita autenticarse para reiniciar «$(unit)»." - --#: ../src/core/dbus-unit.c:535 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Se requiere autenticación para matar a '$(unit)'." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "" -+"Se requiere autenticación para establecer las propiedades de '$(unit)'." - --#: ../src/core/dbus-unit.c:565 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." --msgstr "Se requiere autenticación para reiniciar el estado de «fallido» de '$(unit)'." -+msgstr "" -+"Necesita autenticarse para reiniciar el estado de «fallido» de «$(unit)»." - --#: ../src/core/dbus-unit.c:597 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." -+msgstr "Necesita autenticarse para establecer las propiedades de «$(unit)»." -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." - msgstr "" --"Se requiere autenticación para establecer las propiedades de '$(unit)'." -+"Se requiere autenticación para reiniciar el estado de «fallido» de '$(unit)'." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Se requiere autenticación para reiniciar el estado de «fallido» de '$(unit)'." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Se requiere autenticación para matar a '$(unit)'." - - #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" - #~ msgstr "" -diff --git a/po/fr.po b/po/fr.po -index 0999cf9..d54de1e 100644 ---- a/po/fr.po -+++ b/po/fr.po -@@ -3,19 +3,22 @@ - # French translations for systemd package - # Traductions françaises du paquet systemd. - # -+# Julien Humbert , 2020. - msgid "" - msgstr "" - "Project-Id-Version: systemd\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2020-02-03 01:21+0100\n" --"PO-Revision-Date: 2019-03-07 23:09+0100\n" --"Last-Translator: Sylvain Plantefève \n" --"Language-Team: French\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" -+"PO-Revision-Date: 2020-08-28 05:29+0000\n" -+"Last-Translator: Julien Humbert \n" -+"Language-Team: French \n" - "Language: fr\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" --"Plural-Forms: nplurals=2; plural=(n > 1);\n" -+"Plural-Forms: nplurals=2; plural=n > 1;\n" -+"X-Generator: Weblate 4.2.1\n" - - #: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" -@@ -48,7 +51,7 @@ msgstr "" - #: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "" --"Définir ou supprimer des variables d'environnement du système ou du " -+"Définir ou supprimer des variables d’environnement du système ou du " - "gestionnaire de services" - - #: src/core/org.freedesktop.systemd1.policy.in:55 -@@ -56,16 +59,16 @@ msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." - msgstr "" --"Authentification requise pour définir ou supprimer des variables " --"d'environnement du système ou du gestionnaire de services." -+"Authentification requise pour définir ou supprimer des variables d’" -+"environnement du système ou du gestionnaire de services." - - #: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" --msgstr "Recharger l'état de systemd" -+msgstr "Recharger l’état de systemd" - - #: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." --msgstr "Authentification requise pour recharger l'état de systemd" -+msgstr "Authentification requise pour recharger l’état de systemd." - - #: src/home/org.freedesktop.home1.policy:13 - msgid "Create a home area" -@@ -74,7 +77,7 @@ msgstr "Créer un espace personnel" - #: src/home/org.freedesktop.home1.policy:14 - msgid "Authentication is required to create a user's home area." - msgstr "" --"Authentification requise pour créer l'espace personnel d'un utilisateur." -+"Authentification requise pour créer l’espace personnel d’un utilisateur." - - #: src/home/org.freedesktop.home1.policy:23 - msgid "Remove a home area" -@@ -83,18 +86,18 @@ msgstr "Retirer un espace personnel" - #: src/home/org.freedesktop.home1.policy:24 - msgid "Authentication is required to remove a user's home area." - msgstr "" --"Authentification requise pour retirer l'espace personnel d'un utilisateur." -+"Authentification requise pour retirer l’espace personnel d’un utilisateur." - - #: src/home/org.freedesktop.home1.policy:33 - msgid "Check credentials of a home area" --msgstr "Vérifier les identifiants d'un espace personnel" -+msgstr "Vérifier les identifiants d’un espace personnel" - - #: src/home/org.freedesktop.home1.policy:34 - msgid "" - "Authentication is required to check credentials against a user's home area." - msgstr "" --"Authentification requise pour vérifier les identifiants de l'espace " --"personnel d'un utilisateur." -+"Authentification requise pour vérifier les identifiants de l’espace " -+"personnel d’un utilisateur." - - #: src/home/org.freedesktop.home1.policy:43 - msgid "Update a home area" -@@ -103,7 +106,7 @@ msgstr "Mettre à jour un espace personnel" - #: src/home/org.freedesktop.home1.policy:44 - msgid "Authentication is required to update a user's home area." - msgstr "" --"Authentification requise pour mettre à jour l'espace personnel d'un " -+"Authentification requise pour mettre à jour l’espace personnel d’un " - "utilisateur." - - #: src/home/org.freedesktop.home1.policy:53 -@@ -116,33 +119,34 @@ msgstr "Authentification requise pour retailler un espace personnel." - - #: src/home/org.freedesktop.home1.policy:63 - msgid "Change password of a home area" --msgstr "Changer le mot de passe d'un espace personnel" -+msgstr "Changer le mot de passe d’un espace personnel" - - #: src/home/org.freedesktop.home1.policy:64 --msgid "Authentication is required to change the password of a user's home area." -+msgid "" -+"Authentication is required to change the password of a user's home area." - msgstr "" --"Authentification requise pour changer le mot de passe de l'espace personnel " --"d'un utilisateur." -+"Authentification requise pour changer le mot de passe de l’espace personnel " -+"d’un utilisateur." - - #: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" --msgstr "Définir le nom d'hôte" -+msgstr "Définir le nom d’hôte" - - #: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." --msgstr "Authentification requise pour définir le nom d'hôte local." -+msgstr "Authentification requise pour définir le nom d’hôte local." - - #: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" --msgstr "Définir le nom d'hôte statique" -+msgstr "Définir le nom d’hôte statique" - - #: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." - msgstr "" --"Authentification requise pour définir le nom d'hôte local de manière " --"statique, tout comme le nom d'hôte familier." -+"Authentification requise pour définir le nom d’hôte local de manière " -+"statique, tout comme le nom d’hôte familier." - - #: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" -@@ -155,11 +159,11 @@ msgstr "" - - #: src/hostname/org.freedesktop.hostname1.policy:51 - msgid "Get product UUID" --msgstr "Obtenir l'UUID du produit" -+msgstr "Obtenir l’UUID du produit" - - #: src/hostname/org.freedesktop.hostname1.policy:52 - msgid "Authentication is required to get product UUID." --msgstr "Authentification requise pour obtenir l'UUID du produit." -+msgstr "Authentification requise pour obtenir l’UUID du produit." - - #: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" -@@ -169,7 +173,7 @@ msgstr "Importer une image de machine virtuelle (VM) ou de conteneur" - msgid "Authentication is required to import a VM or container image" - msgstr "" - "Authentification requise pour importer une image de machine virtuelle (VM) " --"ou de conteneur." -+"ou de conteneur" - - #: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" -@@ -179,7 +183,7 @@ msgstr "Exporter une image de machine virtuelle (VM) ou de conteneur" - msgid "Authentication is required to export a VM or container image" - msgstr "" - "Authentification requise pour exporter une image de machine virtuelle (VM) " --"ou de conteneur." -+"ou de conteneur" - - #: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" -@@ -188,8 +192,8 @@ msgstr "Télécharger une image de machine virtuelle (VM) ou de conteneur" - #: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "" --"Authentification requise pour télécharger une image de machine virtuelle " --"(VM) ou de conteneur." -+"Authentification requise pour télécharger une image de machine virtuelle (VM)" -+" ou de conteneur" - - #: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" -@@ -210,33 +214,33 @@ msgstr "" - - #: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" --msgstr "Permet aux applications d'empêcher l'arrêt du système" -+msgstr "Permet aux applications d’empêcher l’arrêt du système" - - #: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" --"Authentification requise pour permettre à une application d'empêcher l'arrêt " -+"Authentification requise pour permettre à une application d’empêcher l’arrêt " - "du système." - - #: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" --msgstr "Permet aux applications de retarder l'arrêt du système" -+msgstr "Permet aux applications de retarder l’arrêt du système" - - #: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" --"Authentification requise pour permettre à une application de retarder " --"l'arrêt du système." -+"Authentification requise pour permettre à une application de retarder l’" -+"arrêt du système." - - #: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" --msgstr "Permet aux applications d'empêcher la mise en veille du système" -+msgstr "Permet aux applications d’empêcher la mise en veille du système" - - #: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" --"Authentification requise pour permettre à une application d'empêcher la mise " -+"Authentification requise pour permettre à une application d’empêcher la mise " - "en veille du système." - - #: src/login/org.freedesktop.login1.policy:55 -@@ -251,21 +255,20 @@ msgstr "" - - #: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" --msgstr "" --"Permet aux applications d'empêcher l'hibernation automatique du système" -+msgstr "Permet aux applications d’empêcher l’hibernation automatique du système" - - #: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." - msgstr "" --"Authentification requise pour permettre à une application d'empêcher " --"l'hibernation automatique du système." -+"Authentification requise pour permettre à une application d’empêcher l’" -+"hibernation automatique du système." - - #: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" --"Permet aux applications d'empêcher la gestion du bouton d'alimentation du " -+"Permet aux applications d’empêcher la gestion du bouton d’alimentation du " - "système" - - #: src/login/org.freedesktop.login1.policy:76 -@@ -273,13 +276,13 @@ msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." - msgstr "" --"Authentification requise pour permettre à une application d'empêcher la " --"gestion du bouton d'alimentation du système." -+"Authentification requise pour permettre à une application d’empêcher la " -+"gestion du bouton d’alimentation du système." - - #: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" --"Permet aux applications d'empêcher la gestion du bouton de mise en veille du " -+"Permet aux applications d’empêcher la gestion du bouton de mise en veille du " - "système" - - #: src/login/org.freedesktop.login1.policy:87 -@@ -287,13 +290,13 @@ msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." - msgstr "" --"Authentification requise pour permettre à une application d'empêcher la " -+"Authentification requise pour permettre à une application d’empêcher la " - "gestion du bouton de mise en veille du système." - - #: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" --"Permet aux applications d'empêcher la gestion du bouton d'hibernation du " -+"Permet aux applications d’empêcher la gestion du bouton d’hibernation du " - "système" - - #: src/login/org.freedesktop.login1.policy:98 -@@ -301,46 +304,46 @@ msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." - msgstr "" --"Authentification requise pour permettre à une application d'empêcher la " --"gestion du bouton d'hibernation du système." -+"Authentification requise pour permettre à une application d’empêcher la " -+"gestion du bouton d’hibernation du système." - - #: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" --"Permet aux applications d'empêcher la gestion par le système du rabat de " --"l'écran" -+"Permet aux applications d’empêcher la gestion par le système du rabat de " -+"l’écran" - - #: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." - msgstr "" --"Authentification requise pour permettre à une application d'empêcher la " --"gestion par le système du rabat de l'écran." -+"Authentification requise pour permettre à une application d’empêcher la " -+"gestion par le système du rabat de l’écran." - - #: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" --msgstr "Permet à un utilisateur non connecté d'exécuter des programmes" -+msgstr "Permet à un utilisateur non connecté d’exécuter des programmes" - - #: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" --"Requête explicite requise pour exécuter des programmes en tant " --"qu'utilisateur non connecté." -+"Requête explicite requise pour exécuter des programmes en tant qu’" -+"utilisateur non connecté." - - #: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" --msgstr "Permet aux utilisateurs non connectés d'exécuter des programmes" -+msgstr "Permet aux utilisateurs non connectés d’exécuter des programmes" - - #: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" --"Authentification requise pour exécuter des programmes en tant qu'utilisateur " -+"Authentification requise pour exécuter des programmes en tant qu’utilisateur " - "non connecté." - - #: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" --msgstr "Permet d'associer des périphériques à des postes (seats)" -+msgstr "Permet d’associer des périphériques à des postes (seats)" - - #: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." -@@ -352,8 +355,7 @@ msgid "Flush device to seat attachments" - msgstr "Révoquer les associations de périphériques aux postes (seats)" - - #: src/login/org.freedesktop.login1.policy:149 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Authentification requise pour révoquer les associations de périphériques aux " - "postes (seats)." -@@ -368,27 +370,27 @@ msgstr "Authentification requise pour éteindre le système." - - #: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" --msgstr "Éteindre le système alors que d'autres utilisateurs sont connectés" -+msgstr "Éteindre le système alors que d’autres utilisateurs sont connectés" - - #: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." - msgstr "" --"Authentification requise pour éteindre le système alors que d'autres " -+"Authentification requise pour éteindre le système alors que d’autres " - "utilisateurs sont connectés." - - #: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" --msgstr "Éteindre le système alors qu'une application a demandé de l'empêcher" -+msgstr "Éteindre le système alors qu’une application a demandé de l’empêcher" - - #: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" --"Authentification requise pour éteindre le système alors qu'une application a " --"demandé de l'empêcher." -+"Authentification requise pour éteindre le système alors qu’une application a " -+"demandé de l’empêcher." - - #: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" -@@ -400,27 +402,27 @@ msgstr "Authentification requise pour redémarrer le système." - - #: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" --msgstr "Redémarrer le système alors que d'autres utilisateurs sont connectés" -+msgstr "Redémarrer le système alors que d’autres utilisateurs sont connectés" - - #: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" --"Authentification requise pour redémarrer le système alors que d'autres " -+"Authentification requise pour redémarrer le système alors que d’autres " - "utilisateurs sont connectés." - - #: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" --msgstr "Redémarrer le système alors qu'une application a demandé de l'empêcher" -+msgstr "Redémarrer le système alors qu’une application a demandé de l’empêcher" - - #: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" --"Authentification requise pour redémarrer le système alors qu'une application " --"a demandé de l'empêcher." -+"Authentification requise pour redémarrer le système alors qu’une application " -+"a demandé de l’empêcher." - - #: src/login/org.freedesktop.login1.policy:224 - msgid "Halt the system" -@@ -432,27 +434,31 @@ msgstr "Authentification requise pour arrêter le système." - - #: src/login/org.freedesktop.login1.policy:235 - msgid "Halt the system while other users are logged in" --msgstr "Arrêter le système alors que d'autres utilisateurs sont connectés" -+msgstr "Arrêter le système alors que d’autres utilisateurs sont connectés" - - #: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "" --"Authentification requise pour arrêter le système alors que d'autres " -+"Authentification requise pour arrêter le système alors que d’autres " - "utilisateurs sont connectés." - - #: src/login/org.freedesktop.login1.policy:246 - msgid "Halt the system while an application is inhibiting this" --msgstr "Arrêter le système alors qu'une application a demandé de l'empêcher" -+msgstr "Arrêter le système alors qu’une application a demandé de l’empêcher" - - #: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." -+"Authentication is required to halt the system while an application is " -+"inhibiting this." - msgstr "" --"Authentification requise pour arrêter le système alors qu'une application a " --"demandé de l'empêcher." -+"Authentification requise pour mettre le système en hibernation alors qu'une " -+"application a demandé de l'empêcher." - - #: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" -@@ -465,28 +471,28 @@ msgstr "Authentification requise pour mettre le système en veille." - #: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "" --"Mettre le système en veille alors que d'autres utilisateurs sont connectés" -+"Mettre le système en veille alors que d’autres utilisateurs sont connectés" - - #: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." - msgstr "" --"Authentification requise pour mettre le système en veille alors que d'autres " -+"Authentification requise pour mettre le système en veille alors que d’autres " - "utilisateurs sont connectés." - - #: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "" --"Mettre le système en veille alors qu'une application a demandé de l'empêcher" -+"Mettre le système en veille alors qu’une application a demandé de l’empêcher" - - #: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" --"Authentification requise pour mettre le système en veille alors qu'une " --"application a demandé de l'empêcher." -+"Authentification requise pour mettre le système en veille alors qu’une " -+"application a demandé de l’empêcher." - - #: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" -@@ -499,7 +505,7 @@ msgstr "Authentification requise pour mettre le système en hibernation." - #: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "" --"Mettre le système en hibernation alors que d'autres utilisateurs sont " -+"Mettre le système en hibernation alors que d’autres utilisateurs sont " - "connectés" - - #: src/login/org.freedesktop.login1.policy:300 -@@ -507,30 +513,29 @@ msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." - msgstr "" --"Authentification requise pour mettre le système en hibernation alors que " --"d'autres utilisateurs sont connectés." -+"Authentification requise pour mettre le système en hibernation alors que d’" -+"autres utilisateurs sont connectés." - - #: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "" --"Mettre le système en hibernation alors qu'une application a demandé de " --"l'empêcher" -+"Mettre le système en hibernation alors qu’une application a demandé de " -+"l’empêcher" - - #: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" --"Authentification requise pour mettre le système en hibernation alors qu'une " --"application a demandé de l'empêcher." -+"Authentification requise pour mettre le système en hibernation alors qu’une " -+"application a demandé de l’empêcher." - - #: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Gérer les sessions actives, les utilisateurs et les postes (seats)" - - #: src/login/org.freedesktop.login1.policy:322 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Authentification requise pour gérer les sessions actives, les utilisateurs " - "et les postes (seats)." -@@ -547,48 +552,48 @@ msgstr "" - - #: src/login/org.freedesktop.login1.policy:341 - msgid "Set the reboot \"reason\" in the kernel" --msgstr "Définir la « raison » du redémarrage dans le noyau" -+msgstr "Définir la « raison » du redémarrage dans le noyau" - - #: src/login/org.freedesktop.login1.policy:342 - msgid "Authentication is required to set the reboot \"reason\" in the kernel." - msgstr "" --"Authentification requise pour définir la « raison » du redémarrage dans le " -+"Authentification requise pour définir la « raison » du redémarrage dans le " - "noyau." - - #: src/login/org.freedesktop.login1.policy:352 - msgid "Indicate to the firmware to boot to setup interface" --msgstr "Indiquer au micrologiciel de démarrer sur l'interface de configuration" -+msgstr "Indiquer au micrologiciel de démarrer sur l’interface de configuration" - - #: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." - msgstr "" --"Authentification requise pour indiquer au micrologiciel de démarrer sur " --"l'interface de configuration." -+"Authentification requise pour indiquer au micrologiciel de démarrer sur l’" -+"interface de configuration." - - #: src/login/org.freedesktop.login1.policy:363 - msgid "Indicate to the boot loader to boot to the boot loader menu" --msgstr "Indiquer au programme d'amorçage d'afficher le menu au démarrage" -+msgstr "Indiquer au programme d’amorçage d’afficher le menu au démarrage" - - #: src/login/org.freedesktop.login1.policy:364 - msgid "" - "Authentication is required to indicate to the boot loader to boot to the " - "boot loader menu." - msgstr "" --"Authentification requise pour indiquer au programme d'amorçage d'afficher le " -+"Authentification requise pour indiquer au programme d’amorçage d’afficher le " - "menu au démarrage." - - #: src/login/org.freedesktop.login1.policy:374 - msgid "Indicate to the boot loader to boot a specific entry" --msgstr "Indiquer au programme d'amorçage de démarrer une entrée spécifique" -+msgstr "Indiquer au programme d’amorçage de démarrer une entrée spécifique" - - #: src/login/org.freedesktop.login1.policy:375 - msgid "" - "Authentication is required to indicate to the boot loader to boot into a " - "specific boot loader entry." - msgstr "" --"Authentification requise pour indiquer au programme d'amorçage de démarrer " -+"Authentification requise pour indiquer au programme d’amorçage de démarrer " - "une entrée spécifique." - - #: src/login/org.freedesktop.login1.policy:385 -@@ -597,7 +602,7 @@ msgstr "Définir un message wall" - - #: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" --msgstr "Authentification requise pour définir un message wall." -+msgstr "Authentification requise pour définir un message wall" - - #: src/login/org.freedesktop.login1.policy:395 - msgid "Change Session" -@@ -618,11 +623,11 @@ msgstr "" - - #: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" --msgstr "Connexion à l'hôte local" -+msgstr "Connexion à l’hôte local" - - #: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." --msgstr "Authentification requise pour permettre la connexion à l'hôte local." -+msgstr "Authentification requise pour permettre la connexion à l’hôte local." - - #: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" -@@ -636,12 +641,12 @@ msgstr "" - - #: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" --msgstr "Obtenir une interface système sur l'hôte local" -+msgstr "Obtenir une interface système sur l’hôte local" - - #: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "" --"Authentification requise pour obtenir une interface système sur l'hôte local." -+"Authentification requise pour obtenir une interface système sur l’hôte local." - - #: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" -@@ -656,12 +661,12 @@ msgstr "" - - #: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" --msgstr "Obtenir un pseudo terminal sur l'hôte local" -+msgstr "Obtenir un pseudo terminal sur l’hôte local" - - #: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "" --"Authentification requise pour obtenir un pseudo terminal sur l'hôte local." -+"Authentification requise pour obtenir un pseudo terminal sur l’hôte local." - - #: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" -@@ -763,7 +768,7 @@ msgstr "Activer/désactiver DNSSEC" - #: src/network/org.freedesktop.network1.policy:100 - #: src/resolve/org.freedesktop.resolve1.policy:111 - msgid "Authentication is required to enable or disable DNSSEC." --msgstr "Authentification requise pour activer ou désactiver DNSSEC" -+msgstr "Authentification requise pour activer ou désactiver DNSSEC." - - #: src/network/org.freedesktop.network1.policy:110 - #: src/resolve/org.freedesktop.resolve1.policy:121 -@@ -793,26 +798,36 @@ msgid "Authentication is required to reset DNS settings." - msgstr "Authentification requise pour réinitialiser les paramètres DNS." - - #: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Authentification requise pour définir un message wall." -+ -+#: src/network/org.freedesktop.network1.policy:154 - msgid "Renew dynamic addresses" - msgstr "Renouveler les adresses dynamiques" - --#: src/network/org.freedesktop.network1.policy:144 -+#: src/network/org.freedesktop.network1.policy:155 - msgid "Authentication is required to renew dynamic addresses." - msgstr "Authentification requise pour renouveler les adresses dynamiques." - --#: src/network/org.freedesktop.network1.policy:154 -+#: src/network/org.freedesktop.network1.policy:165 - msgid "Reload network settings" - msgstr "Recharger les paramètres réseau" - --#: src/network/org.freedesktop.network1.policy:155 -+#: src/network/org.freedesktop.network1.policy:166 - msgid "Authentication is required to reload network settings." - msgstr "Authentification requise pour recharger les paramètres réseau." - --#: src/network/org.freedesktop.network1.policy:165 -+#: src/network/org.freedesktop.network1.policy:176 - msgid "Reconfigure network interface" - msgstr "Reconfigurer une interface réseau" - --#: src/network/org.freedesktop.network1.policy:166 -+#: src/network/org.freedesktop.network1.policy:177 - msgid "Authentication is required to reconfigure network interface." - msgstr "Authentification requise pour reconfigurer une interface réseau." - -@@ -874,11 +889,11 @@ msgstr "" - - #: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" --msgstr "Définir l'heure du système" -+msgstr "Définir l’heure du système" - - #: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." --msgstr "Authentification requise pour définir l'heure du système." -+msgstr "Authentification requise pour définir l’heure du système." - - #: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" -@@ -891,7 +906,7 @@ msgstr "Authentification requise pour définir le fuseau horaire du système." - #: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "" --"Positionner l'horloge matérielle à l'heure locale ou sur le temps universel " -+"Positionner l’horloge matérielle à l’heure locale ou sur le temps universel " - "coordonné (UTC)" - - #: src/timedate/org.freedesktop.timedate1.policy:44 -@@ -899,62 +914,80 @@ msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." - msgstr "" --"Authentification requise pour positionner l'horloge matérielle à l'heure " -+"Authentification requise pour positionner l’horloge matérielle à l’heure " - "locale ou sur le temps universel coordonné (UTC)." - - #: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" --msgstr "Activer ou désactiver la synchronisation de l'heure avec le réseau" -+msgstr "Activer ou désactiver la synchronisation de l’heure avec le réseau" - - #: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." - msgstr "" --"Authentification requise pour activer ou désactiver la synchronisation de " --"l'heure avec le réseau." -+"Authentification requise pour activer ou désactiver la synchronisation de l’" -+"heure avec le réseau." - --#: src/core/dbus-unit.c:355 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." --msgstr "Authentification requise pour démarrer « $(unit) »." -+msgstr "Authentification requise pour démarrer « $(unit) »." - --#: src/core/dbus-unit.c:356 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." --msgstr "Authentification requise pour arrêter « $(unit) »." -+msgstr "Authentification requise pour arrêter « $(unit) »." - --#: src/core/dbus-unit.c:357 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." --msgstr "Authentification requise pour recharger « $(unit) »." -+msgstr "Authentification requise pour recharger « $(unit) »." - --#: src/core/dbus-unit.c:358 src/core/dbus-unit.c:359 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." --msgstr "Authentification requise pour redémarrer « $(unit) »." -+msgstr "Authentification requise pour redémarrer « $(unit) »." - --#: src/core/dbus-unit.c:531 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." - msgstr "" --"Authentification requise pour envoyer un signal UNIX aux processus de " --"« $(unit) »." -+"Authentification requise pour envoyer un signal UNIX aux processus de « " -+"$(unit) »." - --#: src/core/dbus-unit.c:562 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" --"Authentification requise pour réinitialiser l'état d'« échec » de " --"« $(unit) »." -+"Authentification requise pour réinitialiser l’état d’« échec » de « $(unit) " -+"»." - --#: src/core/dbus-unit.c:595 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." --msgstr "Authentification requise pour définir des propriétés de « $(unit) »." -+msgstr "Authentification requise pour définir des propriétés de « $(unit) »." - --#: src/core/dbus-unit.c:704 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." - msgstr "" - "Authentification requise pour supprimer les fichiers et les dossiers " --"associés à « $(unit) »." -+"associés à « $(unit) »." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to send a UNIX signal to the processes of " -+#| "'$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Authentification requise pour envoyer un signal UNIX aux processus de " -+"« $(unit) »." -+ -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "" -+#~ "Authentification requise pour arrêter le système alors qu'une application " -+#~ "a demandé de l'empêcher." - - #~ msgid "Authentication is required to kill '$(unit)'." - #~ msgstr "Authentification requise pour tuer « $(unit) »." -diff --git a/po/gl.po b/po/gl.po -index 147d34d..d58c493 100644 ---- a/po/gl.po -+++ b/po/gl.po -@@ -4,8 +4,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2019-10-26 14:02+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2019-12-29 22:30+0100\n" - "Last-Translator: Fran Diéguez \n" - "Language-Team: gnome-l10n-gl@gnome.org\n" -@@ -69,6 +69,74 @@ msgstr "Recargar o estado de systemd" - msgid "Authentication is required to reload the systemd state." - msgstr "Requírese autenticación para recargar o estado de systemd." - -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to set NTP servers." -+msgid "Authentication is required to create a user's home area." -+msgstr "Requírese autenticación para estabelecer os servidores NTP." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to set NTP servers." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Requírese autenticación para estabelecer os servidores NTP." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to attach or detach a portable service image." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Requírese autenticación para anexar ou desanexar unha imaxe de servizo " -+"portábel." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "Requírese autenticación para anexar un dispositivo a un asento." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set NTP servers." -+msgid "Authentication is required to resize a user's home area." -+msgstr "Requírese autenticación para estabelecer os servidores NTP." -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Requírese autenticación para xestionar as sesións, usuarios e asentos " -+"activos." -+ - #: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Estabelecer o nome do equipo" -@@ -288,8 +356,7 @@ msgid "Flush device to seat attachments" - msgstr "Reiniciar os anexos do dispositivo aos asentos" - - #: src/login/org.freedesktop.login1.policy:149 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Requírese autenticación para reiniciar como os dispositivos están anexados " - "aos asentos." -@@ -320,8 +387,8 @@ msgstr "Apagar o sistema cando unha aplicación solicitou a súa inhibición" - - #: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Requírese autenticación para apagar o sistema mentres unha aplicación " - "solicitou a súa inhibición." -@@ -340,8 +407,8 @@ msgstr "Reiniciar o sistema mentres outros usuarios teñen unha sesión iniciada - - #: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Requírese autenticación para reiniciar o sistema mentres outros usuarios " - "teñen unha sesión iniciada." -@@ -352,8 +419,8 @@ msgstr "Reiniciar o sistema cando unha aplicación solicitou a súa inhibición" - - #: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Requírese autenticación para reiniciar o sistema mentres unha aplicación " - "solicitou a súa inhibición." -@@ -372,8 +439,8 @@ msgstr "Deter o sistema mentres outros usuarios teñen unha sesión iniciada" - - #: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "" - "Requírese autenticación para deter o sistema mentres outros usuarios teñen " - "unha sesión iniciada." -@@ -383,11 +450,15 @@ msgid "Halt the system while an application is inhibiting this" - msgstr "Deter o sistema cando unha aplicación solicitou a súa inhibición" - - #: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." -+"Authentication is required to halt the system while an application is " -+"inhibiting this." - msgstr "" --"Requírese autenticación para deter o sistema mentres unha aplicación " -+"Requírese autenticación para hibernar o sistema mentres unha aplicación " - "solicitou a súa inhibición." - - #: src/login/org.freedesktop.login1.policy:257 -@@ -416,8 +487,8 @@ msgstr "Suspender o sistema cando unha aplicación solicitou a súa inhibición" - - #: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Requírese autenticación para suspender o sistema mentres unha aplicación " - "solicitou a súa inhibición." -@@ -448,8 +519,8 @@ msgstr "Hibernar o sistema cando unha aplicación solicitou a súa inhibición" - - #: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Requírese autenticación para hibernar o sistema mentres unha aplicación " - "solicitou a súa inhibición." -@@ -459,8 +530,7 @@ msgid "Manage active sessions, users and seats" - msgstr "Xestionar as sesións, usuarios e asentos activos" - - #: src/login/org.freedesktop.login1.policy:322 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Requírese autenticación para xestionar as sesións, usuarios e asentos " - "activos." -@@ -529,6 +599,16 @@ msgstr "Estabelecer a mensaxe do muro" - msgid "Authentication is required to set a wall message" - msgstr "Requírese autenticación para estabelecer unha mensaxe de muro" - -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to halt the system." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Requírese autenticación para deter o sistema." -+ - #: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Iniciar sesión nun contenedor local" -@@ -711,26 +791,36 @@ msgid "Authentication is required to reset DNS settings." - msgstr "Requírese autenticación para restabelecer as preferencias de DNS." - - #: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Requírese autenticación para estabelecer unha mensaxe de muro" -+ -+#: src/network/org.freedesktop.network1.policy:154 - msgid "Renew dynamic addresses" - msgstr "Renovar enderezos dinámicos" - --#: src/network/org.freedesktop.network1.policy:144 -+#: src/network/org.freedesktop.network1.policy:155 - msgid "Authentication is required to renew dynamic addresses." - msgstr "Requírese autenticación para renovar o enderezo dinámico." - --#: src/network/org.freedesktop.network1.policy:154 -+#: src/network/org.freedesktop.network1.policy:165 - msgid "Reload network settings" - msgstr "Recargar as preferencias de rede" - --#: src/network/org.freedesktop.network1.policy:155 -+#: src/network/org.freedesktop.network1.policy:166 - msgid "Authentication is required to reload network settings." - msgstr "Requírese autenticación para recargar as preferencias da rede." - --#: src/network/org.freedesktop.network1.policy:165 -+#: src/network/org.freedesktop.network1.policy:176 - msgid "Reconfigure network interface" - msgstr "Reconfigurar a interface de rede" - --#: src/network/org.freedesktop.network1.policy:166 -+#: src/network/org.freedesktop.network1.policy:177 - msgid "Authentication is required to reconfigure network interface." - msgstr "Requírese autenticación para reconfigurar a inteface de rede." - -@@ -831,23 +921,23 @@ msgstr "" - "Requírese autenticación para controlar se a sincronización de hora por rede " - "debería activarse." - --#: src/core/dbus-unit.c:354 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Requírese autenticación para inciar '$(unit)'." - --#: src/core/dbus-unit.c:355 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Requírese autenticación para deter '$(unit)'." - --#: src/core/dbus-unit.c:356 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Requírese autenticación para recargar '$(unit)'." - --#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Requírese autenticación para reiniciar '$(unit)'." - --#: src/core/dbus-unit.c:530 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." -@@ -855,19 +945,37 @@ msgstr "" - "Requírese autenticación para enviarlle un sinal UNIX aos procesos de " - "'$(unit)'." - --#: src/core/dbus-unit.c:561 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Requírese autenticación para reinicair o estado «fallido» de '$(unit)'." - --#: src/core/dbus-unit.c:594 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Requírese autenticación para estabelecer as propiedades en '$(unit)'." - --#: src/core/dbus-unit.c:703 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." - msgstr "" - "Requírese autenticación para eliminar ficheiros ou directorios asociados con " - "'$(unit)'." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to send a UNIX signal to the processes of " -+#| "'$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Requírese autenticación para enviarlle un sinal UNIX aos procesos de " -+"'$(unit)'." -+ -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "" -+#~ "Requírese autenticación para deter o sistema mentres unha aplicación " -+#~ "solicitou a súa inhibición." -diff --git a/po/hr.po b/po/hr.po -index 8385d5a..6cf7e8a 100644 ---- a/po/hr.po -+++ b/po/hr.po -@@ -3,22 +3,23 @@ - # SOME DESCRIPTIVE TITLE. - # This file is distributed under the same license as the PACKAGE package. - # gogo , 2016. --# -+# Gogo Gogsi , 2020. - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2020-03-08 12:55+0100\n" --"PO-Revision-Date: 2020-03-08 12:57+0100\n" --"Last-Translator: gogo \n" --"Language-Team: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" -+"PO-Revision-Date: 2020-08-29 11:29+0000\n" -+"Last-Translator: Gogo Gogsi \n" -+"Language-Team: Croatian \n" - "Language: hr\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" --"X-Generator: Poedit 2.0.6\n" --"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" --"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -+"X-Generator: Weblate 4.2.1\n" - - #: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" -@@ -563,7 +564,7 @@ msgstr "Postavljanje zaslonske pruke" - - #: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" --msgstr "Potrebna je ovjera za postavljanje zaslonske pruke." -+msgstr "Potrebna je ovjera za postavljanje zaslonske poruke." - - #: src/login/org.freedesktop.login1.policy:395 - msgid "Change Session" -@@ -873,40 +874,46 @@ msgstr "" - "Potrebna je ovjera za uključivanje ili isključivanje mrežnog usklađivanja " - "vremena." - --#: src/core/dbus-unit.c:356 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Potrebna je ovjera za pokretanje '$(unit)'." - --#: src/core/dbus-unit.c:357 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Potrebna je ovjera za zaustavljanje '$(unit)'." - --#: src/core/dbus-unit.c:358 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Potrebna je ovjera za ponovno učitavnje '$(unit)'." - --#: src/core/dbus-unit.c:359 src/core/dbus-unit.c:360 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Potrebna je ovjera za ponovno pokretanje'$(unit)'." - --#: src/core/dbus-unit.c:532 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." - msgstr "Potrebna je ovjera za slanje UNIX signala u procese '$(unit)'." - --#: src/core/dbus-unit.c:563 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "Potrebna je ovjera za vraćanje \"neuspjelog\" stanja '$(unit)'." - --#: src/core/dbus-unit.c:596 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Potrebna je ovjera za postavljanje svojstava na '$(unit)'." - --#: src/core/dbus-unit.c:705 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." - msgstr "" --"Potrebna je ovjera za za brisanje datoteka i direktorija pridruženih sa " -+"Potrebna je ovjera za brisanje datoteka i direktorija pridruženih sa " - "'$(unit)'." -+ -+#: src/core/dbus-unit.c:760 -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Potrebna je ovjera za zamrzavanje ili odmrzavanje procesa '$(unit)' jedinice." -diff --git a/po/hu.po b/po/hu.po -index e4e5d54..d36bb4b 100644 ---- a/po/hu.po -+++ b/po/hu.po -@@ -8,8 +8,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2016-04-24 12:53+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2016-08-23 18:03+0100\n" - "Last-Translator: Balázs Úr \n" - "Language-Team: Hungarian \n" -@@ -20,41 +20,41 @@ msgstr "" - "Plural-Forms: nplurals=2; plural=(n != 1);\n" - "X-Generator: Lokalize 2.0\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Jelmondat visszaküldése a rendszernek" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "" - "Hitelesítés szükséges a bevitt jelmondat visszaküldéséhez a rendszernek." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Rendszerszolgáltatások vagy más egységek kezelése" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" - "Hitelesítés szükséges a rendszerszolgáltatások vagy más egységek kezeléséhez." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Rendszerszolgáltatás- vagy egységfájlok kezelése" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" - "Hitelesítés szükséges a rendszerszolgáltatás- vagy egységfájlok kezeléséhez." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "" - "Rendszer- és szolgáltatáskezelő környezeti változóinak beállítása vagy " - "törlése" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -62,27 +62,97 @@ msgstr "" - "Hitelesítés szükséges a rendszer- és szolgáltatáskezelő környezeti " - "változóinak beállításához vagy törléséhez." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "A systemd állapotának újratöltése" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások " -+"kezeléséhez." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy " -+"munkaállomáshoz" -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Hitelesítés szükséges a falüzenet beállításához" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások " -+"kezeléséhez." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Gépnév beállítása" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Hitelesítés szükséges a helyi gépnév beállításához." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Statikus gépnév beállítása" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -90,100 +160,110 @@ msgstr "" - "Hitelesítés szükséges a statikusan megadott helyi gépnév, valamint a szép " - "gépnév beállításához." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Gépinformációk beállítása" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "Hitelesítés szükséges a helyi gép információinak beállításához." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Hitelesítés szükséges a következő újratöltéséhez: „$(unit)”." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "VM vagy konténer lemezkép importálása" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép importálásához." - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "VM vagy konténer lemezkép exportálása" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép exportálásához." - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "VM vagy konténer lemezkép letöltése" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép letöltéséhez." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Területi beállítás megadása" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "Hitelesítés szükséges a rendszer területi beállításainak megadásához." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Rendszer billentyűzetbeállítások megadása" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" - "Hitelesítés szükséges a rendszer billentyűzetbeállításainak megadásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Alkalmazások meggátolhatják a rendszer leállítását" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - "Hitelesítés szükséges egy alkalmazás számára a rendszerleállítás " - "meggátlásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Alkalmazások késleltethetik a rendszer leállítását" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "Hitelesítés szükséges egy alkalmazás számára a rendszerleállítás " - "késleltetéséhez." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Alkalmazások meggátolhatják a rendszer altatását" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "Hitelesítés szükséges egy alkalmazás számára a rendszeraltatás meggátlásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Alkalmazások késleltethetik a rendszer altatását" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "Hitelesítés szükséges egy alkalmazás számára a rendszeraltatás " - "késleltetéséhez." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "Alkalmazások meggátolhatják a rendszer automatikus felfüggesztését" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -191,12 +271,12 @@ msgstr "" - "Hitelesítés szükséges egy alkalmazás számára az automatikus " - "rendszerfelfüggesztés meggátlásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" - "Alkalmazások meggátolhatják a bekapcsoló gomb rendszer általi kezelését" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." -@@ -204,12 +284,12 @@ msgstr "" - "Hitelesítés szükséges egy alkalmazás számára a bekapcsoló gomb rendszer " - "általi kezelésének meggátlásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" - "Alkalmazások meggátolhatják a felfüggesztés gomb rendszer általi kezelését" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." -@@ -217,12 +297,12 @@ msgstr "" - "Hitelesítés szükséges egy alkalmazás számára a felfüggesztés gomb rendszer " - "általi kezelésének meggátlásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" - "Alkalmazások meggátolhatják a hibernálás gomb rendszer általi kezelését" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -230,11 +310,11 @@ msgstr "" - "Hitelesítés szükséges egy alkalmazás számára a hibernálás gomb rendszer " - "általi kezelésének meggátlásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "Alkalmazások meggátolhatják a fedélkapcsoló rendszer általi kezelését" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -242,61 +322,60 @@ msgstr "" - "Hitelesítés szükséges egy alkalmazás számára a fedélkapcsoló rendszer általi " - "kezelésének meggátlásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" - msgstr "Programfuttatás engedélyezése be nem jelentkezett felhasználó számára" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" - "Határozott kérés szükséges a programfuttatáshoz be nem jelentkezett " - "felhasználóként." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "Programfuttatás engedélyezése be nem jelentkezett felhasználók számára" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Hitelesítés szükséges a programfuttatáshoz be nem jelentkezett " - "felhasználóként." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Eszközök csatolásának engedélyezése munkaállomásokhoz" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "" - "Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy " - "munkaállomáshoz" - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Eszközök és munkaállomások csatolásainak törlése" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Hitelesítés szükséges az eszközök munkaállomásokhoz csatolásainak " - "alaphelyzetbe állításához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "A rendszer kikapcsolása" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Hitelesítés szükséges a rendszer kikapcsolásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "" - "A rendszer kikapcsolása miközben be vannak jelentkezve más felhasználók" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -304,66 +383,114 @@ msgstr "" - "Hitelesítés szükséges a rendszer kikapcsolásához miközben be vannak " - "jelentkezve más felhasználók." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "" - "A rendszer kikapcsolása miközben egy alkalmazás ennek meggátlását kérte" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Hitelesítés szükséges a rendszer kikapcsolásához miközben egy alkalmazás " - "ennek meggátlását kérte." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "A rendszer újraindítása" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Hitelesítés szükséges a rendszer újraindításához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "A rendszer újraindítása mialatt be vannak jelentkezve más felhasználók" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Hitelesítés szükséges a rendszer újraindításához miközben be vannak " - "jelentkezve más felhasználók." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "" - "A rendszer újraindítása miközben egy alkalmazás ennek meggátlását kérte" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Hitelesítés szükséges a rendszer újraindításához miközben egy alkalmazás " - "ennek meggátlását kérte." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "A rendszer hibernálása" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "Hitelesítés szükséges a rendszer hibernálásához." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "A rendszer hibernálása mialatt be vannak jelentkezve más felhasználók" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"Hitelesítés szükséges a rendszer hibernálásához miközben be vannak " -+"jelentkezve más felhasználók." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "A rendszer hibernálása miközben egy alkalmazás ennek meggátlását kérte" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"Hitelesítés szükséges a rendszer hibernálásához miközben egy alkalmazás " -+"ennek meggátlását kérte." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "A rendszer felfüggesztése" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Hitelesítés szükséges a rendszer felfüggesztéséhez." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "" - "A rendszer felfüggesztése mialatt be vannak jelentkezve más felhasználók" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -371,32 +498,32 @@ msgstr "" - "Hitelesítés szükséges a rendszer felfüggesztéséhez miközben be vannak " - "jelentkezve más felhasználók." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "" - "A rendszer felfüggesztése miközben egy alkalmazás ennek meggátlását kérte" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Hitelesítés szükséges a rendszer felfüggesztéséhez miközben egy alkalmazás " - "ennek meggátlását kérte." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "A rendszer hibernálása" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "Hitelesítés szükséges a rendszer hibernálásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "A rendszer hibernálása mialatt be vannak jelentkezve más felhasználók" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -404,43 +531,54 @@ msgstr "" - "Hitelesítés szükséges a rendszer hibernálásához miközben be vannak " - "jelentkezve más felhasználók." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "A rendszer hibernálása miközben egy alkalmazás ennek meggátlását kérte" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Hitelesítés szükséges a rendszer hibernálásához miközben egy alkalmazás " - "ennek meggátlását kérte." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Aktív munkamenetek, felhasználók és munkaállomások kezelése" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások " - "kezeléséhez." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Aktív munkamenetek zárolása vagy feloldása" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "" - "Hitelesítés szükséges az aktív munkamenetek zárolásához vagy feloldásához." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Hitelesítés szükséges a rendszer időzónájának beállításához." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "A firmware-nek jelezhető, hogy a beállítófelületet bootolja" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -448,77 +586,119 @@ msgstr "" - "Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet " - "bootolja" - --#: ../src/login/org.freedesktop.login1.policy.in.h:57 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet " -+"bootolja" -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet " -+"bootolja" -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Falüzenet beállítása" - --#: ../src/login/org.freedesktop.login1.policy.in.h:58 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Hitelesítés szükséges a falüzenet beállításához" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Hitelesítés szükséges a helyi gépnév beállításához." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Bejelentkezés helyi konténerbe" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Bejelentkezés a helyi gépre" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "Hitelesítés szükséges a bejelentkezéshez a helyi gépre." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Parancsértelmező elérése helyi konténerben" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez helyi konténerben." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Parancsértelmező elérése a helyi gépen" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez a helyi gépen." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Pszeudoterminál elérése helyi konténerben" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez helyi konténerben." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Pszeudoterminál elérése helyi gépen" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez a helyi gépen." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Virtuális gépek és konténerek kezelése" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "Hitelesítés szükséges helyi virtuális gépek és konténerek kezeléséhez." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Helyi virtuális gép és konténer lemezképek kezelése" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." -@@ -526,27 +706,258 @@ msgstr "" - "Hitelesítés szükséges a helyi virtuális gép és konténer lemezképek " - "kezeléséhez." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Hitelesítés szükséges a rendszeridő beállításához." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "Hitelesítés szükséges a rendszeridő beállításához." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Hitelesítés szükséges a következő leállításához: „$(unit)”." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Hitelesítés szükséges a helyi gépnév beállításához." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Hitelesítés szükséges a rendszer hibernálásához." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Hitelesítés szükséges a bejelentkezéshez a helyi gépre." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Hitelesítés szükséges a helyi gépnév beállításához." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Hitelesítés szükséges a rendszer hibernálásához." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Hitelesítés szükséges a rendszer területi beállításainak megadásához." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Hitelesítés szükséges a rendszeridő beállításához." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Hitelesítés szükséges a rendszeridő beállításához." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Hitelesítés szükséges a falüzenet beállításához" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Hitelesítés szükséges a falüzenet beállításához" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Hitelesítés szükséges a rendszer újraindításához." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép importálásához." -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "" -+"Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy " -+"munkaállomáshoz" -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép letöltéséhez." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "Hitelesítés szükséges a falüzenet beállításához" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "Hitelesítés szükséges a falüzenet beállításához" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Hitelesítés szükséges a rendszer billentyűzetbeállításainak megadásához." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Rendszeridő beállítása" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "Hitelesítés szükséges a rendszeridő beállításához." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Rendszer időzónájának beállítása" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "Hitelesítés szükséges a rendszer időzónájának beállításához." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "Az RTC beállítása helyi időzónára vagy UTC-re" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -554,44 +965,72 @@ msgstr "" - "Hitelesítés szükséges az RTC beállításához a helyi időzóna vagy UTC " - "tárolására." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Hálózati időszinkronizáció be- vagy kikapcsolása" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." - msgstr "Hitelesítés szükséges a hálózati időszinkronizáció engedélyezéséhez." - --#: ../src/core/dbus-unit.c:450 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Hitelesítés szükséges a következő elindításához: „$(unit)”." - --#: ../src/core/dbus-unit.c:451 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Hitelesítés szükséges a következő leállításához: „$(unit)”." - --#: ../src/core/dbus-unit.c:452 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Hitelesítés szükséges a következő újratöltéséhez: „$(unit)”." - --#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Hitelesítés szükséges a következő újraindításához: „$(unit)”." - --#: ../src/core/dbus-unit.c:560 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Hitelesítés szükséges a következő kilövéséhez: „$(unit)”." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "" -+"Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”." - --#: ../src/core/dbus-unit.c:590 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: " - "„$(unit)”." - --#: ../src/core/dbus-unit.c:622 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "" - "Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”." - -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: " -+"„$(unit)”." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: " -+"„$(unit)”." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Hitelesítés szükséges a következő kilövéséhez: „$(unit)”." -diff --git a/po/id.po b/po/id.po -index efc2ad7..06268b3 100644 ---- a/po/id.po -+++ b/po/id.po -@@ -6,8 +6,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2018-03-04 11:09+0700\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2018-03-04 11:12+0700\n" - "Last-Translator: Andika Triwidada \n" - "Language-Team: Indonesian \n" -@@ -45,11 +45,11 @@ msgstr "Kelola layanan sistem atau berkas unit" - msgid "Authentication is required to manage system service or unit files." - msgstr "Otentikasi diperlukan untuk mengelola layanan sistem atau berkas unit." - --#: src/core/org.freedesktop.systemd1.policy.in:53 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "Atur atau hapus variabel lingkungan manajer layanan dan sistem" - --#: src/core/org.freedesktop.systemd1.policy.in:54 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -57,27 +57,91 @@ msgstr "" - "Otentikasi diperlukan untuk menata atau menghapus variabel lingkungan " - "manajer layanan dan sistem." - --#: src/core/org.freedesktop.systemd1.policy.in:63 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Muat ulang keadaan systemd" - --#: src/core/org.freedesktop.systemd1.policy.in:64 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "Otentikasi diperlukan untuk memuat ulang keadaan systemd." - --#: src/hostname/org.freedesktop.hostname1.policy:22 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Otentikasi diperlukan untuk memuat ulang keadaan systemd." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Otentikasi diperlukan untuk memuat ulang keadaan systemd." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "Otentikasi diperlukan untuk mengelola seat, pengguna, dan sesi aktif." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "Otentikasi diperlukan untuk mencantol suatu perangkat ke sebuah seat." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Otentikasi diperlukan untuk menyetel pesan wall" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "Otentikasi diperlukan untuk mengelola seat, pengguna, dan sesi aktif." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Setel nama host" - --#: src/hostname/org.freedesktop.hostname1.policy:23 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Otentikasi diperlukan untuk menata nama host lokal." - --#: src/hostname/org.freedesktop.hostname1.policy:32 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Setel nama host statik" - --#: src/hostname/org.freedesktop.hostname1.policy:33 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -85,14 +149,24 @@ msgstr "" - "Otentikasi diperlukan untuk menata nama host lokal yang dikonfigurasi " - "statik, maupun nama host cantik." - --#: src/hostname/org.freedesktop.hostname1.policy:43 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Setel informasi mesin" - --#: src/hostname/org.freedesktop.hostname1.policy:44 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "Otentikasi diperlukan untuk menata informasi mesin lokal." - -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Otentikasi diperlukan untuk memuat ulang '$(unit)'." -+ - #: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Impor sebuah image kontainer atau VM" -@@ -260,8 +334,7 @@ msgid "Flush device to seat attachments" - msgstr "Siram perangkat untuk mendudukkan lampiran" - - #: src/login/org.freedesktop.login1.policy:149 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Otentikasi diperlukan untuk me-reset bagaimana perangkat dicantolkan ke seat." - -@@ -291,8 +364,8 @@ msgstr "Matikan daya sistem ketika sebuah aplikasi meminta untuk mencegahnya" - - #: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Otentikasi diperlukan untuk mematikan daya sistem ketika sebuah aplikasi " - "meminta untuk mencegahnya." -@@ -311,8 +384,8 @@ msgstr "Boot ulang sistem ketika pengguna lain sedang log masuk" - - #: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Otentikasi diperlukan untuk mem-boot ulang sistem ketika pengguna lain " - "sedang log masuk." -@@ -323,8 +396,8 @@ msgstr "Boot ulang sistem ketika sebuah aplikasi meminta untuk mencegahnya" - - #: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Otentikasi diperlukan untuk mem-boot ulang sistem ketika sebuah aplikasi " - "meminta untuk mencegahnya." -@@ -343,8 +416,8 @@ msgstr "Halt sistem ketika pengguna lain sedang log masuk" - - #: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "" - "Otentikasi diperlukan untuk meng-halt sistem ketika pengguna lain sedang log " - "masuk." -@@ -354,12 +427,16 @@ msgid "Halt the system while an application is inhibiting this" - msgstr "Halt sistem ketika sebuah aplikasi meminta untuk mencegahnya" - - #: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." -+"Authentication is required to halt the system while an application is " -+"inhibiting this." - msgstr "" --"Otentikasi diperlukan untuk meng-halt sistem ketika sebuah aplikasi meminta " --"untuk mencegahnya." -+"Otentikasi diperlukan untuk menghibernasi sistem ketika sebuah aplikasi " -+"meminta mencegahnya." - - #: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" -@@ -387,8 +464,8 @@ msgstr "Suspensikan sistem ketika sebuah aplikasi meminta untuk mencegahnya" - - #: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Otentikasi diperlukan untuk mensuspensi sistem ketika suatu aplikasi meminta " - "untuk mencegahnya." -@@ -419,8 +496,8 @@ msgstr "Hibernasikan sistem ketika sebuah aplikasi meminta untuk mencegahnya." - - #: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Otentikasi diperlukan untuk menghibernasi sistem ketika sebuah aplikasi " - "meminta mencegahnya." -@@ -430,8 +507,7 @@ msgid "Manage active sessions, users and seats" - msgstr "Kelola seat, pengguna, dan sesi aktif" - - #: src/login/org.freedesktop.login1.policy:322 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "Otentikasi diperlukan untuk mengelola seat, pengguna, dan sesi aktif." - - #: src/login/org.freedesktop.login1.policy:331 -@@ -443,10 +519,22 @@ msgid "Authentication is required to lock or unlock active sessions." - msgstr "Otentikasi diperlukan untuk mengunci atau membuka kunci sesi aktif." - - #: src/login/org.freedesktop.login1.policy:341 --msgid "Allow indication to the firmware to boot to setup interface" --msgstr "Ijinkan indikasi ke firmware untuk boot ke antar muka penyiapan" -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" - - #: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Otentikasi diperlukan untuk menyetel zona waktu sistem." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" -+msgstr "Ijinkan indikasi ke firmware untuk boot ke antar muka penyiapan" -+ -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -454,14 +542,56 @@ msgstr "" - "Otentikasi diperlukan untuk mengindikasikan ke firmware agar boot ke " - "antarmuka penyiapan." - --#: src/login/org.freedesktop.login1.policy:351 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Otentikasi diperlukan untuk mengindikasikan ke firmware agar boot ke " -+"antarmuka penyiapan." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Otentikasi diperlukan untuk mengindikasikan ke firmware agar boot ke " -+"antarmuka penyiapan." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Setel suatu pesan wall" - --#: src/login/org.freedesktop.login1.policy:352 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Otentikasi diperlukan untuk menyetel pesan wall" - -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to halt the system." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Otentikasi diperlukan untuk meng-halt sistem." -+ - #: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Log masuk ke dalam suatu kontainer lokal" -@@ -538,6 +668,206 @@ msgstr "" - "Otentikasi diperlukan untuk mengelola mesin virtual lokal dan image " - "kontainer." - -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Otentikasi diperlukan untuk menyetel waktu sistem." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+#, fuzzy -+#| msgid "Register a DNS-SD service" -+msgid "Set DNS servers" -+msgstr "Daftarkan suatu layanan DNS-SD" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to set DNS servers." -+msgstr "Otentikasi diperlukan untuk mendaftarkan suatu layanan DNS-SD" -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Otentikasi diperlukan untuk menghentikan '$(unit)'." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Otentikasi diperlukan untuk menata nama host lokal." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Otentikasi diperlukan untuk menghibernasi sistem." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Otentikasi diperlukan untuk log masuk ke dalam host lokal." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Otentikasi diperlukan untuk mendaftarkan suatu layanan DNS-SD" -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Otentikasi diperlukan untuk menghibernasi sistem." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Otentikasi diperlukan untuk menyetel locale sistem." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Otentikasi diperlukan untuk menyetel waktu sistem." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Otentikasi diperlukan untuk menyetel waktu sistem." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Otentikasi diperlukan untuk menyetel pesan wall" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Otentikasi diperlukan untuk menyetel pesan wall" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Otentikasi diperlukan untuk memuat ulang keadaan systemd." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Otentikasi diperlukan untuk mem-boot ulang sistem." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "Otentikasi diperlukan untuk mengimpor suatu image kontainer atau VM" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "Otentikasi diperlukan untuk mencantol suatu perangkat ke sebuah seat." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "Otentikasi diperlukan untuk mengunduh suatu image kontainer atau VM" -+ - #: src/resolve/org.freedesktop.resolve1.policy:22 - msgid "Register a DNS-SD service" - msgstr "Daftarkan suatu layanan DNS-SD" -@@ -554,6 +884,16 @@ msgstr "Cabut pendaftaran suatu layanan DNS-SD" - msgid "Authentication is required to unregister a DNS-SD service" - msgstr "Otentikasi diperlukan untuk mencabut pendaftaran suatu layanan DNS-SD" - -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "Otentikasi diperlukan untuk menyetel pengaturan papan tik sistem." -+ - #: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Setel waktu sistem" -@@ -582,11 +922,11 @@ msgstr "" - "Otentikasi diperlukan untuk mengendalikan apakah RTC menyimpan waktu UTC " - "atau lokal." - --#: src/timedate/org.freedesktop.timedate1.policy:54 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Nyalakan atau matikan penyelarasan waktu jaringan" - --#: src/timedate/org.freedesktop.timedate1.policy:55 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -594,31 +934,64 @@ msgstr "" - "Otentikasi diperlukan untuk mengendalikan apakah sinkronisasi waktu jaringan " - "mesti difungsikan." - --#: src/core/dbus-unit.c:496 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Otentikasi diperlukan untuk memulai '$(unit)'." - --#: src/core/dbus-unit.c:497 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Otentikasi diperlukan untuk menghentikan '$(unit)'." - --#: src/core/dbus-unit.c:498 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Otentikasi diperlukan untuk memuat ulang '$(unit)'." - --#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Otentikasi diperlukan untuk memulai ulang '$(unit)'." - --#: src/core/dbus-unit.c:607 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Otentikasi diperlukan untuk mematikan '$(unit)'." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "Otentikasi diperlukan untuk menata properti pada '$(unit)'." - --#: src/core/dbus-unit.c:638 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Otentikasi diperlukan untuk me-reset keadaan \"failed\" dari '$(unit)'." - --#: src/core/dbus-unit.c:671 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Otentikasi diperlukan untuk menata properti pada '$(unit)'." -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"Otentikasi diperlukan untuk me-reset keadaan \"failed\" dari '$(unit)'." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Otentikasi diperlukan untuk me-reset keadaan \"failed\" dari '$(unit)'." -+ -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "" -+#~ "Otentikasi diperlukan untuk meng-halt sistem ketika sebuah aplikasi " -+#~ "meminta untuk mencegahnya." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Otentikasi diperlukan untuk mematikan '$(unit)'." -diff --git a/po/it.po b/po/it.po -index a2f45bd..7bee017 100644 ---- a/po/it.po -+++ b/po/it.po -@@ -8,7 +8,7 @@ msgid "" - msgstr "" - "Project-Id-Version: systemd\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2020-02-27 17:10+0100\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2020-02-27 17:22+0100\n" - "Last-Translator: Daniele Medri \n" - "Language-Team: Italian\n" -@@ -75,7 +75,9 @@ msgid "Create a home area" - msgstr "Crea un'area home" - - #: src/home/org.freedesktop.home1.policy:14 --msgid "Authentication is required to creat a user's home area." -+#, fuzzy -+#| msgid "Authentication is required to creat a user's home area." -+msgid "Authentication is required to create a user's home area." - msgstr "Autenticazione richiesta per creare un'area home per l'utente." - - #: src/home/org.freedesktop.home1.policy:23 -@@ -83,7 +85,9 @@ msgid "Remove a home area" - msgstr "Rimuovi un'area home" - - #: src/home/org.freedesktop.home1.policy:24 --msgid "Authentication is required to remov a user's home area." -+#, fuzzy -+#| msgid "Authentication is required to remov a user's home area." -+msgid "Authentication is required to remove a user's home area." - msgstr "Autenticazione richiesta per rimuovere un'area home per l'utente." - - #: src/home/org.freedesktop.home1.policy:33 -@@ -102,7 +106,9 @@ msgid "Update a home area" - msgstr "Aggiorna un'area home" - - #: src/home/org.freedesktop.home1.policy:44 --msgid "Authentication is required to updat a user's home area." -+#, fuzzy -+#| msgid "Authentication is required to updat a user's home area." -+msgid "Authentication is required to update a user's home area." - msgstr "Autenticazione richiesta per aggiornare un'area home per l'utente." - - #: src/home/org.freedesktop.home1.policy:53 -@@ -110,7 +116,9 @@ msgid "Resize a home area" - msgstr "Ridimensiona un'area home" - - #: src/home/org.freedesktop.home1.policy:54 --msgid "Authentication is required to resiz a user's home area." -+#, fuzzy -+#| msgid "Authentication is required to resiz a user's home area." -+msgid "Authentication is required to resize a user's home area." - msgstr "Autenticazione richiesta per ridimensionare l'area home dell'utente." - - #: src/home/org.freedesktop.home1.policy:63 -@@ -118,7 +126,11 @@ msgid "Change password of a home area" - msgstr "Cambia password di un'area home" - - #: src/home/org.freedesktop.home1.policy:64 --msgid "Authentication is required to chang the password of a user's home area." -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to chang the password of a user's home area." -+msgid "" -+"Authentication is required to change the password of a user's home area." - msgstr "" - "Autenticazione richiesta per cambiare le password per l'area home " - "dell'utente." -@@ -771,26 +783,36 @@ msgid "Authentication is required to reset DNS settings." - msgstr "Autenticazione richiesta per ripristinare le configurazioni DNS." - - #: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti" -+ -+#: src/network/org.freedesktop.network1.policy:154 - msgid "Renew dynamic addresses" - msgstr "Rinnova indirizzi dinamici" - --#: src/network/org.freedesktop.network1.policy:144 -+#: src/network/org.freedesktop.network1.policy:155 - msgid "Authentication is required to renew dynamic addresses." - msgstr "Autenticazione richiesta per rinnovare gli indirizzi dinamici." - --#: src/network/org.freedesktop.network1.policy:154 -+#: src/network/org.freedesktop.network1.policy:165 - msgid "Reload network settings" - msgstr "Ricarica configurazioni di rete" - --#: src/network/org.freedesktop.network1.policy:155 -+#: src/network/org.freedesktop.network1.policy:166 - msgid "Authentication is required to reload network settings." - msgstr "Autenticazione richiesta per ricaricare le configurazioni di rete." - --#: src/network/org.freedesktop.network1.policy:165 -+#: src/network/org.freedesktop.network1.policy:176 - msgid "Reconfigure network interface" - msgstr "Riconfigura interfaccia di rete" - --#: src/network/org.freedesktop.network1.policy:166 -+#: src/network/org.freedesktop.network1.policy:177 - msgid "Authentication is required to reconfigure network interface." - msgstr "Autenticazione richiesta per riconfigurare l'interfaccia di rete." - -@@ -894,23 +916,23 @@ msgstr "" - "Autenticazione richiesta per verificare se la sincronizzazione dell'orario " - "in rete deve essere attivata." - --#: src/core/dbus-unit.c:356 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Autenticazione richiesta per avviare '$(unit)'." - --#: src/core/dbus-unit.c:357 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Autenticazione richiesta per fermare '$(unit)'." - --#: src/core/dbus-unit.c:358 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Autenticazione richiesta per ricaricare '$(unit)'." - --#: src/core/dbus-unit.c:359 src/core/dbus-unit.c:360 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Autenticazione richiesta per riavviare '$(unit)'." - --#: src/core/dbus-unit.c:532 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." -@@ -918,19 +940,30 @@ msgstr "" - "Autenticazione richiesta per inviare un segnale UNIX ai processi di " - "'$(unit)'." - --#: src/core/dbus-unit.c:563 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Autenticazione richiesta per riconfigurare lo stato \"fallito\" di '$(unit)'." - --#: src/core/dbus-unit.c:596 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Autenticazione richiesta per configurare le proprietà di '$(unit)'." - --#: src/core/dbus-unit.c:705 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." - msgstr "" - "Autenticazione richiesta per eliminare i file e le directory associate a " - "'$(unit)'." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to send a UNIX signal to the processes of " -+#| "'$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Autenticazione richiesta per inviare un segnale UNIX ai processi di " -+"'$(unit)'." -diff --git a/po/ja.po b/po/ja.po -index 7662bec..be5157a 100644 ---- a/po/ja.po -+++ b/po/ja.po -@@ -6,7 +6,7 @@ msgid "" - msgstr "" - "Project-Id-Version: systemd\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2020-02-02 23:20+0900\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2018-10-27 07:41+0900\n" - "Last-Translator: Yu Watanabe \n" - "Language-Team: \n" -@@ -106,7 +106,8 @@ msgid "Change password of a home area" - msgstr "ホーム領域のパスワード変更" - - #: src/home/org.freedesktop.home1.policy:64 --msgid "Authentication is required to change the password of a user's home area." -+msgid "" -+"Authentication is required to change the password of a user's home area." - msgstr "ユーザのホーム領域のパスワードを変更するには認証が必要です。" - - #: src/hostname/org.freedesktop.hostname1.policy:20 -@@ -302,8 +303,7 @@ msgid "Flush device to seat attachments" - msgstr "デバイスのシートへの接続のリセット" - - #: src/login/org.freedesktop.login1.policy:149 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "デバイスのシートへの接続をリセットするには認証が必要です。" - - #: src/login/org.freedesktop.login1.policy:158 -@@ -331,8 +331,8 @@ msgstr "アプリケーションが使用されている状態でシステムの - - #: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "アプリケーションが使用されている状態でシステムの電源を切るには認証が必要で" - "す。" -@@ -351,8 +351,8 @@ msgstr "他のユーザがログインしている状態でシステムを再起 - - #: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "他のユーザがログインしている状態でシステムを再起動するには認証が必要です。" - -@@ -362,8 +362,8 @@ msgstr "アプリケーションが使用されている状態でシステムを - - #: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "アプリケーションが使用されている状態でシステムを再起動するには認証が必要で" - "す。" -@@ -382,8 +382,8 @@ msgstr "他のユーザがログインしている状態でシステムを停止 - - #: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "" - "他のユーザがログインしている状態でシステムを停止するには認証が必要です。" - -@@ -392,11 +392,16 @@ msgid "Halt the system while an application is inhibiting this" - msgstr "アプリケーションが使用されている状態でシステムを停止する" - - #: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." -+"Authentication is required to halt the system while an application is " -+"inhibiting this." - msgstr "" --"アプリケーションが使用されている状態でシステムを停止するには認証が必要です。" -+"アプリケーションが使用されている状態でシステムをハイバネートするには認証が必" -+"要です。" - - #: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" -@@ -424,8 +429,8 @@ msgstr "アプリケーションが使用されている状態でシステムを - - #: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "アプリケーションが使用されている状態でシステムをサスペンドするには認証が必要" - "です。" -@@ -456,8 +461,8 @@ msgstr "アプリケーションが使用されている状態でシステムを - - #: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "アプリケーションが使用されている状態でシステムをハイバネートするには認証が必" - "要です。" -@@ -467,8 +472,7 @@ msgid "Manage active sessions, users and seats" - msgstr "アクティブなセッションやユーザ,シートの管理" - - #: src/login/org.freedesktop.login1.policy:322 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "アクティブなセッションやユーザ,シートを管理するには認証が必要です。" - - #: src/login/org.freedesktop.login1.policy:331 -@@ -711,26 +715,36 @@ msgid "Authentication is required to reset DNS settings." - msgstr "DNSの設定を破棄するには認証が必要です。" - - #: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "全ユーザへのメッセージを設定するには認証が必要です。" -+ -+#: src/network/org.freedesktop.network1.policy:154 - msgid "Renew dynamic addresses" - msgstr "動的アドレスの更新" - --#: src/network/org.freedesktop.network1.policy:144 -+#: src/network/org.freedesktop.network1.policy:155 - msgid "Authentication is required to renew dynamic addresses." - msgstr "動的アドレスの更新には認証が必要です。" - --#: src/network/org.freedesktop.network1.policy:154 -+#: src/network/org.freedesktop.network1.policy:165 - msgid "Reload network settings" - msgstr "ネットワークの設定の再読み込み" - --#: src/network/org.freedesktop.network1.policy:155 -+#: src/network/org.freedesktop.network1.policy:166 - msgid "Authentication is required to reload network settings." - msgstr "ネットワークの設定を再読み込みするには認証が必要です。" - --#: src/network/org.freedesktop.network1.policy:165 -+#: src/network/org.freedesktop.network1.policy:176 - msgid "Reconfigure network interface" - msgstr "ネットワークインターフェイスの再設定" - --#: src/network/org.freedesktop.network1.policy:166 -+#: src/network/org.freedesktop.network1.policy:177 - msgid "Authentication is required to reconfigure network interface." - msgstr "ネットワークインターフェイスの再設定には認証が必要です。" - -@@ -822,39 +836,55 @@ msgid "" - "shall be enabled." - msgstr "ネットワーク経由の時刻同期を有効もしくは無効にするには認証が必要です。" - --#: src/core/dbus-unit.c:355 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "'$(unit)'を開始するには認証が必要です。" - --#: src/core/dbus-unit.c:356 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "'$(unit)'を停止するには認証が必要です。" - --#: src/core/dbus-unit.c:357 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "'$(unit)'を再読込するには認証が必要です。" - --#: src/core/dbus-unit.c:358 src/core/dbus-unit.c:359 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "'$(unit)'を再起動するには認証が必要です。" - --#: src/core/dbus-unit.c:531 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." - msgstr "'$(unit)'のプロセスにUNIXシグナルを送るには認証が必要です。" - --#: src/core/dbus-unit.c:562 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "'$(unit)'の「失敗」状態をリセットするには認証が必要です。" - --#: src/core/dbus-unit.c:595 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "'$(unit)'のプロパティを設定するには認証が必要です。" - --#: src/core/dbus-unit.c:704 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." - msgstr "" - "'$(unit)'に関連付けられたファイルやディレクトリの削除には認証が必要です。" -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to send a UNIX signal to the processes of " -+#| "'$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "'$(unit)'のプロセスにUNIXシグナルを送るには認証が必要です。" -+ -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "" -+#~ "アプリケーションが使用されている状態でシステムを停止するには認証が必要で" -+#~ "す。" -diff --git a/po/ko.po b/po/ko.po -index 301a322..c4c4bd9 100644 ---- a/po/ko.po -+++ b/po/ko.po -@@ -7,49 +7,49 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2015-09-25 22:52+0900\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2015-11-03 13:19+0100\n" - "Last-Translator: Dongsu Park \n" - "Language-Team: GNOME Korea \n" -+"Language: ko\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" - "X-Generator: Gtranslator 2.91.7\n" - "Plural-Forms: nplurals=1; plural=0;\n" --"Language: ko\n" - "X-Poedit-SourceCharset: UTF-8\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "시스템에 암호문 보내기" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "시스템에 입력한 암호를 보내려면 인증이 필요합니다." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "시스템 서비스 또는 기타 유닛 관리" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "시스템 서비스 또는 기타 유닛을 관리하려면 인증이 필요합니다." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "시스템 서비스 또는 유닛 파일 관리" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "시스템 서비스 또는 유닛 파일을 관리하려면 인증이 필요합니다." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "시스템 및 서비스 관리자 환경 변수 설정 또는 설정 해제" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -57,27 +57,91 @@ msgstr "" - "시스템 및 서비스 관리자 환경 변수를 설정하거나 설정 해제하려면 인증이 필요합" - "니다." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "systemd 상태 다시 불러오기" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "systemd 상태를 다시 불러오려면 인증이 필요합니다." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "systemd 상태를 다시 불러오려면 인증이 필요합니다." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "systemd 상태를 다시 불러오려면 인증이 필요합니다." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "활성 세션, 사용자 시트를 관리하려면 인증이 필요합니다." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "시트에 장치 부착을 허용하려면 인증이 필요합니다." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "wall 메시지를 설정하려면 인증이 필요합니다" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "활성 세션, 사용자 시트를 관리하려면 인증이 필요합니다." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "호스트 이름 설정" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "로컬 호스트 이름을 설정하려면 인증이 필요합니다." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "정적 호스트 이름 설정" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -85,94 +149,104 @@ msgstr "" - "로컬 호스트 이름을 모양새를 갖춘 호스트 이름 처럼 정적으로 설정하려면 인증" - "이 필요합니다." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "머신 정보 설정" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "로컬 머신 정보를 설정하려면 인증이 필요합니다." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "'$(unit)' 서비스 유닛을 다시 불러오려면 인증이 필요합니다." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "VM 또는 컨테이너의 이미지 가져오기" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "VM 또는 컨테이너의 이미지를 가져오려면 인증이 필요합니다" - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "가상 머신 또는 컨테이너의 이미지 내보내기" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "가상 머신 또는 컨테이너의 이미지를 내보내려면 인증이 필요합니다" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "가상머신 또는 컨테이너 이미지 다운로드" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "가상머신 또는 컨테이너 이미지를 다운로드하려면 인증이 필요합니다" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "시스템 로캘 설정" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "시스템 로캘을 설정하려면 인증이 필요합니다." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "시스템 키보드 설정" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "시스템 키보드를 설정하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "프로그램의 시스템 전원 끄기 방지 요청 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "프로그램의 시스템 전원 끄기 방지 요청을 허용하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "프로그램의 시스템 전원 끄기 지연 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "프로그램의 시스템 전원 끄기 지연 동작을 허용하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "프로그램의 시스템 대기 상태 진입 방지 요청 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "프로그램의 시스템 대기 상태 진입 방지 요청을 허용하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "프로그램의 시스템 대기 상태 진입 지연 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "프로그램의 시스템 대기 상태 진입 지연 동작을 허용하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "프로그램의 시스템 자동 절전 상태 진입 방지 요청 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -180,44 +254,44 @@ msgstr "" - "프로그램의 시스템 자동 절전 상태 진입 방지 요청을 허용하려면 인증이 필요합니" - "다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "프로그램의 시스템 전원 키 처리 방지 요청 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." - msgstr "" - "프로그램의 시스템 전원 키 처리 방지 요청을 허용하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "프로그램의 시스템 절전 키 처리 방지 요청 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." - msgstr "" - "프로그램의 시스템 절전 키 처리 방지 요청을 허용하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "프로그램의 시스템 최대 절전 키 처리 방지 요청 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." - msgstr "" - "프로그램의 시스템 최대 절전 키 처리 방지 요청을 허용하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "프로그램의 시스템 랩톱 덮개 스위치 처리 방지 요청 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -225,136 +299,196 @@ msgstr "" - "프로그램의 시스템 랩톱 덮개 스위치 처리 방지 요청을 허용하려면 인증이 필요합" - "니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 -+#, fuzzy -+#| msgid "Allow non-logged-in users to run programs" -+msgid "Allow non-logged-in user to run programs" -+msgstr "비 로그인 사용자 프로그램 실행 허용" -+ -+#: src/login/org.freedesktop.login1.policy:118 -+#, fuzzy -+#| msgid "Authentication is required to run programs as a non-logged-in user." -+msgid "Explicit request is required to run programs as a non-logged-in user." -+msgstr "비 로그인 사용자에게 프로그램 실행을 허용하려면 인증이 필요합니다." -+ -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "비 로그인 사용자 프로그램 실행 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "비 로그인 사용자에게 프로그램 실행을 허용하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "시트에 장치 부착 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "시트에 장치 부착을 허용하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "시트로부터 장치 해제 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "시트에 붙인 장치 상태를 초기화하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "시스템 끄기" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "시스템을 끄려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "다른 사용자가 로그인 했을 때 시스템 끄기" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." - msgstr "다른 사용자가 로그인 했을 때 시스템 전원을 끄려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "프로그램이 시스템을 끄지 못하게 요청할 때 시스템 전원 끄기" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "프로그램이 시스템을 끄지 못하게 요청할 때 시스템 전원을 끄려면 인증이 필요합" - "니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "시스템 다시 시작" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "시스템을 다시 시작하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "다른 사용자가 로그인 했을 때 시스템 다시 시작" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "다른 사용자가 로그인 했을 때 시스템을 다시 시작하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "프로그램이 시스템을 다시 시작하지 못하게 요청할 때 시스템 다시 시작" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "프로그램이 시스템을 다시 시작하지 못하게 요청할 때 시스템을 다시 시작하려면 " - "인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "시스템 최대 절전 상태 진입" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "시스템을 최대 절전 상태로 놓으려면 인증이 필요합니다." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "다른 사용자가 로그인 했을 때 시스템 최대 절전 상태 진입" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"다른 사용자가 로그인 했을 때 시스템을 최대 절전 상태로 놓으려면 인증이 필요합" -+"니다." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "" -+"프로그램이 최대 절전 상태 진입을 못하게 요청할 때 시스템 최대 절전 상태 진입" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"프로그램이 최대 절전 상태 진입을 못하게 요청할 때 시스템을 최대 절전 상태로 " -+"놓으려면 인증이 필요합니다." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "시스템 절전 상태 진입" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "시스템을 절전 상태로 놓으려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "다른 사용자가 로그인 했을 때 시스템 절전 상태 진입" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." - msgstr "" - "다른 사용자가 로그인 했을 때 시스템을 절전 상태로 놓으려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "프로그램이 절전 상태 진입을 못하게 요청할 때 시스템 절전 상태 진입" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "프로그램이 절전 상태 진입을 못하게 요청할 때 시스템을 절전 상태로 놓으려면 인" - "증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "시스템 최대 절전 상태 진입" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "시스템을 최대 절전 상태로 놓으려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "다른 사용자가 로그인 했을 때 시스템 최대 절전 상태 진입" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -362,143 +496,420 @@ msgstr "" - "다른 사용자가 로그인 했을 때 시스템을 최대 절전 상태로 놓으려면 인증이 필요합" - "니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "" - "프로그램이 최대 절전 상태 진입을 못하게 요청할 때 시스템 최대 절전 상태 진입" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "프로그램이 최대 절전 상태 진입을 못하게 요청할 때 시스템을 최대 절전 상태로 " - "놓으려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "활성 세션, 사용자, 시트 관리" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "활성 세션, 사용자 시트를 관리하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "활성 세션 잠금 또는 잠금 해제" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "활성화 세션을 잠금 또는 잠금 해제하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "시스템 시간대를 설정하려면 인증이 필요합니다." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "설정 화면으로 부팅하도록 펌웨어에게 지시 허용" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." - msgstr "설정 화면으로 부팅하도록 펌웨어에게 지시하려면 인증이 필요합니다." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "설정 화면으로 부팅하도록 펌웨어에게 지시하려면 인증이 필요합니다." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "설정 화면으로 부팅하도록 펌웨어에게 지시하려면 인증이 필요합니다." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "wall 메시지 설정" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "wall 메시지를 설정하려면 인증이 필요합니다" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "로컬 호스트 이름을 설정하려면 인증이 필요합니다." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "로컬 컨테이너 로그인" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "로컬 컨테이너로 로그인하려면 인증이 필요합니다." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "로컬 호스트 로그인" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "로컬 호스트로 로그인하려면 인증이 필요합니다." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "로컬 컨테이너의 쉘 획득" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "로컬 컨테이너에서 쉘을 획득하려면 인증이 필요합니다." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "로컬 호스트 쉘 획득" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "로컬 호스트의 쉘을 획득하려면 인증이 필요합니다." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "로컬 컨테이너에서 의사 TTY 획득" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "로컬 컨테이너에서 의사 TTY를 획득하려면 인증이 필요합니다." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "로컬 호스트에서 유사 TTY 획득" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "로컬 호스트에서 의사 TTY를 획득하려면 인증이 필요합니다." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "로컬 가상 머신 및 컨테이너 관리" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "로컬 가상 머신 및 컨테이너를 관리하려면 인증이 필요합니다." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "로컬 가상 머신 및 컨테이너 이미지 관리" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." - msgstr "로컬 가상 머신 및 컨테이너 이미지를 관리하려면 인증이 필요합니다." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "시스템 시간을 설정하려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "시스템 시간을 설정하려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "'$(unit)' 서비스 유닛을 멈추려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "로컬 호스트 이름을 설정하려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "시스템을 최대 절전 상태로 놓으려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "로컬 호스트로 로그인하려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "로컬 호스트 이름을 설정하려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "시스템을 최대 절전 상태로 놓으려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "시스템 로캘을 설정하려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "시스템 시간을 설정하려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "시스템 시간을 설정하려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "wall 메시지를 설정하려면 인증이 필요합니다" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "wall 메시지를 설정하려면 인증이 필요합니다" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "systemd 상태를 다시 불러오려면 인증이 필요합니다." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "시스템을 다시 시작하려면 인증이 필요합니다." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "VM 또는 컨테이너의 이미지를 가져오려면 인증이 필요합니다" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "시트에 장치 부착을 허용하려면 인증이 필요합니다." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "가상머신 또는 컨테이너 이미지를 다운로드하려면 인증이 필요합니다" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "wall 메시지를 설정하려면 인증이 필요합니다" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "wall 메시지를 설정하려면 인증이 필요합니다" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "시스템 키보드를 설정하려면 인증이 필요합니다." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "시스템 시간 설정" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "시스템 시간을 설정하려면 인증이 필요합니다." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "시스템 시간대 설정" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "시스템 시간대를 설정하려면 인증이 필요합니다." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "RTC를 로컬 시간대 또는 UTC로 설정" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -506,40 +917,64 @@ msgstr "" - "RTC를 로컬 시간 또는 UTC 시간으로 저장할 지 여부를 제어하려면 인증이 필요합니" - "다." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "네트워크 시간 동기화 켜거나 끄기" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." - msgstr "네트워크 시간 동기화의 활성화 여부를 제어하려면 인증이 필요합니다." - --#: ../src/core/dbus-unit.c:428 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "'$(unit)' 서비스 유닛을 시작하려면 인증이 필요합니다." - --#: ../src/core/dbus-unit.c:429 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "'$(unit)' 서비스 유닛을 멈추려면 인증이 필요합니다." - --#: ../src/core/dbus-unit.c:430 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "'$(unit)' 서비스 유닛을 다시 불러오려면 인증이 필요합니다." - --#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "'$(unit)' 서비스 유닛을 다시 시작하려면 인증이 필요합니다." - --#: ../src/core/dbus-unit.c:535 --msgid "Authentication is required to kill '$(unit)'." --msgstr "'$(unit)' 서비스 유닛을 강제로 끝내려면 인증이 필요합니다." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "'$(unit)' 서비스 유닛 속성을 설정하려면 인증이 필요합니다." - --#: ../src/core/dbus-unit.c:565 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "'$(unit)' 서비스 유닛의 \"실패\" 상태를 되돌리려면 인증이 필요합니다." - --#: ../src/core/dbus-unit.c:597 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "'$(unit)' 서비스 유닛 속성을 설정하려면 인증이 필요합니다." -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "'$(unit)' 서비스 유닛의 \"실패\" 상태를 되돌리려면 인증이 필요합니다." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "'$(unit)' 서비스 유닛의 \"실패\" 상태를 되돌리려면 인증이 필요합니다." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "'$(unit)' 서비스 유닛을 강제로 끝내려면 인증이 필요합니다." -diff --git a/po/lt.po b/po/lt.po -index 2f03fd6..af27e89 100644 ---- a/po/lt.po -+++ b/po/lt.po -@@ -2,8 +2,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2019-04-08 15:29+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2019-04-08 22:01+0300\n" - "Last-Translator: Moo\n" - "Language-Team: Lithuanian\n" -@@ -67,6 +67,75 @@ msgstr "Iš naujo įkelti systemd būseną" - msgid "Authentication is required to reload the systemd state." - msgstr "Norint iš naujo įkelti systemd būseną, reikia patvirtinti tapatybę." - -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Norint iš naujo įkelti systemd būseną, reikia patvirtinti tapatybę." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Norint iš naujo įkelti systemd būseną, reikia patvirtinti tapatybę." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to attach or detach a portable service image." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Norint prijungti ar atskirti perkeliamos tarnybos atvaizdį, reikia nustatyti " -+"tapatybę." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"Norint prijungti įrenginį prie darbo vietos, reikia nustatyti tapatybę." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Norint nustatyti sienos pranešimą, reikia nustatyti tapatybę" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Norint tvarkyti aktyvius seansus, naudotojus ir darbo vietas, reikia " -+"nustatyti tapatybę." -+ - #: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Nustatyti serverio pavadinimą" -@@ -281,8 +350,7 @@ msgid "Flush device to seat attachments" - msgstr "Išvalyti įrenginių prijungimus prie darbo vietų" - - #: src/login/org.freedesktop.login1.policy:149 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Norint atstatyti tai, kaip įrenginiai yra prijungti prie darbo vietų, reikia " - "nustatyti tapatybę." -@@ -313,8 +381,8 @@ msgstr "Išjungti sistemos maitinimą, nors programa paprašė tai sulaikyti" - - #: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Norint išjungti sistemos maitinimą, nepaisant to, kad programa paprašė tai " - "sulaikyti, reikia nustatyti tapatybę." -@@ -333,8 +401,8 @@ msgstr "Paleisti sistemą iš naujo nepaisant kitų prisijungusių naudotojų" - - #: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Norint paleisti sistemą iš naujo nepaisant kitų prisijungusių naudotojų, " - "reikia nustatyti tapatybę." -@@ -345,8 +413,8 @@ msgstr "Paleisti sistemą iš naujo, nors programa paprašė tai sulaikyti" - - #: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Norint paleisti sistemą iš naujo, nepaisant to, kad programa paprašė tai " - "sulaikyti, reikia nustatyti tapatybę." -@@ -365,8 +433,8 @@ msgstr "Stabdyti sistemą nepaisant kitų prisijungusių naudotojų" - - #: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "" - "Norint stabdyti sistemą nepaisant kitų prisijungusių naudotojų, reikia " - "nustatyti tapatybę." -@@ -376,11 +444,15 @@ msgid "Halt the system while an application is inhibiting this" - msgstr "Stabdyti sistemą, nors programa paprašė tai sulaikyti" - - #: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." -+"Authentication is required to halt the system while an application is " -+"inhibiting this." - msgstr "" --"Norint stabdyti sistemą, nepaisant to, kad programa paprašė tai sulaikyti, " -+"Norint užmigdyti sistemą, nepaisant to, kad programa paprašė tai sulaikyti, " - "reikia nustatyti tapatybę." - - #: src/login/org.freedesktop.login1.policy:257 -@@ -409,8 +481,8 @@ msgstr "Pristabdyti sistemą, nors programa paprašė tai sulaikyti" - - #: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Norint pristabdyti sistemą, nepaisant to, kad programa paprašė tai " - "sulaikyti, reikia nustatyti tapatybę." -@@ -441,8 +513,8 @@ msgstr "Užmigdyti sistemą, nors programa paprašė tai sulaikyti" - - #: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Norint užmigdyti sistemą, nepaisant to, kad programa paprašė tai sulaikyti, " - "reikia nustatyti tapatybę." -@@ -452,8 +524,7 @@ msgid "Manage active sessions, users and seats" - msgstr "Tvarkyti aktyvius seansus, naudotojus ir darbo vietas" - - #: src/login/org.freedesktop.login1.policy:322 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Norint tvarkyti aktyvius seansus, naudotojus ir darbo vietas, reikia " - "nustatyti tapatybę." -@@ -521,6 +592,16 @@ msgstr "Nustatyti sienos pranešimą" - msgid "Authentication is required to set a wall message" - msgstr "Norint nustatyti sienos pranešimą, reikia nustatyti tapatybę" - -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to halt the system." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Norint stabdyti sistemą, reikia nustatyti tapatybę." -+ - #: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Prisijungti prie vietinio konteinerio" -@@ -598,6 +679,175 @@ msgstr "" - "Norint tvarkyti vietinę virtualiąją mašiną ir konteinerio atvaizdžius, " - "reikia nustatyti tapatybę." - -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Norint nustatyti sistemos laiką, reikia nustatyti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+#, fuzzy -+#| msgid "Register a DNS-SD service" -+msgid "Set DNS servers" -+msgstr "Registruoti DNS-SD tarnybą" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to set DNS servers." -+msgstr "Norint registruoti DNS-SD tarnybą, reikia nustatyti tapatybę" -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Norint stabdyti \"$(unit)\", reikia nustatyti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "" -+"Norint nustatyti vietinio serverio pavadinimą, reikia nustatyti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Norint užmigdyti sistemą, reikia nustatyti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to get product UUID." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Norint gauti produkto UUID, reikia nustatyti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Norint registruoti DNS-SD tarnybą, reikia nustatyti tapatybę" -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Norint užmigdyti sistemą, reikia nustatyti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Norint nustatyti sistemos lokalę, reikia nustatyti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Norint nustatyti sistemos laiką, reikia nustatyti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Norint nustatyti sistemos laiką, reikia nustatyti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Norint nustatyti sienos pranešimą, reikia nustatyti tapatybę" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Norint nustatyti sienos pranešimą, reikia nustatyti tapatybę" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Norint iš naujo įkelti systemd būseną, reikia patvirtinti tapatybę." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Norint paleisti sistemą iš naujo, reikia nustatyti tapatybę." -+ - #: src/portable/org.freedesktop.portable1.policy:13 - msgid "Inspect a portable service image" - msgstr "Išnagrinėti perkeliamos tarnybos atvaizdį" -@@ -645,6 +895,17 @@ msgstr "Išregistruoti DNS-SD tarnybą" - msgid "Authentication is required to unregister a DNS-SD service" - msgstr "Norint išregistruoti DNS-SD tarnybą, reikia nustatyti tapatybę" - -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Norint nustatyti sistemos klaviatūros nustatymus, reikia nustatyti tapatybę." -+ - #: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Nustatyti sistemos laiką" -@@ -687,38 +948,66 @@ msgstr "" - "Norint valdyti ar tinklo laiko sinchronizavimas turėtų būti įjungtas, reikia " - "nustatyti tapatybę." - --#: src/core/dbus-unit.c:316 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Norint paleisti \"$(unit)\", reikia nustatyti tapatybę." - --#: src/core/dbus-unit.c:317 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Norint stabdyti \"$(unit)\", reikia nustatyti tapatybę." - --#: src/core/dbus-unit.c:318 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Norint įkelti \"$(unit)\" iš naujo, reikia nustatyti tapatybę." - --#: src/core/dbus-unit.c:319 src/core/dbus-unit.c:320 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Norint paleisti \"$(unit)\" iš naujo, reikia nustatyti tapatybę." - --#: src/core/dbus-unit.c:492 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." - msgstr "" - "Norint siųsti UNIX signalą į \"$(unit)\" procesus, reikia nustatyti tapatybę." - --#: src/core/dbus-unit.c:523 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Norint atstatyti \"$(unit)\" įtaiso \"failed\" būseną, reikia nustatyti " - "tapatybę." - --#: src/core/dbus-unit.c:556 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Norint nustatyti \"$(unit)\" savybes, reikia nustatyti tapatybę." - -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"Norint atstatyti \"$(unit)\" įtaiso \"failed\" būseną, reikia nustatyti " -+"tapatybę." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to send a UNIX signal to the processes of " -+#| "'$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Norint siųsti UNIX signalą į \"$(unit)\" procesus, reikia nustatyti tapatybę." -+ -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "" -+#~ "Norint stabdyti sistemą, nepaisant to, kad programa paprašė tai " -+#~ "sulaikyti, reikia nustatyti tapatybę." -+ - #~ msgid "Authentication is required to kill '$(unit)'." - #~ msgstr "Norint nutraukti \"$(unit)\", reikia nustatyti tapatybę." -diff --git a/po/pl.po b/po/pl.po -index e942255..37c8ca7 100644 ---- a/po/pl.po -+++ b/po/pl.po -@@ -5,8 +5,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2020-05-01 15:36+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2020-05-03 13:50+0200\n" - "Last-Translator: Piotr Drąg \n" - "Language-Team: Polish \n" -@@ -905,25 +905,25 @@ msgstr "" - "Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację " - "czasu przez sieć." - --#: src/core/dbus-unit.c:358 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Wymagane jest uwierzytelnienie, aby uruchomić jednostkę „$(unit)”." - --#: src/core/dbus-unit.c:359 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać jednostkę „$(unit)”." - --#: src/core/dbus-unit.c:360 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "" - "Wymagane jest uwierzytelnienie, aby ponownie wczytać jednostkę „$(unit)”." - --#: src/core/dbus-unit.c:361 src/core/dbus-unit.c:362 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "" - "Wymagane jest uwierzytelnienie, aby ponownie uruchomić jednostkę „$(unit)”." - --#: src/core/dbus-unit.c:534 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." -@@ -931,18 +931,18 @@ msgstr "" - "Wymagane jest uwierzytelnienie, aby wysłać sygnał uniksowy do procesów " - "jednostki „$(unit)”." - --#: src/core/dbus-unit.c:565 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Wymagane jest uwierzytelnienie, aby przywrócić stan „failed” (niepowodzenia) " - "jednostki „$(unit)”." - --#: src/core/dbus-unit.c:598 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "" - "Wymagane jest uwierzytelnienie, aby ustawić właściwości jednostki „$(unit)”." - --#: src/core/dbus-unit.c:707 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." -@@ -950,7 +950,7 @@ msgstr "" - "Wymagane jest uwierzytelnienie, aby usunąć pliki i katalogi powiązane " - "z jednostką „$(unit)”." - --#: src/core/dbus-unit.c:756 -+#: src/core/dbus-unit.c:760 - msgid "" - "Authentication is required to freeze or thaw the processes of '$(unit)' unit." - msgstr "" -diff --git a/po/pt_BR.po b/po/pt_BR.po -index ef61e47..1e807d8 100644 ---- a/po/pt_BR.po -+++ b/po/pt_BR.po -@@ -8,8 +8,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2020-05-29 03:32+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2020-05-30 09:10-0300\n" - "Last-Translator: Rafael Fontenelle \n" - "Language-Team: Brazilian Portuguese \n" -@@ -901,23 +901,23 @@ msgstr "" - "É necessária autenticação para controlar se deve ser habilitada, ou não, a " - "sincronização de horário através de rede." - --#: src/core/dbus-unit.c:358 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "É necessária autenticação para iniciar “$(unit)”." - --#: src/core/dbus-unit.c:359 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "É necessária autenticação para parar “$(unit)”." - --#: src/core/dbus-unit.c:360 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "É necessária autenticação para recarregar “$(unit)”." - --#: src/core/dbus-unit.c:361 src/core/dbus-unit.c:362 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "É necessária autenticação para reiniciar “$(unit)”." - --#: src/core/dbus-unit.c:534 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." -@@ -925,16 +925,16 @@ msgstr "" - "É necessária autenticação para enviar um sinal UNIX para os processos de " - "“$(unit)”." - --#: src/core/dbus-unit.c:565 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "É necessária autenticação para reiniciar o estado “failed” de “$(unit)”." - --#: src/core/dbus-unit.c:598 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "É necessária autenticação para definir propriedades em “$(unit)”." - --#: src/core/dbus-unit.c:707 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." -@@ -942,7 +942,7 @@ msgstr "" - "É necessária autenticação para excluir arquivos e diretórios associados com " - "“$(unit)”." - --#: src/core/dbus-unit.c:756 -+#: src/core/dbus-unit.c:760 - msgid "" - "Authentication is required to freeze or thaw the processes of '$(unit)' unit." - msgstr "" -diff --git a/po/ro.po b/po/ro.po -index 869cf6b..7924cf9 100644 ---- a/po/ro.po -+++ b/po/ro.po -@@ -6,8 +6,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2017-08-13 15:26+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2017-08-13 19:48+0200\n" - "Last-Translator: Daniel Șerbănescu \n" - "Language-Team: Gnome Romanian Translation Team\n" -@@ -19,44 +19,44 @@ msgstr "" - "20)) ? 1 : 2);;\n" - "X-Generator: Virtaal 0.7.1\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Trimite fraza secretă înapoi la sistem" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "" - "Autentificarea este necesară pentru a trimite fraza secretă introdusă înapoi " - "la sistem." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Gestionează serviciile de sistem sau alte unități" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" - "Autentificarea este necesară pentru a gestiona serviciile de sistem sau alte " - "unități." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Gestionează serviciul de sistem sau fișiere unitate" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" - "Autentificarea este necesară pentru a gestiona serviciul de sistem sau " - "fișierele unitate." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "" - "Stabilește sau destabilește variabilele de mediu și managerul de servicii " - "ale sistemului" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -64,27 +64,95 @@ msgstr "" - "Autentificarea este necesară pentru a stabili sau destabili variabile de " - "mediu și managerul de servicii ale sistemului." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Reîncarcă starea systemd" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "Autentificarea este necesară pentru a reîncărca starea systemd." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Autentificarea este necesară pentru a reîncărca starea systemd." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Autentificarea este necesară pentru a reîncărca starea systemd." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Autentificarea este necesară pentru gestionarea sesiunilor active, " -+"utilizatorilor și locurilor." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "Autentificarea este necesară pentru a atașa un dispozitiv la un loc." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Autentificarea este necesară pentru a stabili un mesaj de perete" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Autentificarea este necesară pentru gestionarea sesiunilor active, " -+"utilizatorilor și locurilor." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Stabilește numele de server" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Autentificarea este necesară pentru a stabili numele de server local." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Stabilește numele de server static" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -92,109 +160,119 @@ msgstr "" - "Autentificarea este necesara pentru a stabili numele de server static " - "configurat local, precum și numele lung de server." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Stabilește informațiile despre mașină" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "" - "Autentificarea este necesară pentru stabili informațiile mașinii locale." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Autentificarea este necesară pentru a reîncărca „$ (unit)”." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Importă o VM (mașină virtuală) sau o imagine container" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "" - "Autentificarea este necesară pentru a importa o VM (mașină virtuală) sau o " - "imagine container" - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "Exportă o VM (mașină virtuală) sau o imagine container" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "" - "Autentificarea este necesară pentru a exporta o VM (mașină virtuală) sau o " - "imagine container" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "Descarcă o VM (mașină virtuală) sau o imagine container" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "" - "Autentificarea este necesară pentru a descărca o VM (mașină virtuală) sau o " - "imagine container" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Stabilește localizarea sistemului" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "Autentificarea este necesară pentru a stabili localizarea sistemului." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Stabilește configurările tastaturii sistemului" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" - "Autentificarea este necesară pentru a stabili configurările tastaturii " - "sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Permite aplicațiilor să împiedice închiderea sistemului" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - "Autentificarea este necesară pentru ca o aplicație să împiedice închiderea " - "sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Permite aplicațiilor să întârzie închiderea sistemului" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "Autentificarea este necesară pentru ca o aplicație să întârzie închiderea " - "sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Permite aplicațiilor să împiedice starea de veghe a sistemului" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "Autentificarea este necesară pentru ca o aplicație să împiedice starea de " - "veghe a sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Permite aplicațiilor să întârzie starea de veghe sistemului" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "Autentificarea este necesară pentru ca o aplicație să întârzie starea de " - "veghe a sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "Permite aplicațiilor să împiedice suspendarea automată a sistemului" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -202,13 +280,13 @@ msgstr "" - "Autentificarea este necesară pentru ca o aplicație să împiedice suspendarea " - "automată a sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" - "Permite aplicațiilor să împiedice administrarea butonului de pornire a " - "sistemului" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." -@@ -216,13 +294,13 @@ msgstr "" - "Autentificarea este necesară pentru o aplicație să împiedice administrarea " - "butonului de pornire a sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" - "Permite aplicațiilor să împiedice administrarea butonului de suspendare al " - "sistemului" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." -@@ -230,13 +308,13 @@ msgstr "" - "Autentificarea este necesară pentru o aplicație pentru a împiedica " - "manipularea butonului de suspendare al sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" - "Permite aplicațiilor să împiedice administrarea butonului de hibernare al " - "sistemului" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -244,13 +322,13 @@ msgstr "" - "Autentificarea este necesară pentru o aplicație să împiedice administrarea " - "butonului de hibernare al sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" - "Permite aplicațiilor să împiedice administrarea comutatorului capacului al " - "sistemului" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -258,58 +336,57 @@ msgstr "" - "Autentificarea este necesară pentru ca o aplicație să împiedice manipularea " - "comutatorului capacului al sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" - msgstr "Permite utilizatorilor neautentificați să execute programe" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" - "Cererea explicită este necesară pentru a rula programe ca utilizator " - "neautentificat." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "Permite utilizatorilor neautentificați să execute programe" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Autentificarea este necesară pentru a rula programe ca utilizator " - "neautentificat." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Permite atașarea dispozitivelor la locuri" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "Autentificarea este necesară pentru a atașa un dispozitiv la un loc." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Purjează atașamentele dispozitiv-loc" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Autentificarea este necesară pentru a restabili cum dispozitivele sunt " - "atașate la locuri." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Oprește sistemul" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Este necesară autentificarea pentru oprirea sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Oprește sistemul în timp ce alți utilizatori sunt autentificați" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -317,63 +394,111 @@ msgstr "" - "Autentificarea este necesară pentru oprirea sistemului în timp ce alți " - "utilizatori sunt autentificați." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "Oprește sistemul în timp ce o aplicație a cerut să împiedice asta" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Autentificarea este necesară pentru oprirea sistemului în timp ce o " - "aplicație a cerut să împiedice asta." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Repornește sistemul" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Autentificarea este necesară pentru repornirea sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Repornește sistemul în timp ce alți utilizatori sunt autentificați" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Autentificarea este necesară pentru repornirea sistemului în timp ce alți " - "utilizatori autentificați." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "Repornește sistemul în timp ce o aplicație a cerut să împiedice asta" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Autentificarea este necesară pentru repornirea sistemului în timp ce o " - "aplicație a cerut să împiedice asta." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "Hiberneaza sistemul" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "Este necesară autentificarea pentru hibernarea sistemului." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "Hiberneaza sistemul în timp ce alți utilizatori sunt autentificați" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"Autentificarea este necesară pentru hibernare a sistemului în timp ce alți " -+"utilizatori sunt autentificați." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "Hibernează sistemul în timp ce o aplicație a cerut să împiedice asta" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"Autentificarea este necesară pentru hibernarea sistemului în timp ce o " -+"aplicație a cerut să împiedice asta." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Suspendă sistemul" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Este necesară autentificarea pentru suspendarea sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Suspendă sistemul în timp ce alți utilizatori sunt autentificați" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -381,31 +506,31 @@ msgstr "" - "Autentificarea este necesară pentru suspendarea sistemului timp ce alți " - "utilizatori autentificați." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "Suspendă sistemul în timp ce o aplicație a cerut să împiedice asta" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Autentificarea este necesară pentru suspendarea sistemului în timp ce o " - "aplicație a cerut să împiedice asta." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Hiberneaza sistemul" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "Este necesară autentificarea pentru hibernarea sistemului." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "Hiberneaza sistemul în timp ce alți utilizatori sunt autentificați" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -413,45 +538,57 @@ msgstr "" - "Autentificarea este necesară pentru hibernare a sistemului în timp ce alți " - "utilizatori sunt autentificați." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "Hibernează sistemul în timp ce o aplicație a cerut să împiedice asta" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Autentificarea este necesară pentru hibernarea sistemului în timp ce o " - "aplicație a cerut să împiedice asta." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Gestionează sesiuni active, utilizatori și locuri" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Autentificarea este necesară pentru gestionarea sesiunilor active, " - "utilizatorilor și locurilor." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Blochează sau deblochează sesiuni active" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "" - "Autentificarea este necesară pentru a bloca sau debloca sesiuni active." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "" -+"Autentificarea este necesară pentru a stabili fusul orar al sistemului." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "" - "Permite semnalizatrea către firmware pentru a porni în interfața de " - "configurare" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -459,86 +596,128 @@ msgstr "" - "Autentificarea este necesară pentru a semnaliza către firmware să pornească " - "în interfața de configurare." - --#: ../src/login/org.freedesktop.login1.policy.in.h:57 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Autentificarea este necesară pentru a semnaliza către firmware să pornească " -+"în interfața de configurare." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Autentificarea este necesară pentru a semnaliza către firmware să pornească " -+"în interfața de configurare." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Stabilește un mesaj de perete" - --#: ../src/login/org.freedesktop.login1.policy.in.h:58 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Autentificarea este necesară pentru a stabili un mesaj de perete" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Autentificarea este necesară pentru a stabili numele de server local." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Conectează la un container local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "" - "Autentificarea este necesară pentru a vă conecta într-un container local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Conectează la serverul local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "Autentificarea este necesară pentru a vă conecta la serverul local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Obține un shell într-un container local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" - "Autentificarea este necesară pentru a obține un shell într-un container " - "local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Obține un shell pe serverul local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "" - "Autentificarea este necesară pentru a obține un shell pe serverul local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Obține un pseudo-TTY într-un container local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" - "Autentificarea este necesară pentru a obține un pseudo-TTY într-un container " - "local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Obține un pseudo-TTY pe serverul local" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "" - "Autentificarea este necesară pentru a obține un pseudo-TTY pe serverul local." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Gestioneaza mașini virtuale locale și containere" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" - "Autentificarea este necesară pentru a gestiona mașini virtuale locale și " - "containere." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Gestionează imaginile locale de mașină virtuală și containere" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." -@@ -546,28 +725,262 @@ msgstr "" - "Autentificarea este necesară pentru a gestiona imagini locale de mașini " - "virtuale și de containere." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Autentificarea este necesară pentru a stabili ora sistemului." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "Autentificarea este necesară pentru a stabili ora sistemului." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Autentificarea este necesară pentru a opri „$(unit)”." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Autentificarea este necesară pentru a stabili numele de server local." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Este necesară autentificarea pentru hibernarea sistemului." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Autentificarea este necesară pentru a vă conecta la serverul local." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Autentificarea este necesară pentru a stabili numele de server local." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Este necesară autentificarea pentru hibernarea sistemului." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Autentificarea este necesară pentru a stabili localizarea sistemului." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Autentificarea este necesară pentru a stabili ora sistemului." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Autentificarea este necesară pentru a stabili ora sistemului." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Autentificarea este necesară pentru a stabili un mesaj de perete" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Autentificarea este necesară pentru a stabili un mesaj de perete" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Autentificarea este necesară pentru a reîncărca starea systemd." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Autentificarea este necesară pentru repornirea sistemului." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "" -+"Autentificarea este necesară pentru a importa o VM (mașină virtuală) sau o " -+"imagine container" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "Autentificarea este necesară pentru a atașa un dispozitiv la un loc." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "" -+"Autentificarea este necesară pentru a descărca o VM (mașină virtuală) sau o " -+"imagine container" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "Autentificarea este necesară pentru a stabili un mesaj de perete" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "Autentificarea este necesară pentru a stabili un mesaj de perete" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Autentificarea este necesară pentru a stabili configurările tastaturii " -+"sistemului." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Stabilește ora sistemului" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "Autentificarea este necesară pentru a stabili ora sistemului." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Stabilește fusul orar al sistemului" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "" - "Autentificarea este necesară pentru a stabili fusul orar al sistemului." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "Stabilește RTC la ora locală sau UTC" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -575,11 +988,11 @@ msgstr "" - "Autentificarea este necesară pentru a controla dacă RTC stochează ora locală " - "sau UTC." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Comută sincronizarea cu ora rețelei" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -587,32 +1000,59 @@ msgstr "" - "Autentificarea este necesară pentru a controla dacă sincronizarea cu ora " - "rețelei ar trebui activată." - --#: ../src/core/dbus-unit.c:457 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Autentificarea este necesară pentru a porni „$(unit)”." - --#: ../src/core/dbus-unit.c:458 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Autentificarea este necesară pentru a opri „$(unit)”." - --#: ../src/core/dbus-unit.c:459 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Autentificarea este necesară pentru a reîncărca „$ (unit)”." - --#: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Autentificarea este necesară pentru a reporni „$(unit)”." - --#: ../src/core/dbus-unit.c:568 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Autentificarea este necesară pentru a omorî „$(unit)”." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "" -+"Autentificarea este necesară pentru a stabili proprietățile pe „$(unit)”." - --#: ../src/core/dbus-unit.c:599 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Autentificarea este necesară pentru a restabili starea „eșuată” a „$(unit)”." - --#: ../src/core/dbus-unit.c:632 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "" - "Autentificarea este necesară pentru a stabili proprietățile pe „$(unit)”." -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"Autentificarea este necesară pentru a restabili starea „eșuată” a „$(unit)”." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Autentificarea este necesară pentru a restabili starea „eșuată” a „$(unit)”." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Autentificarea este necesară pentru a omorî „$(unit)”." -diff --git a/po/ru.po b/po/ru.po -index f13c51f..778da46 100644 ---- a/po/ru.po -+++ b/po/ru.po -@@ -9,15 +9,15 @@ msgid "" - msgstr "" - "Project-Id-Version: systemd\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2020-03-03 00:56+1000\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2020-03-03 16:05+1000\n" - "Last-Translator: Vladimir Yerilov \n" - "Language: ru\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" --"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<" --"=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" -+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" - "X-Generator: Lokalize 19.12.2\n" - - #: src/core/org.freedesktop.systemd1.policy.in:22 -@@ -78,8 +78,8 @@ msgstr "Создать домашнее пространство" - #: src/home/org.freedesktop.home1.policy:14 - msgid "Authentication is required to create a user's home area." - msgstr "" --"Чтобы создать домашнее пространство пользователя, необходимо пройти" --" аутентификацию." -+"Чтобы создать домашнее пространство пользователя, необходимо пройти " -+"аутентификацию." - - #: src/home/org.freedesktop.home1.policy:23 - msgid "Remove a home area" -@@ -88,8 +88,8 @@ msgstr "Удалить домашнее пространство" - #: src/home/org.freedesktop.home1.policy:24 - msgid "Authentication is required to remove a user's home area." - msgstr "" --"Чтобы удалить домашнее пространство пользователя, необходимо пройти" --" аутентификацию." -+"Чтобы удалить домашнее пространство пользователя, необходимо пройти " -+"аутентификацию." - - #: src/home/org.freedesktop.home1.policy:33 - msgid "Check credentials of a home area" -@@ -99,8 +99,8 @@ msgstr "Проверить учётные данные домашнего про - msgid "" - "Authentication is required to check credentials against a user's home area." - msgstr "" --"Чтобы проверить учётные данные для домашнего пространства пользователя," --" необходимо пройти аутентификацию." -+"Чтобы проверить учётные данные для домашнего пространства пользователя, " -+"необходимо пройти аутентификацию." - - #: src/home/org.freedesktop.home1.policy:43 - msgid "Update a home area" -@@ -109,8 +109,8 @@ msgstr "Обновить домашнее пространство" - #: src/home/org.freedesktop.home1.policy:44 - msgid "Authentication is required to update a user's home area." - msgstr "" --"Чтобы обновить домашнее пространство пользователя, необходимо пройти" --" аутентификацию." -+"Чтобы обновить домашнее пространство пользователя, необходимо пройти " -+"аутентификацию." - - #: src/home/org.freedesktop.home1.policy:53 - msgid "Resize a home area" -@@ -119,8 +119,8 @@ msgstr "Изменить размер домашнего пространств - #: src/home/org.freedesktop.home1.policy:54 - msgid "Authentication is required to resize a user's home area." - msgstr "" --"Чтобы изменить размер домашнего пространства пользователя, необходимо пройти" --" аутентификацию." -+"Чтобы изменить размер домашнего пространства пользователя, необходимо пройти " -+"аутентификацию." - - #: src/home/org.freedesktop.home1.policy:63 - msgid "Change password of a home area" -@@ -130,8 +130,8 @@ msgstr "Изменить пароль для домашнего простран - msgid "" - "Authentication is required to change the password of a user's home area." - msgstr "" --"Чтобы изменить пароль для домашнего пространства пользователя, необходимо" --" пройти аутентификацию." -+"Чтобы изменить пароль для домашнего пространства пользователя, необходимо " -+"пройти аутентификацию." - - #: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" -@@ -472,8 +472,8 @@ msgid "" - "Authentication is required to halt the system while an application is " - "inhibiting this." - msgstr "" --"Чтобы остановить систему несмотря на то, что приложение запросило блокировку" --" выключения, необходимо пройти аутентификацию." -+"Чтобы остановить систему несмотря на то, что приложение запросило блокировку " -+"выключения, необходимо пройти аутентификацию." - - #: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" -@@ -588,8 +588,8 @@ msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." - msgstr "" --"Чтобы запустить режим настройки прошивки материнской платы, " --"необходимо пройти аутентификацию." -+"Чтобы запустить режим настройки прошивки материнской платы, необходимо " -+"пройти аутентификацию." - - #: src/login/org.freedesktop.login1.policy:363 - msgid "Indicate to the boot loader to boot to the boot loader menu" -@@ -600,8 +600,8 @@ msgid "" - "Authentication is required to indicate to the boot loader to boot to the " - "boot loader menu." - msgstr "" --"Чтобы отобразить меню загрузчика при следующей загрузке, " --"необходимо пройти аутентификацию." -+"Чтобы отобразить меню загрузчика при следующей загрузке, необходимо пройти " -+"аутентификацию." - - #: src/login/org.freedesktop.login1.policy:374 - msgid "Indicate to the boot loader to boot a specific entry" -@@ -612,8 +612,8 @@ msgid "" - "Authentication is required to indicate to the boot loader to boot into a " - "specific boot loader entry." - msgstr "" --"Чтобы установить определённую загрузочную запись для загрузки, " --"необходимо пройти аутентификацию." -+"Чтобы установить определённую загрузочную запись для загрузки, необходимо " -+"пройти аутентификацию." - - #: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" -@@ -780,7 +780,8 @@ msgstr "Включить/отключить DNS поверх TLS" - #: src/resolve/org.freedesktop.resolve1.policy:100 - msgid "Authentication is required to enable or disable DNS over TLS." - msgstr "" --"Чтобы включить или отключить DNS поверх TLS, необходимо пройти аутентификацию." -+"Чтобы включить или отключить DNS поверх TLS, необходимо пройти " -+"аутентификацию." - - #: src/network/org.freedesktop.network1.policy:99 - #: src/resolve/org.freedesktop.resolve1.policy:110 -@@ -822,32 +823,43 @@ msgstr "" - "Чтобы сбросить локальные настройки DNS, необходимо пройти аутентификацию." - - #: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "" -+"Чтобы отправить сообщение на все терминалы, необходимо пройти аутентификацию." -+ -+#: src/network/org.freedesktop.network1.policy:154 - msgid "Renew dynamic addresses" - msgstr "Обновить динамические адреса" - --#: src/network/org.freedesktop.network1.policy:144 -+#: src/network/org.freedesktop.network1.policy:155 - msgid "Authentication is required to renew dynamic addresses." - msgstr "Чтобы обновить динамические адреса, необходимо пройти аутентификацию." - --#: src/network/org.freedesktop.network1.policy:154 -+#: src/network/org.freedesktop.network1.policy:165 - msgid "Reload network settings" - msgstr "Перечитать настройки сети" - --#: src/network/org.freedesktop.network1.policy:155 -+#: src/network/org.freedesktop.network1.policy:166 - msgid "Authentication is required to reload network settings." - msgstr "" - "Чтобы заставить systemd перечитать настройки сети, необходимо пройти " - "аутентификацию." - --#: src/network/org.freedesktop.network1.policy:165 -+#: src/network/org.freedesktop.network1.policy:176 - msgid "Reconfigure network interface" - msgstr "Изменить конфигурацию сетевого интерфейса" - --#: src/network/org.freedesktop.network1.policy:166 -+#: src/network/org.freedesktop.network1.policy:177 - msgid "Authentication is required to reconfigure network interface." - msgstr "" --"Чтобы изменить конфигурацию сетевого интерфейса, необходимо пройти" --" аутентификацию." -+"Чтобы изменить конфигурацию сетевого интерфейса, необходимо пройти " -+"аутентификацию." - - #: src/portable/org.freedesktop.portable1.policy:13 - msgid "Inspect a portable service image" -@@ -946,47 +958,58 @@ msgstr "" - "Чтобы включить или выключить синхронизацию времени по сети, необходимо " - "пройти аутентификацию." - --#: src/core/dbus-unit.c:356 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Чтобы запустить «$(unit)», необходимо пройти аутентификацию." - --#: src/core/dbus-unit.c:357 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Чтобы остановить «$(unit)», необходимо пройти аутентификацию." - --#: src/core/dbus-unit.c:358 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "" - "Чтобы заставить «$(unit)» перечитать конфигурацию, необходимо пройти " - "аутентификацию." - --#: src/core/dbus-unit.c:359 src/core/dbus-unit.c:360 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Чтобы перезапустить «$(unit)», необходимо пройти аутентификацию." - --#: src/core/dbus-unit.c:532 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." - msgstr "" --"Чтобы отправить сигнал UNIX процессам юнита «$(unit)», необходимо пройти" --" аутентификацию." -+"Чтобы отправить сигнал UNIX процессам юнита «$(unit)», необходимо пройти " -+"аутентификацию." - --#: src/core/dbus-unit.c:563 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Чтобы сбросить состояние «failed» у юнита «$(unit)», необходимо пройти " - "аутентификацию." - --#: src/core/dbus-unit.c:596 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "" - "Чтобы изменить параметры юнита «$(unit)», необходимо пройти аутентификацию." - --#: src/core/dbus-unit.c:705 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." - msgstr "" --"Чтобы удалить файлы и директории, относящиеся к юниту «$(unit)», необходимо" --" пройти аутентификацию." -+"Чтобы удалить файлы и директории, относящиеся к юниту «$(unit)», необходимо " -+"пройти аутентификацию." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to send a UNIX signal to the processes of " -+#| "'$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Чтобы отправить сигнал UNIX процессам юнита «$(unit)», необходимо пройти " -+"аутентификацию." -diff --git a/po/sk.po b/po/sk.po -index 971df90..8b87bd6 100644 ---- a/po/sk.po -+++ b/po/sk.po -@@ -6,55 +6,55 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2017-06-24 03:26+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2017-06-25 11:03+0200\n" -+"Last-Translator: Dušan Kazik \n" - "Language-Team: Slovak \n" - "Language: sk\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" - "Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" --"Last-Translator: Dušan Kazik \n" - "X-Generator: Poedit 2.0.2\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Odoslanie hesla späť do systému" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "" - "Vyžaduje sa overenie totožnosti na odoslanie zadaného hesla späť do systému." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Správa systémových služieb alebo iných jednotiek" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" - "Vyžaduje sa overenie totožnosti na správu systémových služieb alebo iných " - "jednotiek." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Správa systémovej služby alebo súborov jednotky" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" - "Vyžaduje sa overenie totožnosti na správu systémovej služby alebo súborov " - "jednotky." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "" - "Nastavenie alebo zrušenie nastavenia premenných prostredia systému a správcu " - "služieb" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -62,28 +62,92 @@ msgstr "" - "Vyžaduje sa overenie totožnosti na nastavenie alebo zrušenie nastavenia " - "premenných prostredia systému a správcu služieb." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Znovu načítanie stavu systému systemd" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "" - "Vyžaduje sa overenie totožnosti na znovu načítanie stavu systému systemd." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na znovu načítanie stavu systému systemd." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na znovu načítanie stavu systému systemd." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to suspend the system." -+msgid "Authentication is required to update a user's home area." -+msgstr "Vyžaduje sa overenie totožnosti na uspanie systému." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to suspend the system." -+msgid "Authentication is required to resize a user's home area." -+msgstr "Vyžaduje sa overenie totožnosti na uspanie systému." -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie miestnych nastavení." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Nastavenie názvu hostiteľa" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Nastavenie nemenného názvu hostiteľa" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -91,191 +155,200 @@ msgstr "" - "Vyžaduje sa overenie totožnosti na nastavenie pevne určeného názvu miestneho " - "hostiteľa, známeho ako zrozumiteľný názov hostiteľa." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Nastavenie informácií o počítači" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "" - "Vyžaduje sa overenie totožnosti na nastavenie informácií o miestnom počítači." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to get product UUID." -+msgstr "Vyžaduje sa overenie totožnosti na reštartovanie systému." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "" - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Nastavenie miestnych nastavení" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "Vyžaduje sa overenie totožnosti na nastavenie miestnych nastavení." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Nastavenie nastavení systémovej klávesnice" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" - "Vyžaduje sa overenie totožnosti na nastavenie nastavení systémovej " - "klávesnice." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Umožnenie aplikáciám odložiť spánok systému" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "Vyžaduje sa overenie totožnosti na odloženie spánku systému aplikáciou." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" - msgstr "Umožnenie neprihlásenému používateľovi spúšťanie programov" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" - "Vyžaduje sa explicitná požiadavka na spúšťanie programov ako neprihlásený " - "používateľ." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "Umožnenie neprihláseným používateľom spúšťanie programov" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Vyžaduje sa overenie totožnosti na spúšťanie programov ako neprihlásený " - "používateľ." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Vypnutie systému" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Vyžaduje sa overenie totožnosti na vypnutie systému." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Vypnutie systému, pokiaľ sú prihlásení iní používatelia" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -283,59 +356,103 @@ msgstr "" - "Vyžaduje sa overenie totožnosti na vypnutie systému, pokiaľ sú prihlásení " - "iní používatelia." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Reštart systému" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Vyžaduje sa overenie totožnosti na reštartovanie systému." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Reštart systému, pokiaľ sú prihlásení iní používatelia" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Vyžaduje sa overenie totožnosti na reštartovanie systému, pokiaľ sú " - "prihlásení iní používatelia." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Reboot the system" -+msgid "Halt the system" -+msgstr "Reštart systému" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to halt the system." -+msgstr "Vyžaduje sa overenie totožnosti na reštartovanie systému." -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Reboot the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "Reštart systému, pokiaľ sú prihlásení iní používatelia" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reboot the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na reštartovanie systému, pokiaľ sú " -+"prihlásení iní používatelia." -+ -+#: src/login/org.freedesktop.login1.policy:246 -+msgid "Halt the system while an application is inhibiting this" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na nastavenie nastavení systémovej " -+"klávesnice." -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Uspanie systému" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Vyžaduje sa overenie totožnosti na uspanie systému." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Uspanie systému, pokiaľ sú prihlásení iní používatelia" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -343,68 +460,79 @@ msgstr "" - "Vyžaduje sa overenie totožnosti na uspanie systému, pokiaľ sú prihlásení iní " - "používatelia." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Zamknutie alebo odomknutie aktívnych relácií" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "" - "Vyžaduje sa overenie totožnosti na uzamknutie alebo odomknutie aktívnych " - "relácií." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "Umožnenie indikácie spustenia inštalačného rozhrania pre firmvér" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -412,114 +540,391 @@ msgstr "" - "Vyžaduje sa overenie totožnosti na indikáciu spustenia inštalačného " - "rozhrania pre firmvér." - --#: ../src/login/org.freedesktop.login1.policy.in.h:57 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na indikáciu spustenia inštalačného " -+"rozhrania pre firmvér." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na indikáciu spustenia inštalačného " -+"rozhrania pre firmvér." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "" - --#: ../src/login/org.freedesktop.login1.policy.in.h:58 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Prihlásenie do miestneho kontajneru" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "" - "Vyžaduje sa overenie totožnosti na prihlásenie do miestneho kontajneru." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." - msgstr "" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set NTP servers." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie miestnych nastavení." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNS servers." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie miestnych nastavení." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set domains." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Vyžaduje sa overenie totožnosti na reštartovanie systému." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie miestnych nastavení." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset NTP settings." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na nastavenie nastavení systémovej " -+"klávesnice." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset DNS settings." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na nastavenie nastavení systémovej " -+"klávesnice." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to suspend the system." -+msgid "Authentication is required to send force renew message." -+msgstr "Vyžaduje sa overenie totožnosti na uspanie systému." -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to suspend the system." -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Vyžaduje sa overenie totožnosti na uspanie systému." -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na znovu načítanie stavu systému systemd." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Vyžaduje sa overenie totožnosti na reštartovanie systému." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to inspect a portable service image." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie miestnych nastavení." -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to power off the system." -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "Vyžaduje sa overenie totožnosti na vypnutie systému." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "Vyžaduje sa overenie totožnosti na reštartovanie systému." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "Vyžaduje sa overenie totožnosti na reštartovanie systému." -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na nastavenie nastavení systémovej " -+"klávesnice." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." - msgstr "" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Zapnutie alebo vypnutie sieťovej synchronizácie času" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -527,30 +932,51 @@ msgstr "" - "Vyžaduje sa overenie totožnosti na ovládanie, či má byť povolená " - "synchronizácia času cez sieť." - --#: ../src/core/dbus-unit.c:457 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "" - --#: ../src/core/dbus-unit.c:458 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "" - --#: ../src/core/dbus-unit.c:459 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "" - --#: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "" - --#: ../src/core/dbus-unit.c:568 --msgid "Authentication is required to kill '$(unit)'." --msgstr "" -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to suspend the system." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "Vyžaduje sa overenie totožnosti na uspanie systému." - --#: ../src/core/dbus-unit.c:599 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - --#: ../src/core/dbus-unit.c:632 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "" -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na znovu načítanie stavu systému systemd." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Vyžaduje sa overenie totožnosti na znovu načítanie stavu systému systemd." -diff --git a/po/sr.po b/po/sr.po -index a62f5cf..4747b26 100644 ---- a/po/sr.po -+++ b/po/sr.po -@@ -7,8 +7,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: \n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2018-02-13 03:26+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2018-02-18 22:03+0100\n" - "Last-Translator: Марко М. Костић \n" - "Language-Team: \n" -@@ -20,41 +20,41 @@ msgstr "" - "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" - "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - --#: src/core/org.freedesktop.systemd1.policy.in.in:22 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Пошаљи фразу назад ка систему" - --#: src/core/org.freedesktop.systemd1.policy.in.in:23 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "" - "Потребно је да се идентификујете да бисте послали фразу назад у систем." - --#: src/core/org.freedesktop.systemd1.policy.in.in:33 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Управљај системским услугама и другим јединицама" - --#: src/core/org.freedesktop.systemd1.policy.in.in:34 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" - "Потребно је да се идентификујете да бисте управљали системским услугама или " - "другим јединицама." - --#: src/core/org.freedesktop.systemd1.policy.in.in:43 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Управљај системском услугом или јединичним датотекама" - --#: src/core/org.freedesktop.systemd1.policy.in.in:44 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" - "Потребно је да се идентификујете да бисте управљали системском услугом или " - "јединичним датотекама." - --#: src/core/org.freedesktop.systemd1.policy.in.in:53 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "Мењај променљиве окружења на систему и унутар управника услуга" - --#: src/core/org.freedesktop.systemd1.policy.in.in:54 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -62,28 +62,98 @@ msgstr "" - "Потребно је да се идентификујете да бисте мењали променљиве окружења на " - "систему и унутар управника услуга." - --#: src/core/org.freedesktop.systemd1.policy.in.in:63 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Поново учитај стање систем-деа" - --#: src/core/org.freedesktop.systemd1.policy.in.in:64 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "" - "Потребно је да се идентификујете да бисте поново учитали стање систем-деа." - --#: src/hostname/org.freedesktop.hostname1.policy.in:22 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "" -+"Потребно је да се идентификујете да бисте поново учитали стање систем-деа." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "" -+"Потребно је да се идентификујете да бисте поново учитали стање систем-деа." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Потребно је да се идентификујете да бисте управљали покренутим сесијама, " -+"корисницима и седиштима." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "Потребно је да се идентификујете да бисте закачили уређај на седиште." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Потребно је да се идентификујете да бисте поставили зидну поруку" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Потребно је да се идентификујете да бисте управљали покренутим сесијама, " -+"корисницима и седиштима." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Постави назив машине" - --#: src/hostname/org.freedesktop.hostname1.policy.in:23 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Потребно је да се идентификујете да бисте поставили назив машине." - --#: src/hostname/org.freedesktop.hostname1.policy.in:32 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Постави статички назив машине" - --#: src/hostname/org.freedesktop.hostname1.policy.in:33 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -91,111 +161,121 @@ msgstr "" - "Потребно је да се идентификујете да бисте поставили статички назив машине и " - "да бисте поставили леп назив машине." - --#: src/hostname/org.freedesktop.hostname1.policy.in:43 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Постави податке о машини" - --#: src/hostname/org.freedesktop.hostname1.policy.in:44 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "" - "Потребно је да се идентификујете да бисте поставили податке о локалној " - "машини." - --#: src/import/org.freedesktop.import1.policy.in:22 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Потребно је да се идентификујете да бисте поново учитали „$(unit)“." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Увези ВМ или слику контејнера" - --#: src/import/org.freedesktop.import1.policy.in:23 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "" - "Потребно је да се идентификујете да бисте увезли виртуелну машину или слику " - "контејнера" - --#: src/import/org.freedesktop.import1.policy.in:32 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "Извези ВМ или слику контејнера" - --#: src/import/org.freedesktop.import1.policy.in:33 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "" - "Потребно је да се идентификујете да бисте извезли виртуелну машину или слику " - "контејнера" - --#: src/import/org.freedesktop.import1.policy.in:42 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "Преузми ВМ или слику контејнера" - --#: src/import/org.freedesktop.import1.policy.in:43 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "" - "Потребно је да се идентификујете да бисте преузели виртуелну машину или " - "слику контејнера" - --#: src/locale/org.freedesktop.locale1.policy.in:22 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Постави основни језик система" - --#: src/locale/org.freedesktop.locale1.policy.in:23 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "" - "Потребно је да се идентификујете да бисте поставили основни језик система." - --#: src/locale/org.freedesktop.locale1.policy.in:33 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Постави подешавање системске тастатуре" - --#: src/locale/org.freedesktop.locale1.policy.in:34 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" - "Потребно је да се идентификујете да бисте поставили подешавања системске " - "тастатуре." - --#: src/login/org.freedesktop.login1.policy.in:22 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Дозволи програмима да спрече гашење система" - --#: src/login/org.freedesktop.login1.policy.in:23 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - "Потребно је да се идентификујете да бисте дозволили програму да спречи " - "гашење система." - --#: src/login/org.freedesktop.login1.policy.in:33 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Дозволи програмима да одложе гашење система" - --#: src/login/org.freedesktop.login1.policy.in:34 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "Потребно је да се идентификујете да бисте дозволили програму да одложи " - "гашење система." - --#: src/login/org.freedesktop.login1.policy.in:44 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Дозволи програмима да спрече спавање система" - --#: src/login/org.freedesktop.login1.policy.in:45 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "Потребно је да се идентификујете да бисте дозволили програму да спречи " - "спавање система." - --#: src/login/org.freedesktop.login1.policy.in:55 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Дозволи програмима да одложе спавање система" - --#: src/login/org.freedesktop.login1.policy.in:56 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "Потребно је да се идентификујете да бисте дозволили програму да одложи " - "спавање система." - --#: src/login/org.freedesktop.login1.policy.in:65 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "Дозволи програмима да спрече самосталну обуставу система" - --#: src/login/org.freedesktop.login1.policy.in:66 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -203,11 +283,11 @@ msgstr "" - "Потребно је да се идентификујете да бисте дозволили програму да спречи " - "самосталну обуставу система." - --#: src/login/org.freedesktop.login1.policy.in:75 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "Дозволи програмима да спрече систему управљање дугметом за напајање" - --#: src/login/org.freedesktop.login1.policy.in:76 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." -@@ -215,11 +295,11 @@ msgstr "" - "Потребно је да се идентификујете да бисте дозволили програму да спречи " - "систему управљање дугметом за напајање." - --#: src/login/org.freedesktop.login1.policy.in:86 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "Дозволи програмима да спрече систему управљање дугметом за обуставу" - --#: src/login/org.freedesktop.login1.policy.in:87 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." -@@ -227,11 +307,11 @@ msgstr "" - "Потребно је да се идентификујете да бисте дозволили програму да спречи " - "систему управљање дугметом за обуставу." - --#: src/login/org.freedesktop.login1.policy.in:97 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "Дозволи програмима да спрече систему управљање дугметом за спавање" - --#: src/login/org.freedesktop.login1.policy.in:98 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -239,13 +319,13 @@ msgstr "" - "Потребно је да се идентификујете да бисте дозволили програму да спречи " - "систему управљање дугметом за спавање." - --#: src/login/org.freedesktop.login1.policy.in:107 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" - "Дозволи програмима да спрече систему да уради било шта приликом заклапања " - "екрана" - --#: src/login/org.freedesktop.login1.policy.in:108 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -253,58 +333,57 @@ msgstr "" - "Потребно је да се идентификујете да бисте дозволили програму да спречи " - "систему да уради било шта приликом заклапања екрана." - --#: src/login/org.freedesktop.login1.policy.in:117 -+#: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" - msgstr "Дозволи непријављеним корисницима да покрећу програме" - --#: src/login/org.freedesktop.login1.policy.in:118 -+#: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" - "Експлицитан захтев је потребан да бисте покретали програме као непријављен " - "корисник." - --#: src/login/org.freedesktop.login1.policy.in:127 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "Дозволи непријављеним корисницима да покрећу програме" - --#: src/login/org.freedesktop.login1.policy.in:128 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Потребно је да се идентификујете да бисте покретали програме као непријављен " - "корисник." - --#: src/login/org.freedesktop.login1.policy.in:137 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Дозволи качење уређаја на седишта" - --#: src/login/org.freedesktop.login1.policy.in:138 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "Потребно је да се идентификујете да бисте закачили уређај на седиште." - --#: src/login/org.freedesktop.login1.policy.in:148 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Испери уређај да би уседиштио закачено" - --#: src/login/org.freedesktop.login1.policy.in:149 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Потребно је да се идентификујете да бисте поново подесили како се уређаји " - "каче на седишта." - --#: src/login/org.freedesktop.login1.policy.in:158 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Искључи систем" - --#: src/login/org.freedesktop.login1.policy.in:159 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Потребно је да се идентификујете да бисте искључили систем." - --#: src/login/org.freedesktop.login1.policy.in:169 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Искључи систем док су други корисници пријављени" - --#: src/login/org.freedesktop.login1.policy.in:170 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -312,95 +391,99 @@ msgstr "" - "Потребно је да се идентификујете да бисте искључили систем док су други " - "корисници пријављени." - --#: src/login/org.freedesktop.login1.policy.in:180 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "Искључи систем иако је програм затражио да се спречи гашење" - --#: src/login/org.freedesktop.login1.policy.in:181 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Потребно је да се идентификујете да бисте искључили систем иако је програм " - "затражио да се спречи гашење система." - --#: src/login/org.freedesktop.login1.policy.in:191 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Поново покрени систем" - --#: src/login/org.freedesktop.login1.policy.in:192 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Потребно је да се идентификујете да бисте поново покренули систем." - --#: src/login/org.freedesktop.login1.policy.in:202 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Поново покрени систем док су други корисници пријављени" - --#: src/login/org.freedesktop.login1.policy.in:203 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Потребно је да се идентификујете да бисте поново покренули систем док су " - "други корисници пријављени." - --#: src/login/org.freedesktop.login1.policy.in:213 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "Поново покрени систем иако је програм затражио да се спречи гашење" - --#: src/login/org.freedesktop.login1.policy.in:214 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Потребно је да се идентификујете да бисте поново покренули систем иако је " - "програм затражио да се спречи гашење система." - --#: src/login/org.freedesktop.login1.policy.in:224 -+#: src/login/org.freedesktop.login1.policy:224 - msgid "Halt the system" - msgstr "Заустави систем" - --#: src/login/org.freedesktop.login1.policy.in:225 -+#: src/login/org.freedesktop.login1.policy:225 - msgid "Authentication is required to halt the system." - msgstr "Потребно је да се идентификујете да бисте зауставили систем." - --#: src/login/org.freedesktop.login1.policy.in:235 -+#: src/login/org.freedesktop.login1.policy:235 - msgid "Halt the system while other users are logged in" - msgstr "Заустави систем док су други корисници пријављени" - --#: src/login/org.freedesktop.login1.policy.in:236 -+#: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "" - "Потребно је да се идентификујете да бисте зауставили систем док су други " - "корисници пријављени." - --#: src/login/org.freedesktop.login1.policy.in:246 -+#: src/login/org.freedesktop.login1.policy:246 - msgid "Halt the system while an application is inhibiting this" - msgstr "Заустави систем иако програм тражи да се спречи заустављање" - --#: src/login/org.freedesktop.login1.policy.in:247 -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." -+"Authentication is required to halt the system while an application is " -+"inhibiting this." - msgstr "" --"Потребно је да се идентификујете да бисте зауставили систем иако програм " --"тражи да се спречи заустављање система." -+"Потребно је да се идентификујете да бисте успавали систем иако је програм " -+"затражио да се спречи успављивање система." - --#: src/login/org.freedesktop.login1.policy.in:257 -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Обустави систем" - --#: src/login/org.freedesktop.login1.policy.in:258 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Потребно је да се идентификујете да бисте обуставили систем." - --#: src/login/org.freedesktop.login1.policy.in:267 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Обустави систем док су други корисници пријављени" - --#: src/login/org.freedesktop.login1.policy.in:268 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -408,31 +491,31 @@ msgstr "" - "Потребно је да се идентификујете да бисте обуставили систем док су други " - "корисници пријављени." - --#: src/login/org.freedesktop.login1.policy.in:278 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "Обуставите систем иако програм тражи да се спречи обустава" - --#: src/login/org.freedesktop.login1.policy.in:279 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Потребно је да се идентификујете да бисте обуставили систем иако је програм " - "затражио да се спречи обустава система." - --#: src/login/org.freedesktop.login1.policy.in:289 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Успавај систем" - --#: src/login/org.freedesktop.login1.policy.in:290 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "Потребно је да се идентификујете да бисте успавали систем." - --#: src/login/org.freedesktop.login1.policy.in:299 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "Успавај систем док су други корисници пријављени" - --#: src/login/org.freedesktop.login1.policy.in:300 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -440,44 +523,56 @@ msgstr "" - "Потребно је да се идентификујете да бисте успавали систем док су други " - "корисници пријављени." - --#: src/login/org.freedesktop.login1.policy.in:310 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "Успавај систем иако је програм затражио да се спречи спавање" - --#: src/login/org.freedesktop.login1.policy.in:311 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Потребно је да се идентификујете да бисте успавали систем иако је програм " - "затражио да се спречи успављивање система." - --#: src/login/org.freedesktop.login1.policy.in:321 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Управљај покренутим сесијама, корисницима и седиштима" - --#: src/login/org.freedesktop.login1.policy.in:322 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Потребно је да се идентификујете да бисте управљали покренутим сесијама, " - "корисницима и седиштима." - --#: src/login/org.freedesktop.login1.policy.in:331 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Закључај или откључај покренуте сесије" - --#: src/login/org.freedesktop.login1.policy.in:332 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "" - "Потребно је да се идентификујете да бисте закључавали или откључавали " - "покренуте сесије." - --#: src/login/org.freedesktop.login1.policy.in:341 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "" -+"Потребно је да се идентификујете да бисте поставили системску временску зону." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "Напомени фирмверу да се подигне у режиму подешавања интерфејса" - --#: src/login/org.freedesktop.login1.policy.in:342 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -485,89 +580,131 @@ msgstr "" - "Потребно је да се идентификујете да бисте напоменули фирмверу да се подигне " - "у режиму подешавања интерфејса." - --#: src/login/org.freedesktop.login1.policy.in:351 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Потребно је да се идентификујете да бисте напоменули фирмверу да се подигне " -+"у режиму подешавања интерфејса." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Потребно је да се идентификујете да бисте напоменули фирмверу да се подигне " -+"у режиму подешавања интерфејса." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Постави зидну поруку" - --#: src/login/org.freedesktop.login1.policy.in:352 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Потребно је да се идентификујете да бисте поставили зидну поруку" - --#: src/machine/org.freedesktop.machine1.policy.in:22 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to halt the system." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Потребно је да се идентификујете да бисте зауставили систем." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Пријави се у локални контејнер" - --#: src/machine/org.freedesktop.machine1.policy.in:23 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "" - "Потребно је да се идентификујете да бисте се пријавили у локални контејнер." - --#: src/machine/org.freedesktop.machine1.policy.in:32 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Пријави се у локалног домаћина" - --#: src/machine/org.freedesktop.machine1.policy.in:33 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "" - "Потребно је да се идентификујете да бисте се пријавили у локалног домаћина." - --#: src/machine/org.freedesktop.machine1.policy.in:42 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Добиј приступ шкољци унутар локалног контејнера" - --#: src/machine/org.freedesktop.machine1.policy.in:43 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" - "Потребно је да се идентификујете да бисте добили приступ шкољци унутар " - "локалног контејнера." - --#: src/machine/org.freedesktop.machine1.policy.in:53 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Добиј приступ шкољци на локалном домаћину" - --#: src/machine/org.freedesktop.machine1.policy.in:54 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "" - "Потребно је да се идентификујете да бисте добили приступ шкољци на локалном " - "домаћину." - --#: src/machine/org.freedesktop.machine1.policy.in:64 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Добиј приступ псеудо писаћој машини унутар локалног контејнера" - --#: src/machine/org.freedesktop.machine1.policy.in:65 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" - "Потребно је да се идентификујете да бисте добили приступ псеудо писаћој " - "машини унутар локалног контејнера." - --#: src/machine/org.freedesktop.machine1.policy.in:74 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Добиј приступ псеудо писаћој машини на локалном домаћину" - --#: src/machine/org.freedesktop.machine1.policy.in:75 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "" - "Потребно је да се идентификујете да бисте добили приступ псеудо писаћој " - "машини на локалном домаћину." - --#: src/machine/org.freedesktop.machine1.policy.in:84 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Управљај локалним виртуелним машинама и контејнерима" - --#: src/machine/org.freedesktop.machine1.policy.in:85 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" - "Потребно је да се идентификујете да бисте управљали локалним виртуелним " - "машинама и контејнерима." - --#: src/machine/org.freedesktop.machine1.policy.in:95 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Управљај локалним виртуелним машинама и сликама контејнера" - --#: src/machine/org.freedesktop.machine1.policy.in:96 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." -@@ -575,46 +712,265 @@ msgstr "" - "Потребно је да се идентификујете да бисте управљали локалним виртуелним " - "машинама и сликама контејнера." - --#: src/resolve/org.freedesktop.resolve1.policy.in:22 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Потребно је да се идентификујете да бисте поставили системско време." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+#, fuzzy -+#| msgid "Register a DNS-SD service" -+msgid "Set DNS servers" -+msgstr "Региструј DNS-SD услугу" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to set DNS servers." -+msgstr "Потребно је да се идентификујете да бисте регистровали DNS-SD услугу" -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Потребно је да се идентификујете да бисте зауставили „$(unit)“." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Потребно је да се идентификујете да бисте поставили назив машине." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Потребно је да се идентификујете да бисте успавали систем." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "" -+"Потребно је да се идентификујете да бисте се пријавили у локалног домаћина." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Потребно је да се идентификујете да бисте регистровали DNS-SD услугу" -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Потребно је да се идентификујете да бисте успавали систем." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "" -+"Потребно је да се идентификујете да бисте поставили основни језик система." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Потребно је да се идентификујете да бисте поставили системско време." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Потребно је да се идентификујете да бисте поставили системско време." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Потребно је да се идентификујете да бисте поставили зидну поруку" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Потребно је да се идентификујете да бисте поставили зидну поруку" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "" -+"Потребно је да се идентификујете да бисте поново учитали стање систем-деа." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Потребно је да се идентификујете да бисте поново покренули систем." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "" -+"Потребно је да се идентификујете да бисте увезли виртуелну машину или слику " -+"контејнера" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "Потребно је да се идентификујете да бисте закачили уређај на седиште." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "" -+"Потребно је да се идентификујете да бисте преузели виртуелну машину или " -+"слику контејнера" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 - msgid "Register a DNS-SD service" - msgstr "Региструј DNS-SD услугу" - --#: src/resolve/org.freedesktop.resolve1.policy.in:23 -+#: src/resolve/org.freedesktop.resolve1.policy:23 - msgid "Authentication is required to register a DNS-SD service" - msgstr "Потребно је да се идентификујете да бисте регистровали DNS-SD услугу" - --#: src/resolve/org.freedesktop.resolve1.policy.in:33 -+#: src/resolve/org.freedesktop.resolve1.policy:33 - msgid "Unregister a DNS-SD service" - msgstr "Укини регистрацију DNS-SD услуге" - --#: src/resolve/org.freedesktop.resolve1.policy.in:34 -+#: src/resolve/org.freedesktop.resolve1.policy:34 - msgid "Authentication is required to unregister a DNS-SD service" - msgstr "" - "Потребно је да се идентификујете да бисте укинули регистрацију DNS-SD услуге" - --#: src/timedate/org.freedesktop.timedate1.policy.in:22 -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Потребно је да се идентификујете да бисте поставили подешавања системске " -+"тастатуре." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Постави системско време" - --#: src/timedate/org.freedesktop.timedate1.policy.in:23 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "Потребно је да се идентификујете да бисте поставили системско време." - --#: src/timedate/org.freedesktop.timedate1.policy.in:33 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Постави системску временску зону" - --#: src/timedate/org.freedesktop.timedate1.policy.in:34 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "" - "Потребно је да се идентификујете да бисте поставили системску временску зону." - --#: src/timedate/org.freedesktop.timedate1.policy.in:43 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "" - "Постави часовник реалног времена на локалну временску зону или UTC зону" - --#: src/timedate/org.freedesktop.timedate1.policy.in:44 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -622,11 +978,11 @@ msgstr "" - "Потребно је да се идентификујете да бисте подесили да ли RTC чува локално " - "или UTC време." - --#: src/timedate/org.freedesktop.timedate1.policy.in:54 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Укључи или искључи усклађивање времена са мреже" - --#: src/timedate/org.freedesktop.timedate1.policy.in:55 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -634,43 +990,79 @@ msgstr "" - "Потребно је да се идентификујете да бисте подесили да ли се време усклађује " - "са мреже." - --#: src/core/dbus-unit.c:496 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Потребно је да се идентификујете да бисте покренули „$(unit)“." - --#: src/core/dbus-unit.c:497 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Потребно је да се идентификујете да бисте зауставили „$(unit)“." - --#: src/core/dbus-unit.c:498 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Потребно је да се идентификујете да бисте поново учитали „$(unit)“." - --#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Потребно је да се идентификујете да бисте поново покренули „$(unit)“." - --#: src/core/dbus-unit.c:607 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Потребно је да се идентификујете да бисте убили „$(unit)“." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "" -+"Потребно је да се идентификујете да бисте поставили својства за „$(unit)“." - --#: src/core/dbus-unit.c:638 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Потребно је да се идентификујете да бисте поново поставили „неуспешно“ стање " - "за „$(unit)“." - --#: src/core/dbus-unit.c:671 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "" - "Потребно је да се идентификујете да бисте поставили својства за „$(unit)“." - --msgid "Press Ctrl+C to cancel all filesystem checks in progress" -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"Потребно је да се идентификујете да бисте поново поставили „неуспешно“ стање " -+"за „$(unit)“." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." - msgstr "" --"Притисните Ctrl+C да бисте прекинули све текуће провере система датотека" -+"Потребно је да се идентификујете да бисте поново поставили „неуспешно“ стање " -+"за „$(unit)“." - --msgid "Checking in progress on %d disk (%3.1f%% complete)" --msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" --msgstr[0] "Провера у току на %d диску (%3.1f%% готово)" --msgstr[1] "Провера у току на %d диска (%3.1f%% готово)" --msgstr[2] "Провера у току на %d дискова (%3.1f%% готово)" -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "" -+#~ "Потребно је да се идентификујете да бисте зауставили систем иако програм " -+#~ "тражи да се спречи заустављање система." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Потребно је да се идентификујете да бисте убили „$(unit)“." -+ -+#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" -+#~ msgstr "" -+#~ "Притисните Ctrl+C да бисте прекинули све текуће провере система датотека" -+ -+#~ msgid "Checking in progress on %d disk (%3.1f%% complete)" -+#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" -+#~ msgstr[0] "Провера у току на %d диску (%3.1f%% готово)" -+#~ msgstr[1] "Провера у току на %d диска (%3.1f%% готово)" -+#~ msgstr[2] "Провера у току на %d дискова (%3.1f%% готово)" -diff --git a/po/sv.po b/po/sv.po -index c8bd2ae..8148c6b 100644 ---- a/po/sv.po -+++ b/po/sv.po -@@ -4,54 +4,56 @@ - # Sebastian Rasmussen , 2015. - # Andreas Henriksson , 2016. - # Josef Andersson , 2015, 2017. -+# Göran Uddeborg , 2020. - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2017-03-01 15:50+0000\n" --"PO-Revision-Date: 2017-03-19 21:18+0100\n" --"Last-Translator: Josef Andersson \n" --"Language-Team: Swedish\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" -+"PO-Revision-Date: 2020-08-27 02:46+0000\n" -+"Last-Translator: Göran Uddeborg \n" -+"Language-Team: Swedish \n" - "Language: sv\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" --"Plural-Forms: nplurals=2; plural=(n != 1);\n" --"X-Generator: Poedit 1.8.9\n" -+"Plural-Forms: nplurals=2; plural=n != 1;\n" -+"X-Generator: Weblate 4.2.1\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "Skicka tillbaka lösenfras till system" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "" - "Autentisering krävs för att skicka tillbaka den angivna lösenfrasen till " - "systemet." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "Hantera systemtjänster eller andra enheter" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" - "Autentisering krävs för att hantera systemtjänster eller andra enheter." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "Hantera systemtjänster eller enhetsfiler" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "Autentisering krävs för att hantera systemtjänster eller enhetsfiler." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "Ställ in eller ta bort miljövariabler för system- och servicehanterare" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." -@@ -59,27 +61,93 @@ msgstr "" - "Autentisering krävs för att ställa in eller ta bort miljövariabler för " - "system- och servicehanterare." - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "Läs om tillståndet för systemd" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "Autentisering krävs för att läsa om tillståndet för systemd." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "Autentisering krävs för att läsa om tillståndet för systemd." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "Autentisering krävs för att läsa om tillståndet för systemd." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Autentisering krävs för att hantera aktiva sessioner, användare och platser." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "Autentisering krävs för att binda en enhet till en plats." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Autentisering krävs för att ställa in ett väggmeddelande" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Autentisering krävs för att hantera aktiva sessioner, användare och platser." -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Ange värdnamn" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "Autentisering krävs för att ställa in lokalt värdnamn." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "Ange statiskt värdnamn" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." -@@ -87,100 +155,110 @@ msgstr "" - "Autentisering krävs för att ställa in det statiskt konfigurerade lokala " - "värdnamnet såväl som det stiliga värdnamnet." - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "Ställa in datorinformation" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "Autentisering krävs för att ställa in lokal datorinformation." - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "Autentisering krävs för att läsa om tillståndet för \"$(unit)\"." -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "Importera en VM eller behållaravbildning" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "Autentisering krävs för att importera en VM eller behållaravbildning" - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "Exportera en VM eller behållaravbildning" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "Autentisering krävs för att exportera en VM eller behållaravbildning" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "Hämta ner en VM eller behållaravbildning" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "Autentisering krävs för att hämta ner en VM eller behållaravbildning" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "Ange systemlokal" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "Autentisering krävs för att ställa in systemlokal." - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "Ange systeminställningar för tangentbord" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" - "Autentisering krävs för att ställa in systeminställningar för tangentbord." - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "Tillåt program att hindra systemavstängning" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" - "Autentisering krävs för att tillåta ett program att hindra systemavstängning." - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "Tillåt program att fördröja systemavstängning" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" - "Autentisering krävs för att tillåta ett program att fördröja " - "systemavstängning." - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "Tillåt program att hindra system att försättas i viloläge" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" - "Autentisering krävs för att tillåta ett program att hindra ett system att " - "försättas i viloläge." - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "Tillåt program att fördröja att system försätts i viloläge" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" - "Autentisering krävs för att tillåta ett program att fördröja ett system att " - "försättas i viloläge." - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "Tillåt program att hindra automatiskt systemvänteläge" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." -@@ -188,11 +266,11 @@ msgstr "" - "Autentisering krävs för att tillåta ett program att hindra automatiskt " - "systemvänteläge." - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "Tillåt program att hindra systemhantering av strömknappen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." -@@ -200,11 +278,11 @@ msgstr "" - "Autentisering krävs för att tillåta ett program att hindra systemhantering " - "av strömknappen." - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "Tillåt program att hindra systemhantering av väntelägesknappen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." -@@ -212,11 +290,11 @@ msgstr "" - "Autentisering krävs för att tillåta ett program att hindra systemhantering " - "av väntelägesknappen." - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "Tillåt program att hindra systemhantering av vilolägesknappen" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." -@@ -224,11 +302,11 @@ msgstr "" - "Autentisering krävs för att tillåta ett program att hindra systemhantering " - "av vilolägesknappen." - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "Tillåt program att hindra systemhantering av växel för datorhölje" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." -@@ -236,55 +314,54 @@ msgstr "" - "Autentisering krävs för att tillåta ett program att hindra systemhantering " - "av brytaren för datorhöljet." - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" - msgstr "Tillåt ej inloggad användare att köra program" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" - "Uttrycklig begäran krävs för att köra program som en icke inloggad användare." - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "Tillåt ej inloggade användare att köra program" - --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" - "Autentisering krävs för att köra program som en icke inloggad användare." - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "Tillåt att binda enheter till platser" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "Autentisering krävs för att binda en enhet till en plats." - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "Töm bindningar för enhet-till-plats" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Autentisering krävs för att återställa hur enheter är bundna till platser." - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "Stäng av systemet" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "Autentisering krävs för att stänga av systemet." - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "Stäng av systemet medan andra användare är inloggade" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." -@@ -292,94 +369,99 @@ msgstr "" - "Autentisering krävs för att stänga av systemet medan andra användare är " - "inloggade." - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "Stäng av systemet även då ett program hindrar det" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Autentisering krävs för att stänga av systemet även då ett program hindrar " - "det." - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "Starta om systemet" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "Autentisering krävs för att starta om systemet." - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "Starta om systemet medan andra användare är inloggade" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Autentisering krävs för att starta om systemet medan andra användare är " - "inloggade." - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "Starta om systemet även då ett program hindrar det" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Autentisering krävs för att starta om systemet även då ett program hindrar " - "det." - --#: src/login/org.freedesktop.login1.policy.in:224 -+#: src/login/org.freedesktop.login1.policy:224 - msgid "Halt the system" - msgstr "Stoppa systemet" - --#: src/login/org.freedesktop.login1.policy.in:225 -+#: src/login/org.freedesktop.login1.policy:225 - msgid "Authentication is required to halt the system." - msgstr "Autentisering krävs för att stoppa systemet." - --#: src/login/org.freedesktop.login1.policy.in:235 -+#: src/login/org.freedesktop.login1.policy:235 - msgid "Halt the system while other users are logged in" - msgstr "Stoppa systemet medan andra användare är inloggade" - --#: src/login/org.freedesktop.login1.policy.in:236 -+#: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "" - "Autentisering krävs för att stoppa systemet medan andra användare är " - "inloggade." - --#: src/login/org.freedesktop.login1.policy.in:246 -+#: src/login/org.freedesktop.login1.policy:246 - msgid "Halt the system while an application is inhibiting this" - msgstr "Stoppa systemet även då ett program hindrar det" - --#: src/login/org.freedesktop.login1.policy.in:247 -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." -+"Authentication is required to halt the system while an application is " -+"inhibiting this." - msgstr "" --"Autentisering krävs för att stoppa systemet även då ett program hindrar det." -+"Autentisering krävs för att försätta ett program i viloläge även då ett " -+"program hindrar det." - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "Försätt system i vänteläge" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "Autentisering krävs för att försätta system i vänteläge." - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "Försätt systemet i vänteläge medan andra användare är inloggade" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." -@@ -387,31 +469,31 @@ msgstr "" - "Autentisering krävs för att försätta systemet i vänteläge medan andra " - "användare är inloggade." - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "Försätt systemet i vänteläge även då ett program hindrar det" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Autentisering krävs för att försätta ett program i vänteläge även då ett " - "program hindrar det." - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "Försätt systemet i viloläge" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "Autentisering krävs för att försätta systemet i viloläge." - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "Försätt systemet i viloläge medan andra användare är inloggade" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." -@@ -419,42 +501,53 @@ msgstr "" - "Autentisering krävs för att försätta systemet i viloläge medan andra " - "användare är inloggade." - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "Försätt systemet i viloläge även då ett program hindrar det" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Autentisering krävs för att försätta ett program i viloläge även då ett " - "program hindrar det." - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "Hantera aktiva sessioner, användare och platser" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Autentisering krävs för att hantera aktiva sessioner, användare och platser." - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "Lås eller lås upp aktiva sessioner" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "Autentisering krävs för att låsa eller låsa upp aktiva sessioner." - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Autentisering krävs för att ställa in systemets tidszon." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "" - "Tillåt indikering till firmware att starta upp i inställningsgränssnitt" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -462,82 +555,124 @@ msgstr "" - "Autentisering krävs för att indikera till firmware att starta upp till " - "inställningsgränssnitt." - --#: ../src/login/org.freedesktop.login1.policy.in.h:57 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Autentisering krävs för att indikera till firmware att starta upp till " -+"inställningsgränssnitt." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Autentisering krävs för att indikera till firmware att starta upp till " -+"inställningsgränssnitt." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Ange ett väggmeddelande" - --#: ../src/login/org.freedesktop.login1.policy.in.h:58 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Autentisering krävs för att ställa in ett väggmeddelande" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to halt the system." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Autentisering krävs för att stoppa systemet." -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "Logga in i en lokal behållare" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." --msgstr "Autentisering krävs för att logga in i en lokal behållare" -+msgstr "Autentisering krävs för att logga in i en lokal behållare." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "Logga in på en lokal värd" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." --msgstr "Autentisering krävs för att logga in på den lokala värden" -+msgstr "Autentisering krävs för att logga in på den lokala värden." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "Förvärva en kommandotolk i en lokal behållare" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" - "Autentisering krävs för att förvärva en kommandotolk i en lokal behållare." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "Förvärva en kommandotolk på den lokala värden" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "" - "Autentisering krävs för att förvärva en kommandotolk på den lokala värden." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "Förvärva en pseudo TTY i en lokal behållare" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" --"Autentisering krävs för att förvärva en pseudo TTY i en lokal behållare" -+"Autentisering krävs för att förvärva en pseudo TTY i en lokal behållare." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "Förvärva en pseudo TTY på den lokala värden" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "" - "Autentisering krävs för att förvärva en pseudo TTY på den lokala värden." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "Hantera lokala virtuella maskiner och behållare" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" - "Autentisering krävs för att hantera lokala virtuella maskiner och behållare." - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "Hantera lokala virtuella maskin- och behållaravbildningar" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." -@@ -545,29 +680,258 @@ msgstr "" - "Autentisering krävs för att hantera lokala virtuella maskin- och " - "behållaravbildningar." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Autentisering krävs för ställa in systemtiden." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "Autentisering krävs för ställa in systemtiden." -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "Autentisering krävs för att stoppa \"$(unit)\"." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Autentisering krävs för att ställa in lokalt värdnamn." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Autentisering krävs för att försätta systemet i viloläge." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Autentisering krävs för att logga in på den lokala värden" -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Autentisering krävs för att ställa in lokalt värdnamn." -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Autentisering krävs för att försätta systemet i viloläge." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Autentisering krävs för att ställa in systemlokal." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Autentisering krävs för ställa in systemtiden." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Autentisering krävs för ställa in systemtiden." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Autentisering krävs för att ställa in ett väggmeddelande" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Autentisering krävs för att ställa in ett väggmeddelande" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "Autentisering krävs för att läsa om tillståndet för systemd." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Autentisering krävs för att starta om systemet." -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "Autentisering krävs för att importera en VM eller behållaravbildning" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "Autentisering krävs för att binda en enhet till en plats." -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "Autentisering krävs för att hämta ner en VM eller behållaravbildning" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "Autentisering krävs för att ställa in ett väggmeddelande" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "Autentisering krävs för att ställa in ett väggmeddelande" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+"Autentisering krävs för att ställa in systeminställningar för tangentbord." -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Ange systemtid" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "Autentisering krävs för ställa in systemtiden." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "Ange systemets tidszon" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "Autentisering krävs för att ställa in systemets tidszon." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "" - "Sätt realtidsklocka (RTC) till lokal tidszon eller koordinerad universell " - "tid (UTC)" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." -@@ -575,11 +939,11 @@ msgstr "" - "Autentisering krävs för att kunna kontrollera huruvida realtidsklockan (RTC) " - "lagrar den lokala eller koordinerade universella tiden (UTC)." - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "Växla synkronisering av nätverkstid på och av" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." -@@ -587,36 +951,71 @@ msgstr "" - "Autentisering krävs för att kontrollera huruvida synkronisering av " - "nätverkstid ska vara aktiverat." - --#: ../src/core/dbus-unit.c:457 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "Autentisering krävs för att starta \"$(unit)\"." - --#: ../src/core/dbus-unit.c:458 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "Autentisering krävs för att stoppa \"$(unit)\"." - --#: ../src/core/dbus-unit.c:459 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "Autentisering krävs för att läsa om tillståndet för \"$(unit)\"." - --#: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "Autentisering krävs för att starta om \"$(unit)\"." - --#: ../src/core/dbus-unit.c:568 --msgid "Authentication is required to kill '$(unit)'." --msgstr "Autentisering krävs för att döda \"$(unit)\"." -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "Autentisering krävs för att ställa in egenskaper på \"$(unit)\"." - --#: ../src/core/dbus-unit.c:599 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "Autentisering krävs för att återställa det \"fallerade\" tillståndet för " - "\"$(unit)\"." - --#: ../src/core/dbus-unit.c:632 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "Autentisering krävs för att ställa in egenskaper på \"$(unit)\"." - -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"Autentisering krävs för att återställa det \"fallerade\" tillståndet för " -+"\"$(unit)\"." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Autentisering krävs för att återställa det \"fallerade\" tillståndet för " -+"\"$(unit)\"." -+ -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "" -+#~ "Autentisering krävs för att stoppa systemet även då ett program hindrar " -+#~ "det." -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "Autentisering krävs för att döda \"$(unit)\"." -+ - #~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" - #~ msgstr "Tryck Ctrl+C för att avbryta alla pågående filsystemskontroller." - -diff --git a/po/systemd.pot b/po/systemd.pot -new file mode 100644 -index 0000000..76fa72e ---- /dev/null -+++ b/po/systemd.pot -@@ -0,0 +1,841 @@ -+# SOME DESCRIPTIVE TITLE. -+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -+# This file is distributed under the same license as the systemd package. -+# FIRST AUTHOR , YEAR. -+# -+#, fuzzy -+msgid "" -+msgstr "" -+"Project-Id-Version: systemd\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" -+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -+"Last-Translator: FULL NAME \n" -+"Language-Team: LANGUAGE \n" -+"Language: \n" -+"MIME-Version: 1.0\n" -+"Content-Type: text/plain; charset=CHARSET\n" -+"Content-Transfer-Encoding: 8bit\n" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:22 -+msgid "Send passphrase back to system" -+msgstr "" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:23 -+msgid "" -+"Authentication is required to send the entered passphrase back to the system." -+msgstr "" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:33 -+msgid "Manage system services or other units" -+msgstr "" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:34 -+msgid "Authentication is required to manage system services or other units." -+msgstr "" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:43 -+msgid "Manage system service or unit files" -+msgstr "" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:44 -+msgid "Authentication is required to manage system service or unit files." -+msgstr "" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:54 -+msgid "Set or unset system and service manager environment variables" -+msgstr "" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:55 -+msgid "" -+"Authentication is required to set or unset system and service manager " -+"environment variables." -+msgstr "" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:64 -+msgid "Reload the systemd state" -+msgstr "" -+ -+#: src/core/org.freedesktop.systemd1.policy.in:65 -+msgid "Authentication is required to reload the systemd state." -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+msgid "Authentication is required to create a user's home area." -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+msgid "Authentication is required to remove a user's home area." -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+msgid "Authentication is required to resize a user's home area." -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 -+msgid "Set hostname" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:21 -+msgid "Authentication is required to set the local hostname." -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:30 -+msgid "Set static hostname" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:31 -+msgid "" -+"Authentication is required to set the statically configured local hostname, " -+"as well as the pretty hostname." -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:41 -+msgid "Set machine information" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:42 -+msgid "Authentication is required to set local machine information." -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+msgid "Authentication is required to get product UUID." -+msgstr "" -+ -+#: src/import/org.freedesktop.import1.policy:22 -+msgid "Import a VM or container image" -+msgstr "" -+ -+#: src/import/org.freedesktop.import1.policy:23 -+msgid "Authentication is required to import a VM or container image" -+msgstr "" -+ -+#: src/import/org.freedesktop.import1.policy:32 -+msgid "Export a VM or container image" -+msgstr "" -+ -+#: src/import/org.freedesktop.import1.policy:33 -+msgid "Authentication is required to export a VM or container image" -+msgstr "" -+ -+#: src/import/org.freedesktop.import1.policy:42 -+msgid "Download a VM or container image" -+msgstr "" -+ -+#: src/import/org.freedesktop.import1.policy:43 -+msgid "Authentication is required to download a VM or container image" -+msgstr "" -+ -+#: src/locale/org.freedesktop.locale1.policy:22 -+msgid "Set system locale" -+msgstr "" -+ -+#: src/locale/org.freedesktop.locale1.policy:23 -+msgid "Authentication is required to set the system locale." -+msgstr "" -+ -+#: src/locale/org.freedesktop.locale1.policy:33 -+msgid "Set system keyboard settings" -+msgstr "" -+ -+#: src/locale/org.freedesktop.locale1.policy:34 -+msgid "Authentication is required to set the system keyboard settings." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:22 -+msgid "Allow applications to inhibit system shutdown" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:23 -+msgid "" -+"Authentication is required for an application to inhibit system shutdown." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:33 -+msgid "Allow applications to delay system shutdown" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:34 -+msgid "Authentication is required for an application to delay system shutdown." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:44 -+msgid "Allow applications to inhibit system sleep" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:45 -+msgid "Authentication is required for an application to inhibit system sleep." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:55 -+msgid "Allow applications to delay system sleep" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:56 -+msgid "Authentication is required for an application to delay system sleep." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:65 -+msgid "Allow applications to inhibit automatic system suspend" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:66 -+msgid "" -+"Authentication is required for an application to inhibit automatic system " -+"suspend." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:75 -+msgid "Allow applications to inhibit system handling of the power key" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:76 -+msgid "" -+"Authentication is required for an application to inhibit system handling of " -+"the power key." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:86 -+msgid "Allow applications to inhibit system handling of the suspend key" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:87 -+msgid "" -+"Authentication is required for an application to inhibit system handling of " -+"the suspend key." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:97 -+msgid "Allow applications to inhibit system handling of the hibernate key" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:98 -+msgid "" -+"Authentication is required for an application to inhibit system handling of " -+"the hibernate key." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:107 -+msgid "Allow applications to inhibit system handling of the lid switch" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:108 -+msgid "" -+"Authentication is required for an application to inhibit system handling of " -+"the lid switch." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:117 -+msgid "Allow non-logged-in user to run programs" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:118 -+msgid "Explicit request is required to run programs as a non-logged-in user." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:127 -+msgid "Allow non-logged-in users to run programs" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:128 -+msgid "Authentication is required to run programs as a non-logged-in user." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:137 -+msgid "Allow attaching devices to seats" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:138 -+msgid "Authentication is required to attach a device to a seat." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:148 -+msgid "Flush device to seat attachments" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:158 -+msgid "Power off the system" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:159 -+msgid "Authentication is required to power off the system." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:169 -+msgid "Power off the system while other users are logged in" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:170 -+msgid "" -+"Authentication is required to power off the system while other users are " -+"logged in." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:180 -+msgid "Power off the system while an application is inhibiting this" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:181 -+msgid "" -+"Authentication is required to power off the system while an application is " -+"inhibiting this." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:191 -+msgid "Reboot the system" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:192 -+msgid "Authentication is required to reboot the system." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:202 -+msgid "Reboot the system while other users are logged in" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:203 -+msgid "" -+"Authentication is required to reboot the system while other users are logged " -+"in." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:213 -+msgid "Reboot the system while an application is inhibiting this" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:214 -+msgid "" -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:224 -+msgid "Halt the system" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+msgid "Authentication is required to halt the system." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:235 -+msgid "Halt the system while other users are logged in" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:246 -+msgid "Halt the system while an application is inhibiting this" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:257 -+msgid "Suspend the system" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:258 -+msgid "Authentication is required to suspend the system." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:267 -+msgid "Suspend the system while other users are logged in" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:268 -+msgid "" -+"Authentication is required to suspend the system while other users are " -+"logged in." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:278 -+msgid "Suspend the system while an application is inhibiting this" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:279 -+msgid "" -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:289 -+msgid "Hibernate the system" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:290 -+msgid "Authentication is required to hibernate the system." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:299 -+msgid "Hibernate the system while other users are logged in" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:300 -+msgid "" -+"Authentication is required to hibernate the system while other users are " -+"logged in." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:310 -+msgid "Hibernate the system while an application is inhibiting this" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:311 -+msgid "" -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:321 -+msgid "Manage active sessions, users and seats" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:331 -+msgid "Lock or unlock active sessions" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:332 -+msgid "Authentication is required to lock or unlock active sessions." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:352 -+msgid "Indicate to the firmware to boot to setup interface" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:353 -+msgid "" -+"Authentication is required to indicate to the firmware to boot to setup " -+"interface." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:385 -+msgid "Set a wall message" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:386 -+msgid "Authentication is required to set a wall message" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+msgid "Authentication is required to change the virtual terminal." -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:22 -+msgid "Log into a local container" -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:23 -+msgid "Authentication is required to log into a local container." -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:32 -+msgid "Log into the local host" -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:33 -+msgid "Authentication is required to log into the local host." -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:42 -+msgid "Acquire a shell in a local container" -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:43 -+msgid "Authentication is required to acquire a shell in a local container." -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:53 -+msgid "Acquire a shell on the local host" -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:54 -+msgid "Authentication is required to acquire a shell on the local host." -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:64 -+msgid "Acquire a pseudo TTY in a local container" -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:65 -+msgid "" -+"Authentication is required to acquire a pseudo TTY in a local container." -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:74 -+msgid "Acquire a pseudo TTY on the local host" -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:75 -+msgid "Authentication is required to acquire a pseudo TTY on the local host." -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:84 -+msgid "Manage local virtual machines and containers" -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:85 -+msgid "" -+"Authentication is required to manage local virtual machines and containers." -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:95 -+msgid "Manage local virtual machine and container images" -+msgstr "" -+ -+#: src/machine/org.freedesktop.machine1.policy:96 -+msgid "" -+"Authentication is required to manage local virtual machine and container " -+"images." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+msgid "Authentication is required to set NTP servers." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+msgid "Authentication is required to set DNS servers." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+msgid "Authentication is required to set domains." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+msgid "Authentication is required to set default route." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+msgid "Authentication is required to reset NTP settings." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+msgid "Authentication is required to reset DNS settings." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+msgid "Authentication is required to send force renew message." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+msgid "Authentication is required to reload network settings." -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+msgid "Authentication is required to reconfigure network interface." -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+msgid "Authentication is required to inspect a portable service image." -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:24 -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+msgid "Authentication is required to reset name resolution settings." -+msgstr "" -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 -+msgid "Set system time" -+msgstr "" -+ -+#: src/timedate/org.freedesktop.timedate1.policy:23 -+msgid "Authentication is required to set the system time." -+msgstr "" -+ -+#: src/timedate/org.freedesktop.timedate1.policy:33 -+msgid "Set system timezone" -+msgstr "" -+ -+#: src/timedate/org.freedesktop.timedate1.policy:34 -+msgid "Authentication is required to set the system timezone." -+msgstr "" -+ -+#: src/timedate/org.freedesktop.timedate1.policy:43 -+msgid "Set RTC to local timezone or UTC" -+msgstr "" -+ -+#: src/timedate/org.freedesktop.timedate1.policy:44 -+msgid "" -+"Authentication is required to control whether the RTC stores the local or " -+"UTC time." -+msgstr "" -+ -+#: src/timedate/org.freedesktop.timedate1.policy:53 -+msgid "Turn network time synchronization on or off" -+msgstr "" -+ -+#: src/timedate/org.freedesktop.timedate1.policy:54 -+msgid "" -+"Authentication is required to control whether network time synchronization " -+"shall be enabled." -+msgstr "" -+ -+#: src/core/dbus-unit.c:362 -+msgid "Authentication is required to start '$(unit)'." -+msgstr "" -+ -+#: src/core/dbus-unit.c:363 -+msgid "Authentication is required to stop '$(unit)'." -+msgstr "" -+ -+#: src/core/dbus-unit.c:364 -+msgid "Authentication is required to reload '$(unit)'." -+msgstr "" -+ -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 -+msgid "Authentication is required to restart '$(unit)'." -+msgstr "" -+ -+#: src/core/dbus-unit.c:538 -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "" -+ -+#: src/core/dbus-unit.c:569 -+msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgstr "" -+ -+#: src/core/dbus-unit.c:602 -+msgid "Authentication is required to set properties on '$(unit)'." -+msgstr "" -+ -+#: src/core/dbus-unit.c:711 -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+ -+#: src/core/dbus-unit.c:760 -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -diff --git a/po/tr.po b/po/tr.po -index b2af9e9..cb95c7e 100644 ---- a/po/tr.po -+++ b/po/tr.po -@@ -4,21 +4,22 @@ - # Necdet Yücel , 2014. - # Gökhan Gurbetoğlu , 2015. - # Muhammet Kara , 2015, 2016, 2017, 2018. --# -+# Oğuz Ersen , 2020. - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2018-10-26 19:14+0000\n" --"PO-Revision-Date: 2018-10-31 00:12+0300\n" --"Last-Translator: Muhammet Kara \n" --"Language-Team: Turkish \n" --"Language: tr_TR\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" -+"PO-Revision-Date: 2020-08-24 07:29+0000\n" -+"Last-Translator: Oğuz Ersen \n" -+"Language-Team: Turkish \n" -+"Language: tr\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" - "Plural-Forms: nplurals=1; plural=0;\n" --"X-Generator: Gtranslator 2.91.7\n" -+"X-Generator: Weblate 4.2.1\n" - - #: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" -@@ -69,6 +70,75 @@ msgstr "systemd durumunu yeniden yükle" - msgid "Authentication is required to reload the systemd state." - msgstr "systemd durumunu yeniden yüklemek kimlik doğrulaması gerektiriyor." - -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "systemd durumunu yeniden yüklemek kimlik doğrulaması gerektiriyor." -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "systemd durumunu yeniden yüklemek kimlik doğrulaması gerektiriyor." -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to attach or detach a portable service image." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "" -+"Bir taşınabilir hizmet kalıbını tutturmak ya da ayırmak için kimlik " -+"doğrulaması gereklidir." -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "" -+"Bir aygıtın yuvaya takılmasına izin vermek kimlik doğrulaması gerektiriyor." -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "" -+"Aktif oturumları, kullanıcıları ve yuvaları yönetmek için kimlik doğrulaması " -+"gereklidir." -+ - #: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "Makine adını ayarla" -@@ -163,17 +233,17 @@ msgstr "" - - #: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" --msgstr "Uygulamaların sistemin kapanmasını geciktirmelerine izin ver" -+msgstr "Uygulamaların sistemin kapanmasını ertelemesine izin ver" - - #: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" --"Bir uygulamanın sistemin kapanmasını geciktirmesi için kimlik doğrulaması " -+"Bir uygulamanın sistemin kapanmasını ertelemesi için kimlik doğrulaması " - "gereklidir." - - #: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" --msgstr "Uygulamaların sistemin beklemeye geçmesini engellemesine izin ver" -+msgstr "Uygulamaların sistemin uykuya geçmesini engellemesine izin ver" - - #: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." -@@ -183,18 +253,19 @@ msgstr "" - - #: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" --msgstr "Uygulamaların sistemin beklemeye geçmesini ertelemesine izin ver" -+msgstr "Uygulamaların sistemin uykuya geçmesini ertelemesine izin ver" - - #: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" --"Bir uygulamanın sistemin uykuya geçmesini geciktirmesi için kimlik " --"doğrulaması gereklidir." -+"Bir uygulamanın sistemin uykuya geçmesini ertelemesi için kimlik doğrulaması " -+"gereklidir." - - #: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "" --"Uygulamaların sistemin otomatik bekletmeye geçmesini engellemesine izin ver" -+"Uygulamaların sistemin otomatik olarak askıya alınmasını engellemesine izin " -+"ver" - - #: src/login/org.freedesktop.login1.policy:66 - msgid "" -@@ -232,8 +303,8 @@ msgstr "" - #: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" --"Uygulamaların sistemin uykuya geçme tuşunun kullanımını engellemesine izin " --"ver" -+"Uygulamaların sistemin hazırda bekletme tuşunun kullanımını engellemesine " -+"izin ver" - - #: src/login/org.freedesktop.login1.policy:98 - msgid "" -@@ -290,8 +361,7 @@ msgid "Flush device to seat attachments" - msgstr "Aygıtın yuvaya eklenmesini sıfırla" - - #: src/login/org.freedesktop.login1.policy:149 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "" - "Aygıtların yuvalara nasıl takıldığını sıfırlamak kimlik doğrulama " - "gerektiriyor." -@@ -322,8 +392,8 @@ msgstr "Bir uygulama engellenmesini isterken sistemi kapat" - - #: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "" - "Bir uygulama engellenmesini isterken sistemi kapatmak kimlik doğrulaması " - "gerektiriyor." -@@ -342,8 +412,8 @@ msgstr "Diğer kullanıcılar oturum açmışken sistemi yeniden başlat" - - #: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "" - "Diğer kullanıcılar oturum açmışken sistemi yeniden başlatmak kimlik " - "doğrulaması gerektiriyor." -@@ -354,8 +424,8 @@ msgstr "Bir uygulama engellenmesini isterken sistemi yeniden başlat" - - #: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "" - "Bir uygulama engellenmesini isterken sistemi yeniden başlatmak kimlik " - "doğrulaması gerektiriyor." -@@ -374,8 +444,8 @@ msgstr "Diğer kullanıcılar oturum açmışken sistemi durdur" - - #: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "" - "Diğer kullanıcılar oturum açmışken sistemi durdurmak kimlik doğrulaması " - "gerektiriyor." -@@ -385,12 +455,16 @@ msgid "Halt the system while an application is inhibiting this" - msgstr "Bir uygulama engellenmesini isterken sistemi durdur" - - #: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." -+"Authentication is required to halt the system while an application is " -+"inhibiting this." - msgstr "" --"Bir uygulama engellenmesini isterken sistemi durdurmak kimlik doğrulaması " --"gerektiriyor." -+"Bir uygulama engellenmesini isterken sistemi hazırda bekletmek kimlik " -+"doğrulaması gerektiriyor." - - #: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" -@@ -418,8 +492,8 @@ msgstr "Bir uygulama engellenmesini isterken sistemi askıya al" - - #: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "" - "Bir uygulama engellenmesini isterken sistemi askıya almak kimlik doğrulaması " - "gerektiriyor." -@@ -450,8 +524,8 @@ msgstr "Bir uygulama engellenmesini isterken sistemi hazırda beklet" - - #: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "" - "Bir uygulama engellenmesini isterken sistemi hazırda bekletmek kimlik " - "doğrulaması gerektiriyor." -@@ -461,8 +535,7 @@ msgid "Manage active sessions, users and seats" - msgstr "Aktif oturumları, kullanıcıları ve yuvaları yönet" - - #: src/login/org.freedesktop.login1.policy:322 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" - "Aktif oturumları, kullanıcıları ve yuvaları yönetmek için kimlik doğrulaması " - "gereklidir." -@@ -478,11 +551,23 @@ msgstr "" - "doğrulaması gereklidir." - - #: src/login/org.freedesktop.login1.policy:341 --msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Set the reboot \"reason\" in the kernel" - msgstr "" --"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesine izin ver" - - #: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "Sistem zaman dilimini ayarlamak kimlik doğrulaması gerektiriyor." -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" -+msgstr "" -+"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesine izin ver" -+ -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." -@@ -490,17 +575,59 @@ msgstr "" - "Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesi için kimlik " - "doğrulaması gereklidir." - --#: src/login/org.freedesktop.login1.policy:351 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "" -+"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesi için kimlik " -+"doğrulaması gereklidir." -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "" -+"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesi için kimlik " -+"doğrulaması gereklidir." -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "Bir duvar mesajı ayarla" - --#: src/login/org.freedesktop.login1.policy:352 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir" - -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to halt the system." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "Sistemi durdurmak kimlik doğrulaması gerektiriyor." -+ - #: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" --msgstr "Yerel kapsayıcıya giriş yap" -+msgstr "Yerel kapsayıcıda oturum aç" - - #: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." -@@ -508,7 +635,7 @@ msgstr "Yerel kapsayıcıda oturum açmak için kimlik doğrulaması gereklidir. - - #: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" --msgstr "Yerel (ana) makineye giriş yap" -+msgstr "Yerel (ana) makinede oturum aç" - - #: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." -@@ -576,6 +703,174 @@ msgstr "" - "Yerel sanal makineler ve kapsayıcı kalıplarını yönetmek için kimlik " - "doğrulaması gereklidir." - -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "Sistem zamanını ayarlamak kimlik doğrulaması gerektiriyor." -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+#, fuzzy -+#| msgid "Register a DNS-SD service" -+msgid "Set DNS servers" -+msgstr "Bir DNS-SD hizmeti kaydet" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to set DNS servers." -+msgstr "Bir DNS-SD hizmeti kaydetmek için kimlik doğrulaması gereklidir" -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "'$(unit)' durdurmak için kimlik doğrulaması gereklidir." -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "Yerel makine adını ayarlamak kimlik doğrulaması gerektiriyor." -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "Sistemi hazırda bekletmek kimlik doğrulaması gerektiriyor." -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to get product UUID." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "Ürün UUID'ini almak için kimlik doğrulaması gereklidir." -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to register a DNS-SD service" -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "Bir DNS-SD hizmeti kaydetmek için kimlik doğrulaması gereklidir" -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "Sistemi hazırda bekletmek kimlik doğrulaması gerektiriyor." -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "Sistem yerelini ayarlamak kimlik doğrulaması gerektiriyor." -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "Sistem zamanını ayarlamak kimlik doğrulaması gerektiriyor." -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "Sistem zamanını ayarlamak kimlik doğrulaması gerektiriyor." -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "systemd durumunu yeniden yüklemek kimlik doğrulaması gerektiriyor." -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "Sistemi yeniden başlatmak kimlik doğrulaması gerektiriyor." -+ - #: src/portable/org.freedesktop.portable1.policy:13 - msgid "Inspect a portable service image" - msgstr "Bir taşınabilir hizmet kalıbını incele" -@@ -624,6 +919,16 @@ msgid "Authentication is required to unregister a DNS-SD service" - msgstr "" - "Bir DNS-SD hizmetinin kaydını silmek için kimlik doğrulaması gereklidir" - -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "Sistem klavye ayarlarını ayarlamak kimlik doğrulaması gerektiriyor." -+ - #: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "Sistem zamanını ayarla" -@@ -660,27 +965,25 @@ msgstr "Ağ zaman eş zamanlamasını aç veya kapat" - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." --msgstr "" --"Ağ zaman eş zamanlamasını kontrol etmek kimlik doğrulaması gerektiriyor." -+msgstr "Ağ zaman eş zamanlamasını denetlemek kimlik doğrulaması gerektiriyor." - --#: src/core/dbus-unit.c:326 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "'$(unit)' başlatmak için kimlik doğrulaması gereklidir." - --#: src/core/dbus-unit.c:327 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "'$(unit)' durdurmak için kimlik doğrulaması gereklidir." - --#: src/core/dbus-unit.c:328 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "'$(unit)' yeniden yüklemek için kimlik doğrulaması gereklidir." - --#: src/core/dbus-unit.c:329 src/core/dbus-unit.c:330 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "'$(unit)' yeniden başlatmak için kimlik doğrulaması gereklidir." - --#: src/core/dbus-unit.c:437 --#| msgid "Authentication is required to set properties on '$(unit)'." -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." -@@ -688,17 +991,46 @@ msgstr "" - "'$(unit)' süreçlerine bir UNIX sinyali göndermek için kimlik doğrulaması " - "gereklidir." - --#: src/core/dbus-unit.c:468 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "" - "'$(unit)'in \"failed\" (başarısız) durumunu sıfırlamak için kimlik " - "doğrulaması gereklidir." - --#: src/core/dbus-unit.c:501 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "" - "'$(unit)' üzerindeki özellikleri ayarlamak için kimlik doğrulaması " - "gereklidir." - -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "" -+"'$(unit)'in \"failed\" (başarısız) durumunu sıfırlamak için kimlik " -+"doğrulaması gereklidir." -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to send a UNIX signal to the processes of " -+#| "'$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"'$(unit)' süreçlerine bir UNIX sinyali göndermek için kimlik doğrulaması " -+"gereklidir." -+ -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "" -+#~ "Bir uygulama engellenmesini isterken sistemi durdurmak kimlik doğrulaması " -+#~ "gerektiriyor." -+ - #~ msgid "Authentication is required to kill '$(unit)'." - #~ msgstr "'$(unit)' sonlandırmak için kimlik doğrulaması gereklidir." -diff --git a/po/uk.po b/po/uk.po -index f0a7028..df47789 100644 ---- a/po/uk.po -+++ b/po/uk.po -@@ -6,69 +6,70 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd master\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2020-03-22 04:04+0000\n" --"PO-Revision-Date: 2020-03-25 18:40+0200\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" -+"PO-Revision-Date: 2020-08-29 11:29+0000\n" - "Last-Translator: Yuri Chornoivan \n" --"Language-Team: Ukrainian \n" -+"Language-Team: Ukrainian \n" - "Language: uk\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" --"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<" --"=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" --"X-Generator: Lokalize 20.03.70\n" -+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -+"X-Generator: Weblate 4.2.1\n" - - #: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" --msgstr "Надіслати пароль назад у систему" -+msgstr "Надсилання пароля назад у систему" - - #: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." --msgstr "" --"Потрібна автентифікація, щоб надіслати введений пароль назад у систему." -+msgstr "Для надсилання введеного пароля до системи слід пройти розпізнавання." - - #: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" --msgstr "Керувати системними службами й іншими одиницями systemd" -+msgstr "Керування системними службами й іншими одиницями systemd" - - #: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "" --"Потрібна автентифікація, щоб керувати системними службами й іншими одиницями " --"systemd." -+"Для керування системними службами й іншими одиницями systemd слід пройти " -+"розпізнавання." - - #: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" --msgstr "Керувати системними службами й одиницями systemd" -+msgstr "Керування системними службами й одиницями systemd" - - #: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "" --"Потрібна автентифікація, щоб керувати системними службами й одиницями " --"systemd." -+"Для керування системними службами й одиницями systemd слід пройти " -+"розпізнавання." - - #: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "" --"Встановити або забрати змінну середовища з керування службами і системою" -+"Встановлення і скасування встановлення змінних середовища для керування " -+"службами і системою" - - #: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." - msgstr "" --"Потрібна автентифікація, щоб установити або забрати змінні середовища з " --"керування службами і системою." -+"Для встановлення або скасовування встановлення змінних середовища для " -+"керування службами і системою слід пройти розпізнавання." - - #: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" --msgstr "Перезапустити стан системи" -+msgstr "Перезавантаження стану systemd" - - #: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." --msgstr "Потрібна автентифікація, щоб перезапустити стан системи." -+msgstr "Для перезавантаження стану systemd слід пройти розпізнавання." - - #: src/home/org.freedesktop.home1.policy:13 - msgid "Create a home area" -@@ -127,31 +128,31 @@ msgstr "" - - #: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" --msgstr "Встановити назву вузла" -+msgstr "Встановлення назви вузла" - - #: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." --msgstr "Потрібна автентифікація, щоб встановити назву локального вузла." -+msgstr "Для встановлення назви локального вузла слід пройти розпізнавання." - - #: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" --msgstr "Встановити статичну назву вузла" -+msgstr "Встановлення статичної назви вузла" - - #: src/hostname/org.freedesktop.hostname1.policy:31 - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." - msgstr "" --"Потрібна автентифікація, щоб вказати статично налаштовану назву локального " --"вузла, так само й форматовану." -+"Для встановлення статично налаштованої назви локального вузла і форматованої " -+"назви слід пройти розпізнавання." - - #: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" --msgstr "Встановити інформацію про машину" -+msgstr "Встановлення даних щодо машини" - - #: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." --msgstr "Потрібна автентифікація, щоб вказати локальну інформацію про машини." -+msgstr "Для встановлення даних щодо локальної машини слід пройти розпізнавання." - - #: src/hostname/org.freedesktop.hostname1.policy:51 - msgid "Get product UUID" -@@ -159,372 +160,378 @@ msgstr "Отримання UUID продукту" - - #: src/hostname/org.freedesktop.hostname1.policy:52 - msgid "Authentication is required to get product UUID." --msgstr "Потрібна автентифікація, щоб отримати UUID продукту." -+msgstr "Для отримання UUID продукту слід пройти розпізнавання." - - #: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" --msgstr "Імпортувати образ контейнера або віртуальної машини" -+msgstr "Імпортування образу контейнера або віртуальної машини" - - #: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "" --"Потрібна автентифікація, щоб імпортувати образ контейнера або віртуальної " --"машини" -+"Для імпортування образу контейнера або віртуальної машини слід пройти " -+"розпізнавання" - - #: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" --msgstr "Експортувати образ контейнера або віртуальної машини" -+msgstr "Експортування образу контейнера або віртуальної машини" - - #: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "" --"Потрібна автентифікація, щоб експортувати образ контейнера або віртуальної " --"машини" -+"Для експортування образу контейнера або віртуальної машини слід пройти " -+"розпізнавання" - - #: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" --msgstr "Звантажити образ контейнера або віртуальної машини" -+msgstr "Отримання образу контейнера або віртуальної машини" - - #: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "" --"Потрібна автентифікація, щоб звантажити образ контейнера або віртуальної " --"машини" -+"Для отримання образу контейнера або віртуальної машини слід пройти " -+"розпізнавання" - - #: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" --msgstr "Вказати системну локаль" -+msgstr "Визначення системної локалі" - - #: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." --msgstr "Потрібна автентифікація, щоб встановити системну локаль." -+msgstr "Для визначення системної локалі слід пройти розпізнавання." - - #: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" --msgstr "Вказати налаштування системної клавіатури" -+msgstr "Визначення загальносистемних параметрів клавіатури" - - #: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "" --"Потрібна автентифікація, щоб вказати налаштування системної клавіатури." -+"Для визначення загальносистемних параметрів клавіатури слід пройти " -+"розпізнавання." - - #: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" --msgstr "Дозволити програмам перешкоджати вимкненню системи" -+msgstr "Уможливлення перешкоджання вимкненню системи програмами" - - #: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "" --"Потрібна автентифікація, щоб дозволити програмам перешкоджати вимкненню " --"системи." -+"Для того, щоб уможливити програмам перешкоджання вимкненню системи, слід " -+"пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" --msgstr "Дозволити програмам затримувати вимкнення системи" -+msgstr "Уможливлення затримки вимкнення системи програмами" - - #: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "" --"Потрібна автентифікація, щоб дозволити програмам затримувати вимкнення " --"системи." -+"Для того, щоб уможливити програмам затримання вимкнення системи, слід пройти " -+"розпізнавання." - - #: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" --msgstr "Дозволити програмам перешкоджати засинанню системи" -+msgstr "Уможливлення перешкоджання присиплянню системи програмами" - - #: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "" --"Потрібна автентифікація, щоб дозволити програмам перешкоджати засинанню " --"системи." -+"Для того, щоб уможливити програмам перешкоджання присиплянню системи, слід " -+"пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" --msgstr "Дозволити програмами затримувати засинання системи" -+msgstr "Уможливлення затримання присипляння системи програмами" - - #: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "" --"Потрібна автентифікація, щоб дозволити програмам затримувати засинання " --"системи." -+"Для того, щоб уможливити програмам затримання присипляння системи, слід " -+"пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" --msgstr "Дозволити програмам перешкоджати автоматичному призупиненню системи" -+msgstr "" -+"Уможливлення перешкоджання автоматичному призупиненню системи програмами" - - #: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." - msgstr "" --"Потрібна автентифікація, щоб дозволити програмам перешкоджати автоматичному " --"призупиненню системи." -+"Для того, щоб уможливити програмам перешкоджання автоматичне призупинення " -+"роботи системи, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" --msgstr "Дозволити програмам перешкоджати обробленню системою клавіші живлення" -+msgstr "" -+"Уможливлення перешкоджання обробці системою клавіші живлення для програм" - - #: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." - msgstr "" --"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню " --"системою клавіші живлення." -+"Для того, щоб дозволити програмам перешкоджати обробленню системою клавіші " -+"живлення, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "" --"Дозволити програмам перешкоджати обробленню системою клавіші призупинення" -+"Уможливлення перешкоджання обробці системою клавіші призупинення для програм" - - #: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." - msgstr "" --"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню " --"системою клавіші призупинення." -+"Для того, щоб дозволити програмам перешкоджати обробленню системою клавіші " -+"призупинення, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "" --"Дозволити програмам перешкоджати обробленню системою клавіші присипання" -+"Уможливлення перешкоджання обробці системою клавіші присипляння для програм" - - #: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." - msgstr "" --"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню " --"системою клавіші присипання." -+"Для того, щоб дозволити програмам перешкоджати обробленню системою клавіші " -+"присипляння, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "" --"Дозволити програмам перешкоджати обробленню системою клавіші перемикання " --"кришки" -+"Уможливлення перешкоджання обробці системою перемикання кришки для програм" - - #: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." - msgstr "" --"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню " --"системою клавіші перемикання кришки." -+"Для того, щоб дозволити програмам перешкоджати обробленню системою " -+"перемикання кришки, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:117 - msgid "Allow non-logged-in user to run programs" --msgstr "Дозволити незареєстрованим користувачам запускати програми" -+msgstr "Дозвіл для незареєстрованого користувача на запуск програм" - - #: src/login/org.freedesktop.login1.policy:118 - msgid "Explicit request is required to run programs as a non-logged-in user." - msgstr "" --"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам " --"запускати програми." -+"Для того, щоб дозволити незареєстрованому користувачеві запускати програми, " -+"потрібен явний запит." - - #: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" --msgstr "Дозволити незареєстрованим користувачам запускати програми" -+msgstr "Дозвіл для незареєстрованих користувачів на запуск програм" - - #: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "" --"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам " --"запускати програми." -+"Для того, щоб дозволити незареєстрованому користувачеві запускати програми, " -+"слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" --msgstr "Дозволити під'єднання пристроїв до місць" -+msgstr "Дозвіл на під'єднання пристроїв до місць" - - #: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." --msgstr "Потрібна автентифікація, щоб під'єднувати пристрої до місць." -+msgstr "" -+"Для того, щоб під'єднувати пристрої до місць, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" --msgstr "Очисний пристрій для під'єднань до місця" -+msgstr "Вилучення прив'язки пристроїв для місць" - - #: src/login/org.freedesktop.login1.policy:149 - msgid "Authentication is required to reset how devices are attached to seats." --msgstr "" --"Потрібна автентифікація, щоб перезапустити спосіб під'єднання до місць." -+msgstr "Для скидання прив'язки пристроїв до місць слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" --msgstr "Вимкнути систему" -+msgstr "Вимикання системи" - - #: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." --msgstr "Потрібна автентифікація, щоб вимкнути систему." -+msgstr "Для вимикання системи слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" --msgstr "Вимкнути систему, коли інші користувачі ще в ній" -+msgstr "Вимикання системи, коли інші користувачі ще у ній" - - #: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." - msgstr "" --"Потрібна автентифікація, щоб вимкнути систему, коли інші користувачі в ній." -+"Для вимикання системи, коли у ній ще працюють інші користувачі, слід пройти " -+"розпізнавання." - - #: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" --msgstr "Вимкнути систему, коли програми намагаються перешкодити цьому" -+msgstr "Вимикання системи, коли програми намагаються перешкодити цьому" - - #: src/login/org.freedesktop.login1.policy:181 - msgid "" - "Authentication is required to power off the system while an application is " - "inhibiting this." - msgstr "" --"Потрібна автентифікація, щоб вимкнути систему, коли програми намагаються " --"перешкодити цьому." -+"Для того, щоб вимкнути систему, коли програми намагаються перешкодити цьому, " -+"слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" --msgstr "Перезавантажити систему" -+msgstr "Перезавантаження системи" - - #: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." --msgstr "Для перезавантаження системи необхідна ідентифікація." -+msgstr "Для перезавантаження системи слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" --msgstr "Перезавантажити, якщо інші користувачі в системі" -+msgstr "Перезавантаження, якщо інші користувачі в системі" - - #: src/login/org.freedesktop.login1.policy:203 - msgid "" - "Authentication is required to reboot the system while other users are logged " - "in." - msgstr "" --"Потрібна автентифікація, щоб перезапустити систему, коли інші користувачі в " --"ній." -+"Для перезавантаження системи, коли у ній ще працюють інші користувачі, слід " -+"пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" --msgstr "Перезапустити систему, коли програми намагаються перешкодити цьому" -+msgstr "Перезапуск системи, коли програми намагаються перешкодити цьому" - - #: src/login/org.freedesktop.login1.policy:214 - msgid "" - "Authentication is required to reboot the system while an application is " - "inhibiting this." - msgstr "" --"Потрібна автентифікація, щоб перезапустити систему, коли програми " --"намагаються перешкодити цьому." -+"Для того, щоб перезавантажити систему, коли програми намагаються перешкодити " -+"цьому, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:224 - msgid "Halt the system" --msgstr "Зупинити систему" -+msgstr "Зупинення системи" - - #: src/login/org.freedesktop.login1.policy:225 - msgid "Authentication is required to halt the system." --msgstr "Потрібна автентифікація, щоб зупинити систему." -+msgstr "Для зупинення системи слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:235 - msgid "Halt the system while other users are logged in" --msgstr "Зупинити систему, коли інші користувачі в ній" -+msgstr "Зупинення системи, коли інші користувачі в ній" - - #: src/login/org.freedesktop.login1.policy:236 - msgid "" - "Authentication is required to halt the system while other users are logged " - "in." - msgstr "" --"Потрібна автентифікація, щоб зупинити систему, коли інші користувачі в ній." -+"Для зупинення системи, коли у ній ще працюють інші користувачі, слід пройти " -+"розпізнавання." - - #: src/login/org.freedesktop.login1.policy:246 - msgid "Halt the system while an application is inhibiting this" --msgstr "Зупинити систему, коли програми намагаються перешкодити цьому" -+msgstr "Зупинення системи, коли програми намагаються перешкодити цьому" - - #: src/login/org.freedesktop.login1.policy:247 - msgid "" - "Authentication is required to halt the system while an application is " - "inhibiting this." - msgstr "" --"Потрібна автентифікація, щоб зупинити систему, коли програма" --" намагається " --"перешкодити цьому." -+"Для того, щоб зупинити систему, коли програми намагаються перешкодити цьому, " -+"слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" --msgstr "Призупинити систему" -+msgstr "Призупинення системи" - - #: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." --msgstr "Потрібна автентифікація, щоб призупинити систему." -+msgstr "Для призупинення системи слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" --msgstr "Призупинити систему, коли інші користувачі в ній" -+msgstr "Призупинення системи, коли інші користувачі в ній" - - #: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." - msgstr "" --"Потрібна автентифікація, щоб призупинити систему, коли інші користувачі в " --"ній." -+"Для призупинення системи, коли у ній ще працюють інші користувачі, слід " -+"пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" --msgstr "Призупинити систему, коли програми намагаються перешкодити цьому" -+msgstr "Призупинення системи, коли програми намагаються перешкодити цьому" - - #: src/login/org.freedesktop.login1.policy:279 - msgid "" - "Authentication is required to suspend the system while an application is " - "inhibiting this." - msgstr "" --"Потрібна автентифікація, щоб призупинити систему, коли програми намагаються " --"перешкодити цьому." -+"Для того, щоб призупинити систему, коли програми намагаються перешкодити " -+"цьому, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" --msgstr "Приспати систему" -+msgstr "Присипляння системи" - - #: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." --msgstr "Потрібна автентифікація, щоб приспати систему." -+msgstr "Для присипляння системи слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" --msgstr "Приспати систему, коли інші користувачі в ній" -+msgstr "Присипляння системи, коли інші користувачі в ній" - - #: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." - msgstr "" --"Потрібна автентифікація, щоб присипання систему, коли інші користувачі в ній." -+"Для присипляння системи, коли у ній ще працюють інші користувачі, слід " -+"пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" --msgstr "Приспати систему, коли програми намагаються перешкодити цьому" -+msgstr "Присипляння системи, коли програми намагаються перешкодити цьому" - - #: src/login/org.freedesktop.login1.policy:311 - msgid "" - "Authentication is required to hibernate the system while an application is " - "inhibiting this." - msgstr "" --"Потрібна автентифікація, щоб приспати систему, коли програми намагаються " --"перешкодити цьому." -+"Для того, щоб приспати систему, коли програми намагаються перешкодити цьому, " -+"слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" --msgstr "Керувати сеансами, користувачами і робочими місцями" -+msgstr "Керування сеансами, користувачами і робочими місцями" - - #: src/login/org.freedesktop.login1.policy:322 - msgid "Authentication is required to manage active sessions, users and seats." - msgstr "" --"Потрібна автентифікація, щоб керувати сеансами, користувачами і робочими " --"місцями." -+"Для того, щоб керувати сеансами, користувачами і робочими місцями, слід " -+"пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" --msgstr "Заблокувати або розблокувати сеанси" -+msgstr "Блокування і розблоковування сеансів" - - #: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." --msgstr "Потрібна автентифікація, щоб заблокувати або розблокувати сеанси." -+msgstr "" -+"Для того, щоб заблокувати або розблокувати активні сеанси, слід пройти " -+"розпізнавання." - - #: src/login/org.freedesktop.login1.policy:341 - msgid "Set the reboot \"reason\" in the kernel" -@@ -533,7 +540,8 @@ msgstr "Встановлення «причини» перезавантажен - #: src/login/org.freedesktop.login1.policy:342 - msgid "Authentication is required to set the reboot \"reason\" in the kernel." - msgstr "" --"Потрібна автентифікація, щоб встановити «причину» перезавантаження у ядрі." -+"Для того, щоб встановити «причину» перезавантаження у ядрі, слід пройти " -+"розпізнавання." - - #: src/login/org.freedesktop.login1.policy:352 - msgid "Indicate to the firmware to boot to setup interface" -@@ -544,8 +552,8 @@ msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." - msgstr "" --"Потрібна автентифікація, щоб дозволити мікрокоду визначати, чи завантажувати " --"інтерфейс встановлення." -+"Для того, щоб дозволити мікрокоду визначати, чи завантажувати інтерфейс " -+"встановлення, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:363 - msgid "Indicate to the boot loader to boot to the boot loader menu" -@@ -556,8 +564,8 @@ msgid "" - "Authentication is required to indicate to the boot loader to boot to the " - "boot loader menu." - msgstr "" --"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажитися до " --"меню завантажувача." -+"Для того, щоб вказати завантажувачу, що слід завантажитися до меню " -+"завантажувача, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:374 - msgid "Indicate to the boot loader to boot a specific entry" -@@ -568,16 +576,16 @@ msgid "" - "Authentication is required to indicate to the boot loader to boot into a " - "specific boot loader entry." - msgstr "" --"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажити " --"певний пункт меню завантаження." -+"Для того, щоб вказати завантажувачу, що слід завантажити певний пункт меню " -+"завантаження, слід пройти розпізнавання." - - #: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" --msgstr "Вказати повідомлення на стіні" -+msgstr "Встановлення повідомлення на стіні" - - #: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" --msgstr "Потрібна автентифікація, щоб вказати повідомлення на стіні" -+msgstr "Для встановлення повідомлення на стіні слід пройти розпізнавання" - - #: src/login/org.freedesktop.login1.policy:395 - msgid "Change Session" -@@ -589,77 +597,81 @@ msgstr "Для зміни віртуального термінала слід - - #: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" --msgstr "Увійти в локальний контейнер" -+msgstr "Вхід до локального контейнера" - - #: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." --msgstr "Потрібна автентифікація, щоб увійти в локальний контейнер." -+msgstr "" -+"Для того, щоб увійти до локального контейнера, слід пройти розпізнавання." - - #: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" --msgstr "Увійти в локальний вузол" -+msgstr "Вхід до локального вузла" - - #: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." --msgstr "Потрібна автентифікація, щоб увійти в локальний вузол." -+msgstr "Для входу до локального вузла слід пройти розпізнавання." - - #: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" --msgstr "Перейняти оболонку в локальному контейнері" -+msgstr "Отримання командної оболонки у локальному контейнері" - - #: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "" --"Потрібна автентифікація, щоб перейняти оболонку в локальному контейнері." -+"Для отримання командної оболонки у локальному контейнері слід пройти " -+"розпізнавання." - - #: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" --msgstr "Перейняти оболонку на локальному вузлі" -+msgstr "Отримання командної оболонки на локальному вузлі" - - #: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." --msgstr "Потрібна автентифікація, щоб перейняти оболонку на локальному вузлі." -+msgstr "" -+"Для отримання командної оболонки на локальному вузлі слід пройти " -+"розпізнавання." - - #: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" --msgstr "Перейняти псевдо TTY в локальному контейнері" -+msgstr "Отримання псевдо-TTY у локальному контейнері" - - #: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "" --"Потрібна автентифікація, щоб перейняти псевдо TTY в локальному контейнері." -+"Для отримання псевдо-TTY в локальному контейнері слід пройти розпізнавання." - - #: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" --msgstr "Перейняти псевдо TTY на локальному вузлі" -+msgstr "Отримання псевдо-TTY на локальному вузлі" - - #: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." --msgstr "Потрібна автентифікація, щоб перейняти псевдо TTY на локальному вузлі." -+msgstr "Для отримання псевдо-TTY на локальному вузлі слід пройти розпізнавання." - - #: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" --msgstr "Керувати локальними віртуальними машинами і контейнерами" -+msgstr "Керування локальними віртуальними машинами і контейнерами" - - #: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "" --"Потрібна автентифікація, щоб керувати локальними віртуальними машинами і " --"контейнерами." -+"Для доступу до керування локальними віртуальними машинами і контейнерами " -+"слід пройти розпізнавання." - - #: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" --msgstr "Керувати локальними образами віртуальних машин і контейнерів" -+msgstr "Керування локальними образами віртуальних машин і контейнерів" - - #: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." - msgstr "" --"Потрібна автентифікація, щоб керувати локальними образами віртуальних машин " --"і контейнерів." -+"Для доступу до керування локальними образами віртуальних машин і контейнерів " -+"слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:22 - msgid "Set NTP servers" -@@ -667,7 +679,7 @@ msgstr "Встановлення серверів NTP" - - #: src/network/org.freedesktop.network1.policy:23 - msgid "Authentication is required to set NTP servers." --msgstr "Потрібна автентифікація, щоб встановити сервери NTP." -+msgstr "Для встановлення серверів NTP слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:33 - #: src/resolve/org.freedesktop.resolve1.policy:44 -@@ -677,7 +689,7 @@ msgstr "Встановлення серверів DNS" - #: src/network/org.freedesktop.network1.policy:34 - #: src/resolve/org.freedesktop.resolve1.policy:45 - msgid "Authentication is required to set DNS servers." --msgstr "Потрібна автентифікація, щоб встановити сервери DNS." -+msgstr "Для встановлення серверів DNS слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:44 - #: src/resolve/org.freedesktop.resolve1.policy:55 -@@ -687,7 +699,7 @@ msgstr "Встановлення доменів" - #: src/network/org.freedesktop.network1.policy:45 - #: src/resolve/org.freedesktop.resolve1.policy:56 - msgid "Authentication is required to set domains." --msgstr "Потрібна автентифікація, щоб встановити домени." -+msgstr "Для встановлення доменів слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:55 - #: src/resolve/org.freedesktop.resolve1.policy:66 -@@ -697,7 +709,7 @@ msgstr "Встановлення типового маршруту" - #: src/network/org.freedesktop.network1.policy:56 - #: src/resolve/org.freedesktop.resolve1.policy:67 - msgid "Authentication is required to set default route." --msgstr "Потрібна автентифікація, щоб встановити типовий маршрут." -+msgstr "Для встановлення типового маршруту слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:66 - #: src/resolve/org.freedesktop.resolve1.policy:77 -@@ -707,17 +719,17 @@ msgstr "Вмикання або вимикання LLMNR" - #: src/network/org.freedesktop.network1.policy:67 - #: src/resolve/org.freedesktop.resolve1.policy:78 - msgid "Authentication is required to enable or disable LLMNR." --msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути LLMNR." -+msgstr "Для вмикання або вимикання LLMNR слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:77 - #: src/resolve/org.freedesktop.resolve1.policy:88 - msgid "Enable/disable multicast DNS" --msgstr "Вмикання або вимикання трансляційного DNS" -+msgstr "Вмикання або вимикання трансляційної DNS" - - #: src/network/org.freedesktop.network1.policy:78 - #: src/resolve/org.freedesktop.resolve1.policy:89 - msgid "Authentication is required to enable or disable multicast DNS." --msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути трансляційну DNS." -+msgstr "Для вмикання або вимикання трансляційної DNS слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:88 - #: src/resolve/org.freedesktop.resolve1.policy:99 -@@ -727,7 +739,7 @@ msgstr "Вмикання і вимикання DNS через TLS" - #: src/network/org.freedesktop.network1.policy:89 - #: src/resolve/org.freedesktop.resolve1.policy:100 - msgid "Authentication is required to enable or disable DNS over TLS." --msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути DNS через TLS." -+msgstr "Для вмикання або вимикання DNS через TLS слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:99 - #: src/resolve/org.freedesktop.resolve1.policy:110 -@@ -737,7 +749,7 @@ msgstr "Вмикання або вимикання DNSSEC" - #: src/network/org.freedesktop.network1.policy:100 - #: src/resolve/org.freedesktop.resolve1.policy:111 - msgid "Authentication is required to enable or disable DNSSEC." --msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути DNSSEC." -+msgstr "Для вмикання або вимикання DNSSEC слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:110 - #: src/resolve/org.freedesktop.resolve1.policy:121 -@@ -748,7 +760,7 @@ msgstr "Встановлення прив'язок від'ємної довір - #: src/resolve/org.freedesktop.resolve1.policy:122 - msgid "Authentication is required to set DNSSEC Negative Trust Anchors." - msgstr "" --"Потрібна автентифікація, щоб встановити прив'язки від'ємної довіри DNSSEC." -+"Для встановлення прив'язки від'ємної довіри DNSSEC слід пройти розпізнавання." - - #: src/network/org.freedesktop.network1.policy:121 - msgid "Revert NTP settings" -@@ -773,7 +785,8 @@ msgstr "Сервер DHCP надсилає повідомлення щодо п - #: src/network/org.freedesktop.network1.policy:144 - msgid "Authentication is required to send force renew message." - msgstr "" --"Потрібна автентифікація, щоб надіслати повідомлення щодо примусового оновлення" -+"Для надсилання повідомлення щодо примусового оновлення слід пройти " -+"розпізнавання." - - #: src/network/org.freedesktop.network1.policy:154 - msgid "Renew dynamic addresses" -@@ -805,7 +818,7 @@ msgstr "Інспектування образу портативної служ - - #: src/portable/org.freedesktop.portable1.policy:14 - msgid "Authentication is required to inspect a portable service image." --msgstr "Потрібна автентифікація, щоб інспектувати образ портативної служби." -+msgstr "Для інспектування образу портативної служби слід пройти розпізнавання." - - #: src/portable/org.freedesktop.portable1.policy:23 - msgid "Attach or detach a portable service image" -@@ -815,7 +828,8 @@ msgstr "Долучення або вилучення образу портати - msgid "" - "Authentication is required to attach or detach a portable service image." - msgstr "" --"Потрібна автентифікація, щоб долучити або вилучити образ портативної служби." -+"Для долучення або вилучення образу портативної служби слід пройти " -+"розпізнавання." - - #: src/portable/org.freedesktop.portable1.policy:34 - msgid "Delete or modify portable service image" -@@ -825,24 +839,24 @@ msgstr "Вилучення або внесення змін до образу п - msgid "" - "Authentication is required to delete or modify a portable service image." - msgstr "" --"Потрібна автентифікація, щоб вилучити образ портативної служби або внести до " --"нього зміни." -+"Для вилучення образу портативної служби або внесення до нього змін слід " -+"пройти розпізнавання." - - #: src/resolve/org.freedesktop.resolve1.policy:22 - msgid "Register a DNS-SD service" --msgstr "Зареєструвати службу DNS-SD" -+msgstr "Реєстрація служби DNS-SD" - - #: src/resolve/org.freedesktop.resolve1.policy:23 - msgid "Authentication is required to register a DNS-SD service" --msgstr "Потрібна автентифікація, щоб зареєструвати службу DNS-SD" -+msgstr "Для реєстрації служби DNS-SD слід пройти розпізнавання" - - #: src/resolve/org.freedesktop.resolve1.policy:33 - msgid "Unregister a DNS-SD service" --msgstr "Зняти з реєстрації службу DNS-SD" -+msgstr "Зняття з реєстрації служби DNS-SD" - - #: src/resolve/org.freedesktop.resolve1.policy:34 - msgid "Authentication is required to unregister a DNS-SD service" --msgstr "Потрібна автентифікація, щоб зняти з реєстрації службу DNS-SD" -+msgstr "Для зняття з реєстрації служби DNS-SD слід пройти розпізнавання" - - #: src/resolve/org.freedesktop.resolve1.policy:132 - msgid "Revert name resolution settings" -@@ -856,79 +870,88 @@ msgstr "" - - #: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" --msgstr "Вказати системний час" -+msgstr "Встановлення загальносистемного часу" - - #: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." --msgstr "Потрібна автентифікація, щоб вказати системний час." -+msgstr "Для встановлення загальносистемного часу слід пройти розпізнавання." - - #: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" --msgstr "Вказати системний часовий пояс" -+msgstr "Встановлення загальносистемного часового поясу" - - #: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." --msgstr "Потрібна автентифікація, щоб вказати системний часовий пояс." -+msgstr "" -+"Для встановлення загальносистемного часового поясу слід пройти розпізнавання." - - #: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" --msgstr "Вкажіть RTC для локального часового поясу або UTC" -+msgstr "Встановлення для RTC місцевого часового поясу або UTC" - - #: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." - msgstr "" --"Потрібна автентифікація, щоб контролювати, чи зберігає RTC локальний час або " --"UTC." -+"Для керування тим, зберігатиме годинник реального часу локальний час чи час " -+"UTC, слід пройти розпізнавання." - - #: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" --msgstr "Увімкнути або вимкнути синхронізування часу через мережу" -+msgstr "Вмикання або вимикання синхронізації часу за допомогою мережі" - - #: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." - msgstr "" --"Потрібна автентифікація, щоб контролювати, чи синхронізування часу через " --"мережу запущено." -+"Для керування тим, чи слід вмикати синхронізацію часу за допомогою мережі, " -+"слід пройти розпізнавання." - --#: src/core/dbus-unit.c:356 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." --msgstr "Потрібна автентифікація, щоб запустити «$(unit)»." -+msgstr "Для запуску «$(unit)» слід пройти розпізнавання." - --#: src/core/dbus-unit.c:357 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." --msgstr "Потрібна автентифікація, щоб зупинити «$(unit)»." -+msgstr "Для зупинення «$(unit)» слід пройти розпізнавання." - --#: src/core/dbus-unit.c:358 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." --msgstr "Потрібна автентифікація, щоб перезавантажити «$(unit)»." -+msgstr "Для перезавантаження «$(unit)» слід пройти розпізнавання." - --#: src/core/dbus-unit.c:359 src/core/dbus-unit.c:360 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." --msgstr "Потрібна автентифікація, щоб перезапустити «$(unit)»." -+msgstr "Для перезапуску «$(unit)» слід пройти розпізнавання." - --#: src/core/dbus-unit.c:532 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." - msgstr "" --"Потрібна автентифікація, щоб надіслати сигнал UNIX до процесів «$(unit)»." -+"Для надсилання сигналу UNIX до процесів «$(unit)» слід пройти розпізнавання." - --#: src/core/dbus-unit.c:563 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." --msgstr "Потрібна автентифікація, щоб скинути «пошкоджений» стан з «$(unit)»." -+msgstr "" -+"Для скидання «пошкодженого» стану з «$(unit)» слід пройти розпізнавання." - --#: src/core/dbus-unit.c:596 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." --msgstr "Потрібна автентифікація, щоб вказати властивості на «$(unit)»." -+msgstr "Для визначення властивостей на «$(unit)» слід пройти розпізнавання." - --#: src/core/dbus-unit.c:705 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." - msgstr "" --"Потрібна автентифікація, щоб вилучити файли і каталоги, які пов'язано із " --"«$(unit)»." -+"Для вилучення файлів і каталогів, які пов'язано із «$(unit)», слід пройти " -+"розпізнавання." -+ -+#: src/core/dbus-unit.c:760 -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "" -+"Для замороження або розмороження процесів модуля «$(unit)» слід пройти " -+"розпізнавання." -diff --git a/po/zh_CN.po b/po/zh_CN.po -index 2655f62..83a5193 100644 ---- a/po/zh_CN.po -+++ b/po/zh_CN.po -@@ -8,8 +8,8 @@ - msgid "" - msgstr "" - "Project-Id-Version: systemd\n" --"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" --"POT-Creation-Date: 2015-10-27 02:24+0000\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2016-03-01 20:38-0700\n" - "Last-Translator: Jeff Bai \n" - "Language-Team: Chinese \n" -@@ -20,505 +20,941 @@ msgstr "" - "X-Generator: Poedit 1.8.7.1\n" - "Plural-Forms: nplurals=1; plural=0;\n" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 -+#: src/core/org.freedesktop.systemd1.policy.in:22 - msgid "Send passphrase back to system" - msgstr "将密码发回系统" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 -+#: src/core/org.freedesktop.systemd1.policy.in:23 - msgid "" - "Authentication is required to send the entered passphrase back to the system." - msgstr "将输入的密码发回系统需要认证。" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 -+#: src/core/org.freedesktop.systemd1.policy.in:33 - msgid "Manage system services or other units" - msgstr "管理系统服务或其它单元" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 -+#: src/core/org.freedesktop.systemd1.policy.in:34 - msgid "Authentication is required to manage system services or other units." - msgstr "管理系统服务或其它单元需要认证。" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 -+#: src/core/org.freedesktop.systemd1.policy.in:43 - msgid "Manage system service or unit files" - msgstr "管理系统服务或单元文件" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 -+#: src/core/org.freedesktop.systemd1.policy.in:44 - msgid "Authentication is required to manage system service or unit files." - msgstr "管理系统服务或单元文件需要认证。" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 -+#: src/core/org.freedesktop.systemd1.policy.in:54 - msgid "Set or unset system and service manager environment variables" - msgstr "设置或清除系统及服务管理器的环境变量" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 -+#: src/core/org.freedesktop.systemd1.policy.in:55 - msgid "" - "Authentication is required to set or unset system and service manager " - "environment variables." - msgstr "设置或清除系统及服务管理器的环境变量需要认证。" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 -+#: src/core/org.freedesktop.systemd1.policy.in:64 - msgid "Reload the systemd state" - msgstr "重新载入 systemd 状态" - --#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 -+#: src/core/org.freedesktop.systemd1.policy.in:65 - msgid "Authentication is required to reload the systemd state." - msgstr "重新载入 systemd 状态需要认证。" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to create a user's home area." -+msgstr "重新载入 systemd 状态需要认证。" -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to remove a user's home area." -+msgstr "重新载入 systemd 状态需要认证。" -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "管理活动会话、用户与会话座位需要认证。" -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+# Pay attention to the concept of "seat". -+# -+# To fully understand the meaning, please refer to session management in old ConsoleKit and new systemd-logind. -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "允许将设备附加至某个会话座位需要认证。" -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to resize a user's home area." -+msgstr "设置 wall 消息需要认证。" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "管理活动会话、用户与会话座位需要认证。" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "设置主机名" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 -+#: src/hostname/org.freedesktop.hostname1.policy:21 - msgid "Authentication is required to set the local hostname." - msgstr "设置本地主机名需要认证。" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 -+#: src/hostname/org.freedesktop.hostname1.policy:30 - msgid "Set static hostname" - msgstr "设置静态主机名" - - # For pretty hostname, the zh_CN/zh_TW translation should be discussed again. - # - # There were some discussions, like https://lists.fedoraprojects.org/pipermail/trans-zh_cn/2012-December/001347.html --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 -+#: src/hostname/org.freedesktop.hostname1.policy:31 - #, fuzzy - msgid "" - "Authentication is required to set the statically configured local hostname, " - "as well as the pretty hostname." - msgstr "设置静态本地主机名或美观主机名需要认证。" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 -+#: src/hostname/org.freedesktop.hostname1.policy:41 - msgid "Set machine information" - msgstr "设置机器信息" - --#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 -+#: src/hostname/org.freedesktop.hostname1.policy:42 - msgid "Authentication is required to set local machine information." - msgstr "设置本地机器信息需要认证。" - --#: ../src/import/org.freedesktop.import1.policy.in.h:1 -+#: src/hostname/org.freedesktop.hostname1.policy:51 -+msgid "Get product UUID" -+msgstr "" -+ -+#: src/hostname/org.freedesktop.hostname1.policy:52 -+#, fuzzy -+#| msgid "Authentication is required to reload '$(unit)'." -+msgid "Authentication is required to get product UUID." -+msgstr "重新载入“$(unit)”需要认证。" -+ -+#: src/import/org.freedesktop.import1.policy:22 - msgid "Import a VM or container image" - msgstr "导入虚拟机或容器镜像" - --#: ../src/import/org.freedesktop.import1.policy.in.h:2 -+#: src/import/org.freedesktop.import1.policy:23 - msgid "Authentication is required to import a VM or container image" - msgstr "导入虚拟机或容器镜像需要认证" - --#: ../src/import/org.freedesktop.import1.policy.in.h:3 -+#: src/import/org.freedesktop.import1.policy:32 - msgid "Export a VM or container image" - msgstr "导出虚拟机或容器镜像" - --#: ../src/import/org.freedesktop.import1.policy.in.h:4 -+#: src/import/org.freedesktop.import1.policy:33 - msgid "Authentication is required to export a VM or container image" - msgstr "导出虚拟机或容器镜像需要认证" - --#: ../src/import/org.freedesktop.import1.policy.in.h:5 -+#: src/import/org.freedesktop.import1.policy:42 - msgid "Download a VM or container image" - msgstr "下载虚拟机或容器镜像" - --#: ../src/import/org.freedesktop.import1.policy.in.h:6 -+#: src/import/org.freedesktop.import1.policy:43 - msgid "Authentication is required to download a VM or container image" - msgstr "下载虚拟机或容器镜像需要认证。" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 -+#: src/locale/org.freedesktop.locale1.policy:22 - msgid "Set system locale" - msgstr "设置系统区域和语言" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 -+#: src/locale/org.freedesktop.locale1.policy:23 - msgid "Authentication is required to set the system locale." - msgstr "设置系统区域和语言需要认证。" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 -+#: src/locale/org.freedesktop.locale1.policy:33 - msgid "Set system keyboard settings" - msgstr "设置系统键盘" - --#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 -+#: src/locale/org.freedesktop.locale1.policy:34 - msgid "Authentication is required to set the system keyboard settings." - msgstr "设置系统键盘需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:22 - msgid "Allow applications to inhibit system shutdown" - msgstr "允许应用程序阻止系统关机" - --#: ../src/login/org.freedesktop.login1.policy.in.h:2 -+#: src/login/org.freedesktop.login1.policy:23 - msgid "" - "Authentication is required for an application to inhibit system shutdown." - msgstr "允许应用程序阻止系统关机需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:3 -+#: src/login/org.freedesktop.login1.policy:33 - msgid "Allow applications to delay system shutdown" - msgstr "允许应用程序延迟系统关机" - --#: ../src/login/org.freedesktop.login1.policy.in.h:4 -+#: src/login/org.freedesktop.login1.policy:34 - msgid "Authentication is required for an application to delay system shutdown." - msgstr "允许应用程序延迟系统关机需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:5 -+#: src/login/org.freedesktop.login1.policy:44 - msgid "Allow applications to inhibit system sleep" - msgstr "允许应用程序阻止系统睡眠" - --#: ../src/login/org.freedesktop.login1.policy.in.h:6 -+#: src/login/org.freedesktop.login1.policy:45 - msgid "Authentication is required for an application to inhibit system sleep." - msgstr "允许应用程序阻止系统睡眠需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:7 -+#: src/login/org.freedesktop.login1.policy:55 - msgid "Allow applications to delay system sleep" - msgstr "允许应用程序延迟系统睡眠" - --#: ../src/login/org.freedesktop.login1.policy.in.h:8 -+#: src/login/org.freedesktop.login1.policy:56 - msgid "Authentication is required for an application to delay system sleep." - msgstr "允许应用程序延迟系统睡眠需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:9 -+#: src/login/org.freedesktop.login1.policy:65 - msgid "Allow applications to inhibit automatic system suspend" - msgstr "允许应用程序阻止系统自动挂起" - --#: ../src/login/org.freedesktop.login1.policy.in.h:10 -+#: src/login/org.freedesktop.login1.policy:66 - msgid "" - "Authentication is required for an application to inhibit automatic system " - "suspend." - msgstr "允许应用程序阻止系统自动挂起需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:11 -+#: src/login/org.freedesktop.login1.policy:75 - msgid "Allow applications to inhibit system handling of the power key" - msgstr "允许应用程序阻止系统响应电源键" - --#: ../src/login/org.freedesktop.login1.policy.in.h:12 -+#: src/login/org.freedesktop.login1.policy:76 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the power key." - msgstr "允许应用程序阻止系统响应电源键需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:13 -+#: src/login/org.freedesktop.login1.policy:86 - msgid "Allow applications to inhibit system handling of the suspend key" - msgstr "允许应用程序阻止系统响应挂起键" - --#: ../src/login/org.freedesktop.login1.policy.in.h:14 -+#: src/login/org.freedesktop.login1.policy:87 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the suspend key." - msgstr "允许应用程序阻止系统响应挂起键需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:15 -+#: src/login/org.freedesktop.login1.policy:97 - msgid "Allow applications to inhibit system handling of the hibernate key" - msgstr "允许应用程序阻止系统响应挂起键" - --#: ../src/login/org.freedesktop.login1.policy.in.h:16 -+#: src/login/org.freedesktop.login1.policy:98 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the hibernate key." - msgstr "允许应用程序阻止系统响应挂起键需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:17 -+#: src/login/org.freedesktop.login1.policy:107 - msgid "Allow applications to inhibit system handling of the lid switch" - msgstr "允许应用程序阻止系统响应笔记本上盖开关事件" - --#: ../src/login/org.freedesktop.login1.policy.in.h:18 -+#: src/login/org.freedesktop.login1.policy:108 - msgid "" - "Authentication is required for an application to inhibit system handling of " - "the lid switch." - msgstr "允许应用程序阻止系统响应笔记本上盖开关事件需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:19 -+#: src/login/org.freedesktop.login1.policy:117 -+#, fuzzy -+#| msgid "Allow non-logged-in users to run programs" -+msgid "Allow non-logged-in user to run programs" -+msgstr "允许未登录用户运行程序" -+ -+#: src/login/org.freedesktop.login1.policy:118 -+#, fuzzy -+#| msgid "Authentication is required to run programs as a non-logged-in user." -+msgid "Explicit request is required to run programs as a non-logged-in user." -+msgstr "允许未登录用户运行程序需要认证。" -+ -+#: src/login/org.freedesktop.login1.policy:127 - msgid "Allow non-logged-in users to run programs" - msgstr "允许未登录用户运行程序" - --#: ../src/login/org.freedesktop.login1.policy.in.h:20 -+#: src/login/org.freedesktop.login1.policy:128 - msgid "Authentication is required to run programs as a non-logged-in user." - msgstr "允许未登录用户运行程序需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:21 -+#: src/login/org.freedesktop.login1.policy:137 - msgid "Allow attaching devices to seats" - msgstr "允许将设备附加至会话座位" - - # Pay attention to the concept of "seat". - # - # To fully understand the meaning, please refer to session management in old ConsoleKit and new systemd-logind. --#: ../src/login/org.freedesktop.login1.policy.in.h:22 -+#: src/login/org.freedesktop.login1.policy:138 - msgid "Authentication is required to attach a device to a seat." - msgstr "允许将设备附加至某个会话座位需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:23 -+#: src/login/org.freedesktop.login1.policy:148 - msgid "Flush device to seat attachments" - msgstr "刷新设备至会话座位间的连接" - --#: ../src/login/org.freedesktop.login1.policy.in.h:24 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+#: src/login/org.freedesktop.login1.policy:149 -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "重新设定设备的会话座位接入方式时需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:25 -+#: src/login/org.freedesktop.login1.policy:158 - msgid "Power off the system" - msgstr "关闭系统" - --#: ../src/login/org.freedesktop.login1.policy.in.h:26 -+#: src/login/org.freedesktop.login1.policy:159 - msgid "Authentication is required to power off the system." - msgstr "关闭系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:27 -+#: src/login/org.freedesktop.login1.policy:169 - msgid "Power off the system while other users are logged in" - msgstr "存在其他已登录用户时仍然关机" - --#: ../src/login/org.freedesktop.login1.policy.in.h:28 -+#: src/login/org.freedesktop.login1.policy:170 - msgid "" - "Authentication is required to power off the system while other users are " - "logged in." - msgstr "存在其他已登录用户时关闭系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:29 -+#: src/login/org.freedesktop.login1.policy:180 - msgid "Power off the system while an application is inhibiting this" - msgstr "有其它应用程序阻止时仍然关机" - --#: ../src/login/org.freedesktop.login1.policy.in.h:30 -+#: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "在其它应用程序阻止关机时关闭系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:31 -+#: src/login/org.freedesktop.login1.policy:191 - msgid "Reboot the system" - msgstr "重启系统" - --#: ../src/login/org.freedesktop.login1.policy.in.h:32 -+#: src/login/org.freedesktop.login1.policy:192 - msgid "Authentication is required to reboot the system." - msgstr "重启系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:33 -+#: src/login/org.freedesktop.login1.policy:202 - msgid "Reboot the system while other users are logged in" - msgstr "存在其他已登录用户时仍然重启" - --#: ../src/login/org.freedesktop.login1.policy.in.h:34 -+#: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "存在其他已登录用户时重启系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:35 -+#: src/login/org.freedesktop.login1.policy:213 - msgid "Reboot the system while an application is inhibiting this" - msgstr "有其它应用程序阻止时仍然重启" - --#: ../src/login/org.freedesktop.login1.policy.in.h:36 -+#: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "在其它应用程序阻止重启时重启系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:37 -+#: src/login/org.freedesktop.login1.policy:224 -+#, fuzzy -+#| msgid "Hibernate the system" -+msgid "Halt the system" -+msgstr "休眠系统" -+ -+#: src/login/org.freedesktop.login1.policy:225 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to halt the system." -+msgstr "休眠系统需要认证。" -+ -+#: src/login/org.freedesktop.login1.policy:235 -+#, fuzzy -+#| msgid "Hibernate the system while other users are logged in" -+msgid "Halt the system while other users are logged in" -+msgstr "存在其他已登录用户时仍然休眠" -+ -+#: src/login/org.freedesktop.login1.policy:236 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while other users are " -+#| "logged in." -+msgid "" -+"Authentication is required to halt the system while other users are logged " -+"in." -+msgstr "存在其他已登录用户时进行休眠系统需要认证。" -+ -+#: src/login/org.freedesktop.login1.policy:246 -+#, fuzzy -+#| msgid "Hibernate the system while an application is inhibiting this" -+msgid "Halt the system while an application is inhibiting this" -+msgstr "有其它应用程序阻止时仍然休眠" -+ -+#: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." -+msgid "" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "在其它应用程序阻止休眠时进行休眠需要认证。" -+ -+#: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" - msgstr "挂起系统" - --#: ../src/login/org.freedesktop.login1.policy.in.h:38 -+#: src/login/org.freedesktop.login1.policy:258 - msgid "Authentication is required to suspend the system." - msgstr "挂起系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:39 -+#: src/login/org.freedesktop.login1.policy:267 - msgid "Suspend the system while other users are logged in" - msgstr "存在其他已登录用户时仍然挂起系统" - --#: ../src/login/org.freedesktop.login1.policy.in.h:40 -+#: src/login/org.freedesktop.login1.policy:268 - msgid "" - "Authentication is required to suspend the system while other users are " - "logged in." - msgstr "存在其他已登录用户时挂起系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:41 -+#: src/login/org.freedesktop.login1.policy:278 - msgid "Suspend the system while an application is inhibiting this" - msgstr "有其它应用程序阻止时仍然挂起系统" - --#: ../src/login/org.freedesktop.login1.policy.in.h:42 -+#: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "在其它应用程序阻止挂起时挂起系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:43 -+#: src/login/org.freedesktop.login1.policy:289 - msgid "Hibernate the system" - msgstr "休眠系统" - --#: ../src/login/org.freedesktop.login1.policy.in.h:44 -+#: src/login/org.freedesktop.login1.policy:290 - msgid "Authentication is required to hibernate the system." - msgstr "休眠系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:45 -+#: src/login/org.freedesktop.login1.policy:299 - msgid "Hibernate the system while other users are logged in" - msgstr "存在其他已登录用户时仍然休眠" - --#: ../src/login/org.freedesktop.login1.policy.in.h:46 -+#: src/login/org.freedesktop.login1.policy:300 - msgid "" - "Authentication is required to hibernate the system while other users are " - "logged in." - msgstr "存在其他已登录用户时进行休眠系统需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:47 -+#: src/login/org.freedesktop.login1.policy:310 - msgid "Hibernate the system while an application is inhibiting this" - msgstr "有其它应用程序阻止时仍然休眠" - --#: ../src/login/org.freedesktop.login1.policy.in.h:48 -+#: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "在其它应用程序阻止休眠时进行休眠需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:49 -+#: src/login/org.freedesktop.login1.policy:321 - msgid "Manage active sessions, users and seats" - msgstr "管理活动会话、用户与会话座位" - --#: ../src/login/org.freedesktop.login1.policy.in.h:50 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+#: src/login/org.freedesktop.login1.policy:322 -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "管理活动会话、用户与会话座位需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:51 -+#: src/login/org.freedesktop.login1.policy:331 - msgid "Lock or unlock active sessions" - msgstr "锁定或解锁活动会话" - --#: ../src/login/org.freedesktop.login1.policy.in.h:52 -+#: src/login/org.freedesktop.login1.policy:332 - msgid "Authentication is required to lock or unlock active sessions." - msgstr "对活动会话进行锁定或解锁需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:53 --msgid "Allow indication to the firmware to boot to setup interface" -+#: src/login/org.freedesktop.login1.policy:341 -+msgid "Set the reboot \"reason\" in the kernel" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:342 -+#, fuzzy -+#| msgid "Authentication is required to set the system timezone." -+msgid "Authentication is required to set the reboot \"reason\" in the kernel." -+msgstr "设置系统时区需要认证。" -+ -+#: src/login/org.freedesktop.login1.policy:352 -+#, fuzzy -+#| msgid "Allow indication to the firmware to boot to setup interface" -+msgid "Indicate to the firmware to boot to setup interface" - msgstr "允许向固件发出指示以启动至设置界面" - --#: ../src/login/org.freedesktop.login1.policy.in.h:54 -+#: src/login/org.freedesktop.login1.policy:353 - msgid "" - "Authentication is required to indicate to the firmware to boot to setup " - "interface." - msgstr "向固件发出启动时进入设置界面的指令需要认证。" - --#: ../src/login/org.freedesktop.login1.policy.in.h:55 -+#: src/login/org.freedesktop.login1.policy:363 -+msgid "Indicate to the boot loader to boot to the boot loader menu" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:364 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot to the " -+"boot loader menu." -+msgstr "向固件发出启动时进入设置界面的指令需要认证。" -+ -+#: src/login/org.freedesktop.login1.policy:374 -+msgid "Indicate to the boot loader to boot a specific entry" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:375 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to indicate to the firmware to boot to setup " -+#| "interface." -+msgid "" -+"Authentication is required to indicate to the boot loader to boot into a " -+"specific boot loader entry." -+msgstr "向固件发出启动时进入设置界面的指令需要认证。" -+ -+#: src/login/org.freedesktop.login1.policy:385 - msgid "Set a wall message" - msgstr "设置 wall 消息" - --#: ../src/login/org.freedesktop.login1.policy.in.h:56 -+#: src/login/org.freedesktop.login1.policy:386 - msgid "Authentication is required to set a wall message" - msgstr "设置 wall 消息需要认证。" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "设置本地主机名需要认证。" -+ -+#: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "登入本地容器" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 -+#: src/machine/org.freedesktop.machine1.policy:23 - msgid "Authentication is required to log into a local container." - msgstr "登录一个本地容器需要认证。" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 -+#: src/machine/org.freedesktop.machine1.policy:32 - msgid "Log into the local host" - msgstr "登入本地主机" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 -+#: src/machine/org.freedesktop.machine1.policy:33 - msgid "Authentication is required to log into the local host." - msgstr "登入本地主机需要认证。" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 -+#: src/machine/org.freedesktop.machine1.policy:42 - msgid "Acquire a shell in a local container" - msgstr "在本地容器中获取一个 shell" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 -+#: src/machine/org.freedesktop.machine1.policy:43 - msgid "Authentication is required to acquire a shell in a local container." - msgstr "在本地容器中获取 shell 需要认证。" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 -+#: src/machine/org.freedesktop.machine1.policy:53 - msgid "Acquire a shell on the local host" - msgstr "在本地主机中获取一个 shell" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 -+#: src/machine/org.freedesktop.machine1.policy:54 - msgid "Authentication is required to acquire a shell on the local host." - msgstr "在本地主机中获取 shell 需要认证。" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 -+#: src/machine/org.freedesktop.machine1.policy:64 - msgid "Acquire a pseudo TTY in a local container" - msgstr "在本地容器中获取一个假 TTY" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 -+#: src/machine/org.freedesktop.machine1.policy:65 - msgid "" - "Authentication is required to acquire a pseudo TTY in a local container." - msgstr "在本地容器中获取假 TTY 需要认证。" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 -+#: src/machine/org.freedesktop.machine1.policy:74 - msgid "Acquire a pseudo TTY on the local host" - msgstr "在本地主机中获取一个假 TTY" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 -+#: src/machine/org.freedesktop.machine1.policy:75 - msgid "Authentication is required to acquire a pseudo TTY on the local host." - msgstr "在本地主机中获取假 TTY 需要认证。" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 -+#: src/machine/org.freedesktop.machine1.policy:84 - msgid "Manage local virtual machines and containers" - msgstr "管理本地虚拟机和容器" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 -+#: src/machine/org.freedesktop.machine1.policy:85 - msgid "" - "Authentication is required to manage local virtual machines and containers." - msgstr "管理本地虚拟机和容器需要认证。" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 -+#: src/machine/org.freedesktop.machine1.policy:95 - msgid "Manage local virtual machine and container images" - msgstr "管理本地虚拟机和容器的镜像" - --#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 -+#: src/machine/org.freedesktop.machine1.policy:96 - msgid "" - "Authentication is required to manage local virtual machine and container " - "images." - msgstr "管理本地的虚拟机和容器镜像需要认证。" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 -+#: src/network/org.freedesktop.network1.policy:22 -+msgid "Set NTP servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set NTP servers." -+msgstr "设置系统时间需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:33 -+#: src/resolve/org.freedesktop.resolve1.policy:44 -+msgid "Set DNS servers" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:34 -+#: src/resolve/org.freedesktop.resolve1.policy:45 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to set DNS servers." -+msgstr "设置系统时间需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:44 -+#: src/resolve/org.freedesktop.resolve1.policy:55 -+msgid "Set domains" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:45 -+#: src/resolve/org.freedesktop.resolve1.policy:56 -+#, fuzzy -+#| msgid "Authentication is required to stop '$(unit)'." -+msgid "Authentication is required to set domains." -+msgstr "停止“$(unit)”需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:55 -+#: src/resolve/org.freedesktop.resolve1.policy:66 -+msgid "Set default route" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:56 -+#: src/resolve/org.freedesktop.resolve1.policy:67 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to set default route." -+msgstr "设置本地主机名需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:66 -+#: src/resolve/org.freedesktop.resolve1.policy:77 -+msgid "Enable/disable LLMNR" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:67 -+#: src/resolve/org.freedesktop.resolve1.policy:78 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable LLMNR." -+msgstr "休眠系统需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:77 -+#: src/resolve/org.freedesktop.resolve1.policy:88 -+msgid "Enable/disable multicast DNS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:78 -+#: src/resolve/org.freedesktop.resolve1.policy:89 -+#, fuzzy -+#| msgid "Authentication is required to log into the local host." -+msgid "Authentication is required to enable or disable multicast DNS." -+msgstr "登入本地主机需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:88 -+#: src/resolve/org.freedesktop.resolve1.policy:99 -+msgid "Enable/disable DNS over TLS" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:89 -+#: src/resolve/org.freedesktop.resolve1.policy:100 -+#, fuzzy -+#| msgid "Authentication is required to set the local hostname." -+msgid "Authentication is required to enable or disable DNS over TLS." -+msgstr "设置本地主机名需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:99 -+#: src/resolve/org.freedesktop.resolve1.policy:110 -+msgid "Enable/disable DNSSEC" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:100 -+#: src/resolve/org.freedesktop.resolve1.policy:111 -+#, fuzzy -+#| msgid "Authentication is required to hibernate the system." -+msgid "Authentication is required to enable or disable DNSSEC." -+msgstr "休眠系统需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:110 -+#: src/resolve/org.freedesktop.resolve1.policy:121 -+msgid "Set DNSSEC Negative Trust Anchors" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:111 -+#: src/resolve/org.freedesktop.resolve1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system locale." -+msgid "Authentication is required to set DNSSEC Negative Trust Anchors." -+msgstr "设置系统区域和语言需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:121 -+msgid "Revert NTP settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:122 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset NTP settings." -+msgstr "设置系统时间需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:132 -+msgid "Revert DNS settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system time." -+msgid "Authentication is required to reset DNS settings." -+msgstr "设置系统时间需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "设置 wall 消息需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:154 -+msgid "Renew dynamic addresses" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:155 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to renew dynamic addresses." -+msgstr "设置 wall 消息需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:165 -+msgid "Reload network settings" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reload the systemd state." -+msgid "Authentication is required to reload network settings." -+msgstr "重新载入 systemd 状态需要认证。" -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "重启系统需要认证。" -+ -+#: src/portable/org.freedesktop.portable1.policy:13 -+msgid "Inspect a portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to import a VM or container image" -+msgid "Authentication is required to inspect a portable service image." -+msgstr "导入虚拟机或容器镜像需要认证" -+ -+#: src/portable/org.freedesktop.portable1.policy:23 -+msgid "Attach or detach a portable service image" -+msgstr "" -+ -+# Pay attention to the concept of "seat". -+# -+# To fully understand the meaning, please refer to session management in old ConsoleKit and new systemd-logind. -+#: src/portable/org.freedesktop.portable1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "" -+"Authentication is required to attach or detach a portable service image." -+msgstr "允许将设备附加至某个会话座位需要认证。" -+ -+#: src/portable/org.freedesktop.portable1.policy:34 -+msgid "Delete or modify portable service image" -+msgstr "" -+ -+#: src/portable/org.freedesktop.portable1.policy:35 -+#, fuzzy -+#| msgid "Authentication is required to download a VM or container image" -+msgid "" -+"Authentication is required to delete or modify a portable service image." -+msgstr "下载虚拟机或容器镜像需要认证。" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:22 -+msgid "Register a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:23 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to register a DNS-SD service" -+msgstr "设置 wall 消息需要认证。" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:33 -+msgid "Unregister a DNS-SD service" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:34 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to unregister a DNS-SD service" -+msgstr "设置 wall 消息需要认证。" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:132 -+msgid "Revert name resolution settings" -+msgstr "" -+ -+#: src/resolve/org.freedesktop.resolve1.policy:133 -+#, fuzzy -+#| msgid "Authentication is required to set the system keyboard settings." -+msgid "Authentication is required to reset name resolution settings." -+msgstr "设置系统键盘需要认证。" -+ -+#: src/timedate/org.freedesktop.timedate1.policy:22 - msgid "Set system time" - msgstr "设置系统时间" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 -+#: src/timedate/org.freedesktop.timedate1.policy:23 - msgid "Authentication is required to set the system time." - msgstr "设置系统时间需要认证。" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 -+#: src/timedate/org.freedesktop.timedate1.policy:33 - msgid "Set system timezone" - msgstr "设置系统时区" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 -+#: src/timedate/org.freedesktop.timedate1.policy:34 - msgid "Authentication is required to set the system timezone." - msgstr "设置系统时区需要认证。" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 -+#: src/timedate/org.freedesktop.timedate1.policy:43 - msgid "Set RTC to local timezone or UTC" - msgstr "设置硬件时钟使用本地时间或 UTC" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 -+#: src/timedate/org.freedesktop.timedate1.policy:44 - msgid "" - "Authentication is required to control whether the RTC stores the local or " - "UTC time." - msgstr "设置硬件时钟使用本地时间或 UTC 需要认证。" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 -+#: src/timedate/org.freedesktop.timedate1.policy:53 - msgid "Turn network time synchronization on or off" - msgstr "打开或关闭网络时间同步" - --#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 -+#: src/timedate/org.freedesktop.timedate1.policy:54 - msgid "" - "Authentication is required to control whether network time synchronization " - "shall be enabled." - msgstr "打开或关闭网络时间同步需要认证。" - --#: ../src/core/dbus-unit.c:430 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "启动“$(unit)”需要认证。" - --#: ../src/core/dbus-unit.c:431 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "停止“$(unit)”需要认证。" - --#: ../src/core/dbus-unit.c:432 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "重新载入“$(unit)”需要认证。" - --#: ../src/core/dbus-unit.c:433 ../src/core/dbus-unit.c:434 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "重新启动“$(unit)”需要认证。" - --#: ../src/core/dbus-unit.c:537 --msgid "Authentication is required to kill '$(unit)'." --msgstr "杀死“$(unit)”需要认证。" -+#: src/core/dbus-unit.c:538 -+#, fuzzy -+#| msgid "Authentication is required to set properties on '$(unit)'." -+msgid "" -+"Authentication is required to send a UNIX signal to the processes of " -+"'$(unit)'." -+msgstr "设置“$(unit)”的属性需要认证。" - --#: ../src/core/dbus-unit.c:567 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "重置“$(unit)”的失败(\"failed\")状态需要认证。" - --#: ../src/core/dbus-unit.c:599 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "设置“$(unit)”的属性需要认证。" -+ -+#: src/core/dbus-unit.c:711 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to delete files and directories associated with " -+"'$(unit)'." -+msgstr "重置“$(unit)”的失败(\"failed\")状态需要认证。" -+ -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to reset the \"failed\" state of '$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "重置“$(unit)”的失败(\"failed\")状态需要认证。" -+ -+#~ msgid "Authentication is required to kill '$(unit)'." -+#~ msgstr "杀死“$(unit)”需要认证。" -diff --git a/po/zh_TW.po b/po/zh_TW.po -index ac6cd99..c765b36 100644 ---- a/po/zh_TW.po -+++ b/po/zh_TW.po -@@ -7,7 +7,7 @@ msgid "" - msgstr "" - "Project-Id-Version: \n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2019-10-23 19:12+0800\n" -+"POT-Creation-Date: 2020-08-19 18:02+0200\n" - "PO-Revision-Date: 2019-10-23 19:19+0800\n" - "Last-Translator: pan93412 \n" - "Language-Team: Chinese \n" -@@ -61,6 +61,70 @@ msgstr "重新載入 systemd 狀態" - msgid "Authentication is required to reload the systemd state." - msgstr "重新載入 systemd 狀態需要驗證。" - -+#: src/home/org.freedesktop.home1.policy:13 -+msgid "Create a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:14 -+#, fuzzy -+#| msgid "Authentication is required to set NTP servers." -+msgid "Authentication is required to create a user's home area." -+msgstr "設定 NTP 伺服器需要身份驗證。" -+ -+#: src/home/org.freedesktop.home1.policy:23 -+msgid "Remove a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:24 -+#, fuzzy -+#| msgid "Authentication is required to set NTP servers." -+msgid "Authentication is required to remove a user's home area." -+msgstr "設定 NTP 伺服器需要身份驗證。" -+ -+#: src/home/org.freedesktop.home1.policy:33 -+msgid "Check credentials of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:34 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to attach or detach a portable service image." -+msgid "" -+"Authentication is required to check credentials against a user's home area." -+msgstr "連結或取消連結可攜式服務映像需要身份驗證。" -+ -+#: src/home/org.freedesktop.home1.policy:43 -+msgid "Update a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:44 -+#, fuzzy -+#| msgid "Authentication is required to attach a device to a seat." -+msgid "Authentication is required to update a user's home area." -+msgstr "將設備連接到座位需要驗證。" -+ -+#: src/home/org.freedesktop.home1.policy:53 -+msgid "Resize a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:54 -+#, fuzzy -+#| msgid "Authentication is required to set NTP servers." -+msgid "Authentication is required to resize a user's home area." -+msgstr "設定 NTP 伺服器需要身份驗證。" -+ -+#: src/home/org.freedesktop.home1.policy:63 -+msgid "Change password of a home area" -+msgstr "" -+ -+#: src/home/org.freedesktop.home1.policy:64 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to manage active sessions, users and seats." -+msgid "" -+"Authentication is required to change the password of a user's home area." -+msgstr "管理活躍的工作階段、使用者與座位需要驗證。" -+ - #: src/hostname/org.freedesktop.hostname1.policy:20 - msgid "Set hostname" - msgstr "設定主機名稱" -@@ -247,8 +311,7 @@ msgid "Flush device to seat attachments" - msgstr "暴露裝置以安裝附件" - - #: src/login/org.freedesktop.login1.policy:149 --msgid "" --"Authentication is required to reset how devices are attached to seats." -+msgid "Authentication is required to reset how devices are attached to seats." - msgstr "要重置裝置如何連接到座位需要驗證。" - - #: src/login/org.freedesktop.login1.policy:158 -@@ -275,8 +338,8 @@ msgstr "當應用程式阻止系統電源關閉時將其關閉" - - #: src/login/org.freedesktop.login1.policy:181 - msgid "" --"Authentication is required to power off the system while an application " --"is inhibiting this." -+"Authentication is required to power off the system while an application is " -+"inhibiting this." - msgstr "當應用程式阻止系統電源關閉時將系統電源關閉需要驗證。" - - #: src/login/org.freedesktop.login1.policy:191 -@@ -293,8 +356,8 @@ msgstr "在有其他使用者登入時重新啟動系統" - - #: src/login/org.freedesktop.login1.policy:203 - msgid "" --"Authentication is required to reboot the system while other users are " --"logged in." -+"Authentication is required to reboot the system while other users are logged " -+"in." - msgstr "在有其他使用者登入時重新啟動系統需要驗證。" - - #: src/login/org.freedesktop.login1.policy:213 -@@ -303,8 +366,8 @@ msgstr "當應用程式阻止重新啟動系統時將系統重新啟動" - - #: src/login/org.freedesktop.login1.policy:214 - msgid "" --"Authentication is required to reboot the system while an application " --"is inhibiting this." -+"Authentication is required to reboot the system while an application is " -+"inhibiting this." - msgstr "當應用程式阻止系統重新啟動時將系統重新啟動需要驗證。" - - #: src/login/org.freedesktop.login1.policy:224 -@@ -321,8 +384,8 @@ msgstr "在其他使用者登入時停止系統" - - #: src/login/org.freedesktop.login1.policy:236 - msgid "" --"Authentication is required to halt the system while other users are " --"logged in." -+"Authentication is required to halt the system while other users are logged " -+"in." - msgstr "在其他使用者登入時停止系統需要身份驗證。" - - #: src/login/org.freedesktop.login1.policy:246 -@@ -330,10 +393,14 @@ msgid "Halt the system while an application is inhibiting this" - msgstr "在應用程式阻止時停止系統" - - #: src/login/org.freedesktop.login1.policy:247 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to hibernate the system while an application " -+#| "is inhibiting this." - msgid "" --"Authentication is required to halt the system while an application asked " --"to inhibit it." --msgstr "在應用程式阻止時停止系統需要身份驗證。" -+"Authentication is required to halt the system while an application is " -+"inhibiting this." -+msgstr "當應用程式阻止系統冬眠時將系統冬眠需要驗證。" - - #: src/login/org.freedesktop.login1.policy:257 - msgid "Suspend the system" -@@ -359,8 +426,8 @@ msgstr "當應用程式阻止暫停系統時將系統暫停" - - #: src/login/org.freedesktop.login1.policy:279 - msgid "" --"Authentication is required to suspend the system while an application " --"is inhibiting this." -+"Authentication is required to suspend the system while an application is " -+"inhibiting this." - msgstr "當應用程式阻止系統暫停時將系統暫停需要驗證。" - - #: src/login/org.freedesktop.login1.policy:289 -@@ -387,8 +454,8 @@ msgstr "當應用程式阻止冬眠系統時將系統冬眠" - - #: src/login/org.freedesktop.login1.policy:311 - msgid "" --"Authentication is required to hibernate the system while an application " --"is inhibiting this." -+"Authentication is required to hibernate the system while an application is " -+"inhibiting this." - msgstr "當應用程式阻止系統冬眠時將系統冬眠需要驗證。" - - #: src/login/org.freedesktop.login1.policy:321 -@@ -396,8 +463,7 @@ msgid "Manage active sessions, users and seats" - msgstr "管理活躍的工作階段、使用者與座位" - - #: src/login/org.freedesktop.login1.policy:322 --msgid "" --"Authentication is required to manage active sessions, users and seats." -+msgid "Authentication is required to manage active sessions, users and seats." - msgstr "管理活躍的工作階段、使用者與座位需要驗證。" - - #: src/login/org.freedesktop.login1.policy:331 -@@ -454,6 +520,16 @@ msgstr "設定 wall 訊息" - msgid "Authentication is required to set a wall message" - msgstr "設定 wall 訊息需要身份驗證" - -+#: src/login/org.freedesktop.login1.policy:395 -+msgid "Change Session" -+msgstr "" -+ -+#: src/login/org.freedesktop.login1.policy:396 -+#, fuzzy -+#| msgid "Authentication is required to halt the system." -+msgid "Authentication is required to change the virtual terminal." -+msgstr "停止系統需要身份驗證。" -+ - #: src/machine/org.freedesktop.machine1.policy:22 - msgid "Log into a local container" - msgstr "登入到本機容器" -@@ -627,13 +703,45 @@ msgid "Authentication is required to reset DNS settings." - msgstr "重設 DNS 設定需要身份驗證。" - - #: src/network/org.freedesktop.network1.policy:143 -+msgid "DHCP server sends force renew message" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:144 -+#, fuzzy -+#| msgid "Authentication is required to set a wall message" -+msgid "Authentication is required to send force renew message." -+msgstr "設定 wall 訊息需要身份驗證" -+ -+#: src/network/org.freedesktop.network1.policy:154 - msgid "Renew dynamic addresses" - msgstr "重新產生動態位址" - --#: src/network/org.freedesktop.network1.policy:144 -+#: src/network/org.freedesktop.network1.policy:155 - msgid "Authentication is required to renew dynamic addresses." - msgstr "重新產生動態位址需要身份驗證。" - -+#: src/network/org.freedesktop.network1.policy:165 -+#, fuzzy -+#| msgid "Revert NTP settings" -+msgid "Reload network settings" -+msgstr "還原 NTP 設定" -+ -+#: src/network/org.freedesktop.network1.policy:166 -+#, fuzzy -+#| msgid "Authentication is required to reset NTP settings." -+msgid "Authentication is required to reload network settings." -+msgstr "重設 NTP 設定需要身份驗證。" -+ -+#: src/network/org.freedesktop.network1.policy:176 -+msgid "Reconfigure network interface" -+msgstr "" -+ -+#: src/network/org.freedesktop.network1.policy:177 -+#, fuzzy -+#| msgid "Authentication is required to reboot the system." -+msgid "Authentication is required to reconfigure network interface." -+msgstr "重新啟動系統需要驗證。" -+ - #: src/portable/org.freedesktop.portable1.policy:13 - msgid "Inspect a portable service image" - msgstr "檢查可攜式服務映像" -@@ -720,41 +828,55 @@ msgid "" - "shall be enabled." - msgstr "控制網路時間同步是否啟用需要驗證。" - --#: src/core/dbus-unit.c:354 -+#: src/core/dbus-unit.c:362 - msgid "Authentication is required to start '$(unit)'." - msgstr "啟動 '$(unit)' 需要驗證。" - --#: src/core/dbus-unit.c:355 -+#: src/core/dbus-unit.c:363 - msgid "Authentication is required to stop '$(unit)'." - msgstr "停止 '$(unit)' 需要驗證。" - --#: src/core/dbus-unit.c:356 -+#: src/core/dbus-unit.c:364 - msgid "Authentication is required to reload '$(unit)'." - msgstr "重新載入 '$(unit)' 需要驗證。" - --#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358 -+#: src/core/dbus-unit.c:365 src/core/dbus-unit.c:366 - msgid "Authentication is required to restart '$(unit)'." - msgstr "重新啟動 '$(unit)' 需要驗證。" - --#: src/core/dbus-unit.c:530 -+#: src/core/dbus-unit.c:538 - msgid "" - "Authentication is required to send a UNIX signal to the processes of " - "'$(unit)'." - msgstr "傳送 UNIX 信號至「$(unit)」的程序需要身份驗證。" - --#: src/core/dbus-unit.c:561 -+#: src/core/dbus-unit.c:569 - msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." - msgstr "重置 '$(unit)' 的「失敗」狀態需要驗證。" - --#: src/core/dbus-unit.c:594 -+#: src/core/dbus-unit.c:602 - msgid "Authentication is required to set properties on '$(unit)'." - msgstr "在 '$(unit)' 上設定屬性需要驗證。" - --#: src/core/dbus-unit.c:703 -+#: src/core/dbus-unit.c:711 - msgid "" - "Authentication is required to delete files and directories associated with " - "'$(unit)'." - msgstr "刪除與 '$(unit)' 相關的檔案及目錄需要身份驗證。" - -+#: src/core/dbus-unit.c:760 -+#, fuzzy -+#| msgid "" -+#| "Authentication is required to send a UNIX signal to the processes of " -+#| "'$(unit)'." -+msgid "" -+"Authentication is required to freeze or thaw the processes of '$(unit)' unit." -+msgstr "傳送 UNIX 信號至「$(unit)」的程序需要身份驗證。" -+ -+#~ msgid "" -+#~ "Authentication is required to halt the system while an application asked " -+#~ "to inhibit it." -+#~ msgstr "在應用程式阻止時停止系統需要身份驗證。" -+ - #~ msgid "Authentication is required to kill '$(unit)'." - #~ msgstr "砍除 '$(unit)' 需要驗證。" -diff --git a/rules.d/meson.build b/rules.d/meson.build -index ca4445d..b4640ab 100644 ---- a/rules.d/meson.build -+++ b/rules.d/meson.build -@@ -21,10 +21,13 @@ rules = files(''' - 75-net-description.rules - 75-probe_mtd.rules - 78-sound-card.rules -- 80-drivers.rules - 80-net-setup-link.rules - '''.split()) - -+if conf.get('HAVE_KMOD') == 1 -+ rules += files('80-drivers.rules') -+endif -+ - install_data(rules, - install_dir : udevrulesdir) - -diff --git a/shell-completion/bash/homectl b/shell-completion/bash/homectl -index c2a9e61..1a1d522 100644 ---- a/shell-completion/bash/homectl -+++ b/shell-completion/bash/homectl -@@ -139,7 +139,7 @@ _homectl() { - comps=$(cat /etc/shells) - ;; - --fs-type) -- comps='ext4 xfs btrsf' -+ comps='btrfs ext4 xfs' - ;; - --cifs-user-name) - comps=$(compgen -A user -- "$cur" ) -diff --git a/shell-completion/bash/resolvectl b/shell-completion/bash/resolvectl -index d4ac339..54b241c 100644 ---- a/shell-completion/bash/resolvectl -+++ b/shell-completion/bash/resolvectl -@@ -48,6 +48,7 @@ _resolvectl() { - [DNSSEC]='dnssec' - [DNSOVERTLS]='dnsovertls' - [STANDALONE]='statistics reset-statistics flush-caches reset-server-features' -+ [LOG_LEVEL]='log-level' - ) - local -A ARGS=( - [FAMILY]='tcp udp sctp' -@@ -95,6 +96,9 @@ _resolvectl() { - elif __contains_word "$verb" ${VERBS[STATUS]}; then - comps="$interfaces" - -+ elif __contains_word "$verb" ${VERBS[LOG_LEVEL]}; then -+ comps='debug info notice warning err crit alert emerg' -+ - elif __contains_word "$verb" ${VERBS[FAMILY]}; then - for ((i++; i < COMP_CWORD; i++)); do - if __contains_word "${COMP_WORDS[i]}" ${ARGS[FAMILY]} && -diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in -index fdbe32e..b5bd727 100644 ---- a/shell-completion/bash/systemctl.in -+++ b/shell-completion/bash/systemctl.in -@@ -127,7 +127,7 @@ _systemctl () { - --quiet -q --system --user --version --runtime --recursive -r --firmware-setup - --show-types -i --ignore-inhibitors --plain --failed --value --fail --dry-run --wait' - [ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root -- --preset-mode -n --lines -o --output -M --machine --message' -+ --preset-mode -n --lines -o --output -M --machine --message --timestamp' - ) - - if __contains_word "--user" ${COMP_WORDS[*]}; then -@@ -176,6 +176,9 @@ _systemctl () { - --machine|-M) - comps=$( __get_machines ) - ;; -+ --timestamp) -+ comps='pretty us µs utc us+utc µs+utc' -+ ;; - esac - COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) - return 0 -diff --git a/shell-completion/zsh/_journalctl b/shell-completion/zsh/_journalctl -index 43bec9b..ecc5d08 100644 ---- a/shell-completion/zsh/_journalctl -+++ b/shell-completion/zsh/_journalctl -@@ -26,11 +26,11 @@ _journalctl_fields() { - _journalctl_none() { - local -a _commands _files _jrnl_none - # Setting use-cache will slow this down considerably -- _commands=( ${"$(_call_program commands "$service $_sys_service_mgr -F _EXE" 2>/dev/null)"} ) -+ _commands=( ${(f)"$(_call_program commands "$service $_sys_service_mgr -F _EXE" 2>/dev/null)"} ) - _jrnl_none='yes' - _alternative : \ - 'files:/dev files:_files -W /dev -P /dev/' \ -- "commands:commands:($_commands[@])" \ -+ 'commands:commands:compadd -a _commands' \ - 'fields:fields:_journalctl_fields' - } - -diff --git a/shell-completion/zsh/_networkctl b/shell-completion/zsh/_networkctl -index 4995bd3..13c8009 100644 ---- a/shell-completion/zsh/_networkctl -+++ b/shell-completion/zsh/_networkctl -@@ -6,9 +6,16 @@ - local -a _networkctl_cmds - _networkctl_cmds=( - 'list:List existing links' -- 'status:Show information about the specified links' -- 'lldp:Show Link Layer Discovery Protocol status' -- 'label:Show address labels' -+ 'status:Show information about the specified links' -+ 'lldp:Show Link Layer Discovery Protocol status' -+ 'label:Show address labels' -+ 'delete:Delete virtual netdevs' -+ 'up:Bring devices up' -+ 'down:Bring devices down' -+ 'renew:Renew dynamic configurations' -+ 'forcerenew:Trigger DHCP reconfiguration of all connected clients' -+ 'reconfigure:Reconfigure interfaces' -+ 'reload:Reload .network and .netdev files' - ) - if (( CURRENT == 1 )); then - _describe -t commands 'networkctl command' _networkctl_cmds -@@ -16,16 +23,19 @@ - local curcontext="$curcontext" - local -a _links - cmd="${${_networkctl_cmds[(r)$words[1]:*]%%:*}}" -- if [ $cmd = "status" ]; then -- _links=( "${(foa)$(networkctl list --no-legend | awk 'BEGIN{OFS=":"} {sub(/[[ \t]+/, ""); print $2,$0}' 2>/dev/null)}" ) -- if [[ -n "$_links" ]]; then -- _describe -t links 'links' _links -- else -- _message "no links" -- fi -- else -- _message "no more options" -- fi -+ case $cmd in -+ (list|status|up|down|lldp|delete|renew|forcerenew|reconfigure) -+ _links=( "${(foa)$(networkctl list --no-legend | awk 'BEGIN{OFS=":"} {sub(/[[ \t]+/, ""); print $2,$0}' 2>/dev/null)}" ) -+ if [[ -n "$_links" ]]; then -+ _describe -t links 'links' _links -+ else -+ _message "no links" -+ fi -+ ;; -+ *) -+ _message "no more options" -+ ;; -+ esac - fi - } - -diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in -index 582d469..c59beb1 100644 ---- a/shell-completion/zsh/_systemctl.in -+++ b/shell-completion/zsh/_systemctl.in -@@ -431,6 +431,13 @@ done - _values -s , "${_modes[@]}" - } - -+(( $+functions[_systemctl_timestamp] )) || -+ _systemctl_timestamp() { -+ local -a _styles -+ _styles=(help pretty us µs utc us+utc µs+utc) -+ _values -s , "${_styles[@]}" -+ } -+ - # Build arguments for "systemctl" to be used in completion. - local -a _modes; _modes=("--user" "--system") - # Use the last mode (they are exclusive and the last one is used). -@@ -471,4 +478,5 @@ _arguments -s \ - '--firmware-setup[Tell the firmware to show the setup menu on next boot]' \ - '--plain[When used with list-dependencies, print output as a list]' \ - '--failed[Show failed units]' \ -+ '--timestamp=[Change format of printed timestamps]:style:_systemctl_timestamp' \ - '*::systemctl command:_systemctl_commands' -diff --git a/src/analyze/analyze-condition.c b/src/analyze/analyze-condition.c -index 52ad382..e1365e1 100644 ---- a/src/analyze/analyze-condition.c -+++ b/src/analyze/analyze-condition.c -@@ -8,83 +8,27 @@ - #include "load-fragment.h" - #include "service.h" - --typedef struct condition_definition { -- const char *name; -- ConfigParserCallback parser; -- ConditionType type; --} condition_definition; -- --static const condition_definition condition_definitions[] = { -- { "ConditionPathExists", config_parse_unit_condition_path, CONDITION_PATH_EXISTS }, -- { "ConditionPathExistsGlob", config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB }, -- { "ConditionPathIsDirectory", config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY }, -- { "ConditionPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, -- { "ConditionPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, -- { "ConditionPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, -- { "ConditionPathIsEncrypted", config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED }, -- { "ConditionDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, -- { "ConditionFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, -- { "ConditionFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, -- { "ConditionNeedsUpdate", config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE }, -- { "ConditionFirstBoot", config_parse_unit_condition_string, CONDITION_FIRST_BOOT }, -- { "ConditionKernelCommandLine", config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE }, -- { "ConditionKernelVersion", config_parse_unit_condition_string, CONDITION_KERNEL_VERSION }, -- { "ConditionArchitecture", config_parse_unit_condition_string, CONDITION_ARCHITECTURE }, -- { "ConditionVirtualization", config_parse_unit_condition_string, CONDITION_VIRTUALIZATION }, -- { "ConditionSecurity", config_parse_unit_condition_string, CONDITION_SECURITY }, -- { "ConditionCapability", config_parse_unit_condition_string, CONDITION_CAPABILITY }, -- { "ConditionHost", config_parse_unit_condition_string, CONDITION_HOST }, -- { "ConditionACPower", config_parse_unit_condition_string, CONDITION_AC_POWER }, -- { "ConditionUser", config_parse_unit_condition_string, CONDITION_USER }, -- { "ConditionGroup", config_parse_unit_condition_string, CONDITION_GROUP }, -- { "ConditionControlGroupController", config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER }, -- -- { "AssertPathExists", config_parse_unit_condition_path, CONDITION_PATH_EXISTS }, -- { "AssertPathExistsGlob", config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB }, -- { "AssertPathIsDirectory", config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY }, -- { "AssertPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, -- { "AssertPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, -- { "AssertPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, -- { "AssertPathIsEncrypted", config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED }, -- { "AssertDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, -- { "AssertFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, -- { "AssertFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, -- { "AssertNeedsUpdate", config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE }, -- { "AssertFirstBoot", config_parse_unit_condition_string, CONDITION_FIRST_BOOT }, -- { "AssertKernelCommandLine", config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE }, -- { "AssertKernelVersion", config_parse_unit_condition_string, CONDITION_KERNEL_VERSION }, -- { "AssertArchitecture", config_parse_unit_condition_string, CONDITION_ARCHITECTURE }, -- { "AssertVirtualization", config_parse_unit_condition_string, CONDITION_VIRTUALIZATION }, -- { "AssertSecurity", config_parse_unit_condition_string, CONDITION_SECURITY }, -- { "AssertCapability", config_parse_unit_condition_string, CONDITION_CAPABILITY }, -- { "AssertHost", config_parse_unit_condition_string, CONDITION_HOST }, -- { "AssertACPower", config_parse_unit_condition_string, CONDITION_AC_POWER }, -- { "AssertUser", config_parse_unit_condition_string, CONDITION_USER }, -- { "AssertGroup", config_parse_unit_condition_string, CONDITION_GROUP }, -- { "AssertControlGroupController", config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER }, -- -- /* deprecated, but we should still parse them */ -- { "ConditionNull", config_parse_unit_condition_null, 0 }, -- { "AssertNull", config_parse_unit_condition_null, 0 }, --}; -- - static int parse_condition(Unit *u, const char *line) { -- const char *p; -- Condition **target; -- -- if ((p = startswith(line, "Condition"))) -- target = &u->conditions; -- else if ((p = startswith(line, "Assert"))) -- target = &u->asserts; -- else -- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); -- -- for (size_t i = 0; i < ELEMENTSOF(condition_definitions); i++) { -- const condition_definition *c = &condition_definitions[i]; -- -- p = startswith(line, c->name); -- if (!p) -- continue; -+ assert(u); -+ assert(line); -+ -+ for (ConditionType t = 0; t < _CONDITION_TYPE_MAX; t++) { -+ ConfigParserCallback callback; -+ Condition **target; -+ const char *p, *name; -+ -+ name = condition_type_to_string(t); -+ p = startswith(line, name); -+ if (p) -+ target = &u->conditions; -+ else { -+ name = assert_type_to_string(t); -+ p = startswith(line, name); -+ if (!p) -+ continue; -+ -+ target = &u->asserts; -+ } - - p += strspn(p, WHITESPACE); - -@@ -94,7 +38,12 @@ static int parse_condition(Unit *u, const char *line) { - - p += strspn(p, WHITESPACE); - -- return c->parser(NULL, "(stdin)", 0, NULL, 0, c->name, c->type, p, target, u); -+ if (condition_takes_path(t)) -+ callback = config_parse_unit_condition_path; -+ else -+ callback = config_parse_unit_condition_string; -+ -+ return callback(NULL, "(cmdline)", 0, NULL, 0, name, t, p, target, u); - } - - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); -diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c -index d4996c3..16ab4f8 100644 ---- a/src/analyze/analyze-security.c -+++ b/src/analyze/analyze-security.c -@@ -50,6 +50,8 @@ struct security_info { - bool ip_filters_custom_egress; - - char *keyring_mode; -+ char *protect_proc; -+ char *proc_subset; - bool lock_personality; - bool memory_deny_write_execute; - bool no_new_privileges; -@@ -135,6 +137,8 @@ static void security_info_free(struct security_info *i) { - free(i->root_image); - - free(i->keyring_mode); -+ free(i->protect_proc); -+ free(i->proc_subset); - free(i->notify_access); - - free(i->device_policy); -@@ -388,6 +392,44 @@ static int assess_keyring_mode( - return 0; - } - -+static int assess_protect_proc( -+ const struct security_assessor *a, -+ const struct security_info *info, -+ const void *data, -+ uint64_t *ret_badness, -+ char **ret_description) { -+ -+ assert(ret_badness); -+ assert(ret_description); -+ -+ if (streq_ptr(info->protect_proc, "noaccess")) -+ *ret_badness = 1; -+ else if (STRPTR_IN_SET(info->protect_proc, "invisible", "ptraceable")) -+ *ret_badness = 0; -+ else -+ *ret_badness = 3; -+ -+ *ret_description = NULL; -+ -+ return 0; -+} -+ -+static int assess_proc_subset( -+ const struct security_assessor *a, -+ const struct security_info *info, -+ const void *data, -+ uint64_t *ret_badness, -+ char **ret_description) { -+ -+ assert(ret_badness); -+ assert(ret_description); -+ -+ *ret_badness = !streq_ptr(info->proc_subset, "pid"); -+ *ret_description = NULL; -+ -+ return 0; -+} -+ - static int assess_notify_access( - const struct security_assessor *a, - const struct security_info *info, -@@ -493,7 +535,7 @@ static int assess_system_call_architectures( - - #if HAVE_SECCOMP - --static bool syscall_names_in_filter(Set *s, bool allow_list, const SyscallFilterSet *f) { -+static bool syscall_names_in_filter(Set *s, bool allow_list, const SyscallFilterSet *f, const char **ret_offending_syscall) { - const char *syscall; - - NULSTR_FOREACH(syscall, f->value) { -@@ -503,7 +545,7 @@ static bool syscall_names_in_filter(Set *s, bool allow_list, const SyscallFilter - const SyscallFilterSet *g; - - assert_se(g = syscall_filter_set_find(syscall)); -- if (syscall_names_in_filter(s, allow_list, g)) -+ if (syscall_names_in_filter(s, allow_list, g, ret_offending_syscall)) - return true; /* bad! */ - - continue; -@@ -516,10 +558,13 @@ static bool syscall_names_in_filter(Set *s, bool allow_list, const SyscallFilter - - if (set_contains(s, syscall) == allow_list) { - log_debug("Offending syscall filter item: %s", syscall); -+ if (ret_offending_syscall) -+ *ret_offending_syscall = syscall; - return true; /* bad! */ - } - } - -+ *ret_offending_syscall = NULL; - return false; - } - -@@ -530,43 +575,49 @@ static int assess_system_call_filter( - uint64_t *ret_badness, - char **ret_description) { - -- const SyscallFilterSet *f; -- char *d = NULL; -- uint64_t b; -- - assert(a); - assert(info); - assert(ret_badness); - assert(ret_description); - - assert(a->parameter < _SYSCALL_FILTER_SET_MAX); -- f = syscall_filter_sets + a->parameter; -+ const SyscallFilterSet *f = syscall_filter_sets + a->parameter; -+ -+ char *d = NULL; -+ uint64_t b; - - if (!info->system_call_filter_allow_list && set_isempty(info->system_call_filter)) { - d = strdup("Service does not filter system calls"); - b = 10; - } else { - bool bad; -+ const char *offender = NULL; - - log_debug("Analyzing system call filter, checking against: %s", f->name); -- bad = syscall_names_in_filter(info->system_call_filter, info->system_call_filter_allow_list, f); -+ bad = syscall_names_in_filter(info->system_call_filter, info->system_call_filter_allow_list, f, &offender); - log_debug("Result: %s", bad ? "bad" : "good"); - - if (info->system_call_filter_allow_list) { - if (bad) { -- (void) asprintf(&d, "System call allow list defined for service, and %s is included", f->name); -+ (void) asprintf(&d, "System call allow list defined for service, and %s is included " -+ "(e.g. %s is allowed)", -+ f->name, offender); - b = 9; - } else { -- (void) asprintf(&d, "System call allow list defined for service, and %s is not included", f->name); -+ (void) asprintf(&d, "System call allow list defined for service, and %s is not included", -+ f->name); - b = 0; - } - } else { - if (bad) { -- (void) asprintf(&d, "System call deny list defined for service, and %s is not included", f->name); -+ (void) asprintf(&d, "System call deny list defined for service, and %s is not included " -+ "(e.g. %s is allowed)", -+ f->name, offender); - b = 10; - } else { -- (void) asprintf(&d, "System call deny list defined for service, and %s is included", f->name); -- b = 5; -+ (void) asprintf(&d, "System call deny list defined for service, and %s is included", -+ f->name); -+ b = 0; - } - } - } -@@ -1140,6 +1191,24 @@ static const struct security_assessor security_assessor_table[] = { - .range = 1, - .assess = assess_keyring_mode, - }, -+ { -+ .id = "ProtectProc=", -+ .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectProc=", -+ .description_good = "Service has restricted access to process tree (/proc hidepid=)", -+ .description_bad = "Service has full access to process tree (/proc hidepid=)", -+ .weight = 1000, -+ .range = 3, -+ .assess = assess_protect_proc, -+ }, -+ { -+ .id = "ProcSubset=", -+ .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProcSubset=", -+ .description_good = "Service has no access to non-process /proc files (/proc subset=)", -+ .description_bad = "Service has full access to non-process /proc files (/proc subset=)", -+ .weight = 10, -+ .range = 1, -+ .assess = assess_proc_subset, -+ }, - { - .id = "NotifyAccess=", - .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NotifyAccess=", -@@ -1899,6 +1968,8 @@ static int acquire_security_info(sd_bus *bus, const char *name, struct security_ - { "IPEgressFilterPath", "as", property_read_ip_filters, 0 }, - { "Id", "s", NULL, offsetof(struct security_info, id) }, - { "KeyringMode", "s", NULL, offsetof(struct security_info, keyring_mode) }, -+ { "ProtectProc", "s", NULL, offsetof(struct security_info, protect_proc) }, -+ { "ProcSubset", "s", NULL, offsetof(struct security_info, proc_subset) }, - { "LoadState", "s", NULL, offsetof(struct security_info, load_state) }, - { "LockPersonality", "b", NULL, offsetof(struct security_info, lock_personality) }, - { "MemoryDenyWriteExecute", "b", NULL, offsetof(struct security_info, memory_deny_write_execute) }, -diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c -index 30cb79d..9350648 100644 ---- a/src/analyze/analyze-verify.c -+++ b/src/analyze/analyze-verify.c -@@ -223,7 +223,7 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run - _cleanup_(manager_freep) Manager *m = NULL; - Unit *units[strv_length(filenames)]; - _cleanup_free_ char *var = NULL; -- int r = 0, k, i, count = 0; -+ int r, k, i, count = 0; - char **filename; - - if (strv_isempty(filenames)) -diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c -index 9d64e3c..a9e4b37 100644 ---- a/src/analyze/analyze.c -+++ b/src/analyze/analyze.c -@@ -21,6 +21,8 @@ - #include "bus-map-properties.h" - #include "bus-unit-util.h" - #include "calendarspec.h" -+#include "cap-list.h" -+#include "capability-util.h" - #include "conf-files.h" - #include "copy.h" - #include "def.h" -@@ -899,7 +901,7 @@ static bool times_in_range(const struct unit_times *times, const struct boot_tim - static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level, char ***units, unsigned branches) { - _cleanup_strv_free_ char **deps = NULL; - char **c; -- int r = 0; -+ int r; - usec_t service_longest = 0; - int to_print = 0; - struct unit_times *times; -@@ -1498,7 +1500,6 @@ static int do_unit_files(int argc, char *argv[], void *userdata) { - _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; - _cleanup_hashmap_free_ Hashmap *unit_names = NULL; - char **patterns = strv_skip(argv, 1); -- Iterator i; - const char *k, *dst; - char **v; - int r; -@@ -1511,7 +1512,7 @@ static int do_unit_files(int argc, char *argv[], void *userdata) { - if (r < 0) - return log_error_errno(r, "unit_file_build_name_map() failed: %m"); - -- HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) { -+ HASHMAP_FOREACH_KEY(dst, k, unit_ids) { - if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && - !strv_fnmatch_or_empty(patterns, dst, FNM_NOESCAPE)) - continue; -@@ -1519,7 +1520,7 @@ static int do_unit_files(int argc, char *argv[], void *userdata) { - printf("ids: %s → %s\n", k, dst); - } - -- HASHMAP_FOREACH_KEY(v, k, unit_names, i) { -+ HASHMAP_FOREACH_KEY(v, k, unit_names) { - if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && - !strv_fnmatch_strv_or_empty(patterns, v, FNM_NOESCAPE)) - continue; -@@ -1576,7 +1577,7 @@ static int dump_exit_status(int argc, char *argv[], void *userdata) { - - status = exit_status_from_string(argv[i]); - if (status < 0) -- return log_error_errno(r, "Invalid exit status \"%s\": %m", argv[i]); -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid exit status \"%s\".", argv[i]); - - assert(status >= 0 && (size_t) status < ELEMENTSOF(exit_status_mappings)); - r = table_add_many(table, -@@ -1592,6 +1593,51 @@ static int dump_exit_status(int argc, char *argv[], void *userdata) { - return table_print(table, NULL); - } - -+static int dump_capabilities(int argc, char *argv[], void *userdata) { -+ _cleanup_(table_unrefp) Table *table = NULL; -+ unsigned last_cap; -+ int r; -+ -+ table = table_new("name", "number"); -+ if (!table) -+ return log_oom(); -+ -+ (void) table_set_align_percent(table, table_get_cell(table, 0, 1), 100); -+ -+ /* Determine the maximum of the last cap known by the kernel and by us */ -+ last_cap = MAX((unsigned) CAP_LAST_CAP, cap_last_cap()); -+ -+ if (strv_isempty(strv_skip(argv, 1))) -+ for (unsigned c = 0; c <= last_cap; c++) { -+ r = table_add_many(table, -+ TABLE_STRING, capability_to_name(c) ?: "cap_???", -+ TABLE_UINT, c); -+ if (r < 0) -+ return table_log_add_error(r); -+ } -+ else { -+ for (int i = 1; i < argc; i++) { -+ int c; -+ -+ c = capability_from_name(argv[i]); -+ if (c < 0 || (unsigned) c > last_cap) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Capability \"%s\" not known.", argv[i]); -+ -+ r = table_add_many(table, -+ TABLE_STRING, capability_to_name(c) ?: "cap_???", -+ TABLE_UINT, (unsigned) c); -+ if (r < 0) -+ return table_log_add_error(r); -+ } -+ -+ (void) table_set_sort(table, (size_t) 1, (size_t) -1); -+ } -+ -+ (void) pager_open(arg_pager_flags); -+ -+ return table_print(table, NULL); -+} -+ - #if HAVE_SECCOMP - - static int load_kernel_syscalls(Set **ret) { -@@ -2126,6 +2172,7 @@ static int help(int argc, char *argv[], void *userdata) { - " unit-files List files and symlinks for units\n" - " unit-paths List load directories for units\n" - " exit-status [STATUS...] List exit status definitions\n" -+ " capability [CAP...] List capability definitions\n" - " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n" - " condition CONDITION... Evaluate conditions and asserts\n" - " verify FILE... Check unit files for correctness\n" -@@ -2363,6 +2410,7 @@ static int run(int argc, char *argv[]) { - { "unit-paths", 1, 1, 0, dump_unit_paths }, - { "exit-status", VERB_ANY, VERB_ANY, 0, dump_exit_status }, - { "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters }, -+ { "capability", VERB_ANY, VERB_ANY, 0, dump_capabilities }, - { "condition", 2, VERB_ANY, 0, do_condition }, - { "verify", 2, VERB_ANY, 0, do_verify }, - { "calendar", 2, VERB_ANY, 0, test_calendar }, -diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c -index 3a64436..682c719 100644 ---- a/src/backlight/backlight.c -+++ b/src/backlight/backlight.c -@@ -13,11 +13,36 @@ - #include "main-func.h" - #include "mkdir.h" - #include "parse-util.h" -+#include "pretty-print.h" -+#include "terminal-util.h" - #include "reboot-util.h" - #include "string-util.h" - #include "strv.h" - #include "util.h" - -+static int help(void) { -+ _cleanup_free_ char *link = NULL; -+ int r; -+ -+ r = terminal_urlify_man("systemd-backlight", "8", &link); -+ if (r < 0) -+ return log_oom(); -+ -+ printf("%s save [backlight|leds]:DEVICE\n" -+ "%s load [backlight|leds]:DEVICE\n" -+ "\n%sSave and restore backlight brightness at shutdown and boot.%s\n\n" -+ " save Save current brightness\n" -+ " load Set brightness to be the previously saved value\n" -+ "\nSee the %s for details.\n" -+ , program_invocation_short_name -+ , program_invocation_short_name -+ , ansi_highlight(), ansi_normal() -+ , link -+ ); -+ -+ return 0; -+} -+ - static int find_pci_or_platform_parent(sd_device *device, sd_device **ret) { - const char *subsystem, *sysname, *value; - sd_device *parent; -@@ -236,17 +261,13 @@ static int get_max_brightness(sd_device *device, unsigned *ret) { - * max_brightness in case of 'backlight' subsystem. This avoids preserving - * an unreadably dim screen, which would otherwise force the user to - * disable state restoration. */ --static int clamp_brightness(sd_device *device, char **value, unsigned max_brightness) { -- unsigned brightness, new_brightness, min_brightness; -+static int clamp_brightness(sd_device *device, bool saved, unsigned max_brightness, unsigned *brightness) { -+ unsigned new_brightness, min_brightness; - const char *subsystem; - int r; - -- assert(value); -- assert(*value); -- -- r = safe_atou(*value, &brightness); -- if (r < 0) -- return log_device_warning_errno(device, r, "Failed to parse brightness \"%s\": %m", *value); -+ assert(device); -+ assert(brightness); - - r = sd_device_get_subsystem(device, &subsystem); - if (r < 0) -@@ -257,22 +278,16 @@ static int clamp_brightness(sd_device *device, char **value, unsigned max_bright - else - min_brightness = 0; - -- new_brightness = CLAMP(brightness, min_brightness, max_brightness); -- if (new_brightness != brightness) { -- char *new_value; -- -- r = asprintf(&new_value, "%u", new_brightness); -- if (r < 0) -- return log_oom(); -- -- log_device_info(device, "Saved brightness %s %s to %s.", *value, -- new_brightness > brightness ? -+ new_brightness = CLAMP(*brightness, min_brightness, max_brightness); -+ if (new_brightness != *brightness) -+ log_device_info(device, "%s brightness %u is %s to %u.", -+ saved ? "Saved" : "Current", -+ *brightness, -+ new_brightness > *brightness ? - "too low; increasing" : "too high; decreasing", -- new_value); -- -- free_and_replace(*value, new_value); -- } -+ new_brightness); - -+ *brightness = new_brightness; - return 0; - } - -@@ -284,7 +299,8 @@ static bool shall_clamp(sd_device *d) { - - r = sd_device_get_property_value(d, "ID_BACKLIGHT_CLAMP", &s); - if (r < 0) { -- log_device_debug_errno(d, r, "Failed to get ID_BACKLIGHT_CLAMP property, ignoring: %m"); -+ if (r != -ENOENT) -+ log_device_debug_errno(d, r, "Failed to get ID_BACKLIGHT_CLAMP property, ignoring: %m"); - return true; - } - -@@ -297,31 +313,60 @@ static bool shall_clamp(sd_device *d) { - return r; - } - --static int read_brightness(sd_device *device, const char **ret) { -- const char *subsystem; -+static int read_brightness(sd_device *device, unsigned max_brightness, unsigned *ret_brightness) { -+ const char *subsystem, *value; -+ unsigned brightness; - int r; - - assert(device); -- assert(ret); -+ assert(ret_brightness); - - r = sd_device_get_subsystem(device, &subsystem); - if (r < 0) - return log_device_debug_errno(device, r, "Failed to get subsystem: %m"); - - if (streq(subsystem, "backlight")) { -- r = sd_device_get_sysattr_value(device, "actual_brightness", ret); -- if (r >= 0) -- return 0; -- if (r != -ENOENT) -+ r = sd_device_get_sysattr_value(device, "actual_brightness", &value); -+ if (r == -ENOENT) { -+ log_device_debug_errno(device, r, "Failed to read 'actual_brightness' attribute, " -+ "fall back to use 'brightness' attribute: %m"); -+ goto use_brightness; -+ } -+ if (r < 0) - return log_device_debug_errno(device, r, "Failed to read 'actual_brightness' attribute: %m"); - -- log_device_debug_errno(device, r, "Failed to read 'actual_brightness' attribute, fall back to use 'brightness' attribute: %m"); -+ r = safe_atou(value, &brightness); -+ if (r < 0) { -+ log_device_debug_errno(device, r, "Failed to parse 'actual_brightness' attribute, " -+ "fall back to use 'brightness' attribute: %s", value); -+ goto use_brightness; -+ } -+ -+ if (brightness > max_brightness) { -+ log_device_debug(device, "actual_brightness=%u is larger than max_brightness=%u, " -+ "fall back to use 'brightness' attribute", brightness, max_brightness); -+ goto use_brightness; -+ } -+ -+ *ret_brightness = brightness; -+ return 0; - } - -- r = sd_device_get_sysattr_value(device, "brightness", ret); -+use_brightness: -+ r = sd_device_get_sysattr_value(device, "brightness", &value); - if (r < 0) - return log_device_debug_errno(device, r, "Failed to read 'brightness' attribute: %m"); - -+ r = safe_atou(value, &brightness); -+ if (r < 0) -+ return log_device_debug_errno(device, r, "Failed to parse 'brightness' attribute: %s", value); -+ -+ if (brightness > max_brightness) -+ return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL), -+ "brightness=%u is larger than max_brightness=%u", -+ brightness, max_brightness); -+ -+ *ret_brightness = brightness; - return 0; - } - -@@ -329,11 +374,14 @@ static int run(int argc, char *argv[]) { - _cleanup_(sd_device_unrefp) sd_device *device = NULL; - _cleanup_free_ char *escaped_ss = NULL, *escaped_sysname = NULL, *escaped_path_id = NULL; - const char *sysname, *path_id, *ss, *saved; -- unsigned max_brightness; -+ unsigned max_brightness, brightness; - int r; - - log_setup_service(); - -+ if (strv_contains(strv_skip(argv, 1), "--help")) -+ return help(); -+ - if (argc != 3) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires two arguments."); - -@@ -403,44 +451,50 @@ static int run(int argc, char *argv[]) { - clamp = shall_clamp(device); - - r = read_one_line_file(saved, &value); -- if (IN_SET(r, -ENOENT, 0)) { -- const char *curval; -- -- /* Fallback to clamping current brightness or exit early if -- * clamping is not supported/enabled. */ -+ if (r < 0 && r != -ENOENT) -+ return log_error_errno(r, "Failed to read %s: %m", saved); -+ if (r > 0) { -+ r = safe_atou(value, &brightness); -+ if (r < 0) { -+ log_error_errno(r, "Failed to parse saved brightness '%s', removing %s.", -+ value, saved); -+ (void) unlink(saved); -+ } else { -+ if (clamp) -+ (void) clamp_brightness(device, true, max_brightness, &brightness); -+ -+ /* Do not fall back to read current brightness below. */ -+ r = 1; -+ } -+ } -+ if (r <= 0) { -+ /* Fallback to clamping current brightness or exit early if clamping is not -+ * supported/enabled. */ - if (!clamp) - return 0; - -- r = read_brightness(device, &curval); -+ r = read_brightness(device, max_brightness, &brightness); - if (r < 0) - return log_device_error_errno(device, r, "Failed to read current brightness: %m"); - -- value = strdup(curval); -- if (!value) -- return log_oom(); -- } else if (r < 0) -- return log_error_errno(r, "Failed to read %s: %m", saved); -- -- if (clamp) -- (void) clamp_brightness(device, &value, max_brightness); -+ (void) clamp_brightness(device, false, max_brightness, &brightness); -+ } - -- r = sd_device_set_sysattr_value(device, "brightness", value); -+ r = sd_device_set_sysattr_valuef(device, "brightness", "%u", brightness); - if (r < 0) - return log_device_error_errno(device, r, "Failed to write system 'brightness' attribute: %m"); - - } else if (streq(argv[1], "save")) { -- const char *value; -- - if (validate_device(device) == 0) { - (void) unlink(saved); - return 0; - } - -- r = read_brightness(device, &value); -+ r = read_brightness(device, max_brightness, &brightness); - if (r < 0) - return log_device_error_errno(device, r, "Failed to read current brightness: %m"); - -- r = write_string_file(saved, value, WRITE_STRING_FILE_CREATE); -+ r = write_string_filef(saved, WRITE_STRING_FILE_CREATE, "%u", brightness); - if (r < 0) - return log_device_error_errno(device, r, "Failed to write %s: %m", saved); - -diff --git a/src/basic/blockdev-util.c b/src/basic/blockdev-util.c -index 5f82126..21ff3ba 100644 ---- a/src/basic/blockdev-util.c -+++ b/src/basic/blockdev-util.c -@@ -214,3 +214,40 @@ int lock_whole_block_device(dev_t devt, int operation) { - - return TAKE_FD(lock_fd); - } -+ -+int blockdev_partscan_enabled(int fd) { -+ _cleanup_free_ char *p = NULL, *buf = NULL; -+ unsigned long long ull; -+ struct stat st; -+ int r; -+ -+ /* Checks if partition scanning is correctly enabled on the block device */ -+ -+ if (fstat(fd, &st) < 0) -+ return -errno; -+ -+ if (!S_ISBLK(st.st_mode)) -+ return -ENOTBLK; -+ -+ if (asprintf(&p, "/sys/dev/block/%u:%u/capability", major(st.st_rdev), minor(st.st_rdev)) < 0) -+ return -ENOMEM; -+ -+ r = read_one_line_file(p, &buf); -+ if (r == -ENOENT) /* If the capability file doesn't exist then we are most likely looking at a -+ * partition block device, not the whole block device. And that means we have no -+ * partition scanning on for it (we do for its parent, but not for the partition -+ * itself). */ -+ return false; -+ if (r < 0) -+ return r; -+ -+ r = safe_atollu_full(buf, 16, &ull); -+ if (r < 0) -+ return r; -+ -+#ifndef GENHD_FL_NO_PART_SCAN -+#define GENHD_FL_NO_PART_SCAN (0x0200) -+#endif -+ -+ return !FLAGS_SET(ull, GENHD_FL_NO_PART_SCAN); -+} -diff --git a/src/basic/blockdev-util.h b/src/basic/blockdev-util.h -index 1e7588f..58a7050 100644 ---- a/src/basic/blockdev-util.h -+++ b/src/basic/blockdev-util.h -@@ -20,3 +20,5 @@ int get_block_device(const char *path, dev_t *dev); - int get_block_device_harder(const char *path, dev_t *dev); - - int lock_whole_block_device(dev_t devt, int operation); -+ -+int blockdev_partscan_enabled(int fd); -diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c -index 71e1bc9..43a5891 100644 ---- a/src/basic/btrfs-util.c -+++ b/src/basic/btrfs-util.c -@@ -315,6 +315,15 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) { - return -errno; - } - -+ /* For the root fs — when no initrd is involved — btrfs returns /dev/root on any kernels from -+ * the past few years. That sucks, as we have no API to determine the actual root then. let's -+ * return an recognizable error for this case, so that the caller can maybe print a nice -+ * message about this. -+ * -+ * https://bugzilla.kernel.org/show_bug.cgi?id=89721 */ -+ if (path_equal((char*) di.path, "/dev/root")) -+ return -EUCLEAN; -+ - if (stat((char*) di.path, &st) < 0) - return -errno; - -@@ -1645,7 +1654,10 @@ int btrfs_subvol_snapshot_fd_full( - } else if (r < 0) - return r; - -- r = copy_directory_fd_full(old_fd, new_path, COPY_MERGE|COPY_REFLINK|COPY_SAME_MOUNT|(FLAGS_SET(flags, BTRFS_SNAPSHOT_SIGINT) ? COPY_SIGINT : 0), progress_path, progress_bytes, userdata); -+ r = copy_directory_fd_full( -+ old_fd, new_path, -+ COPY_MERGE|COPY_REFLINK|COPY_SAME_MOUNT|COPY_HARDLINKS|(FLAGS_SET(flags, BTRFS_SNAPSHOT_SIGINT) ? COPY_SIGINT : 0), -+ progress_path, progress_bytes, userdata); - if (r < 0) - goto fallback_fail; - -diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h -index c1bbb42..d9cb95a 100644 ---- a/src/basic/btrfs-util.h -+++ b/src/basic/btrfs-util.h -@@ -121,3 +121,9 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret); - - int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *quota); - int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *quota); -+ -+static inline int btrfs_log_dev_root(int level, int ret, const char *p) { -+ return log_full_errno(level, ret, -+ "File system behind %s is reported by btrfs to be backed by pseudo-device /dev/root, which is not a valid userspace accessible device node. " -+ "Cannot determine correct backing block device.", p); -+} -diff --git a/src/basic/cap-list.h b/src/basic/cap-list.h -index ab41924..4bfb1a3 100644 ---- a/src/basic/cap-list.h -+++ b/src/basic/cap-list.h -@@ -1,6 +1,8 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - #pragma once - -+#include -+ - const char *capability_to_name(int id); - int capability_from_name(const char *name); - int capability_list_length(void); -diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c -index 5a4d020..ae269e8 100644 ---- a/src/basic/capability-util.c -+++ b/src/basic/capability-util.c -@@ -161,28 +161,21 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) { - return 0; - } - --int capability_bounding_set_drop(uint64_t keep, bool right_now) { -- _cleanup_cap_free_ cap_t before_cap = NULL, after_cap = NULL; -+int capability_gain_cap_setpcap(cap_t *ret_before_caps) { -+ _cleanup_cap_free_ cap_t caps = NULL; - cap_flag_value_t fv; -- int r; -- -- /* If we are run as PID 1 we will lack CAP_SETPCAP by default -- * in the effective set (yes, the kernel drops that when -- * executing init!), so get it back temporarily so that we can -- * call PR_CAPBSET_DROP. */ -- -- before_cap = cap_get_proc(); -- if (!before_cap) -+ caps = cap_get_proc(); -+ if (!caps) - return -errno; - -- if (cap_get_flag(before_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) -+ if (cap_get_flag(caps, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) - return -errno; - - if (fv != CAP_SET) { - _cleanup_cap_free_ cap_t temp_cap = NULL; - static const cap_value_t v = CAP_SETPCAP; - -- temp_cap = cap_dup(before_cap); -+ temp_cap = cap_dup(caps); - if (!temp_cap) - return -errno; - -@@ -193,8 +186,27 @@ int capability_bounding_set_drop(uint64_t keep, bool right_now) { - log_debug_errno(errno, "Can't acquire effective CAP_SETPCAP bit, ignoring: %m"); - - /* If we didn't manage to acquire the CAP_SETPCAP bit, we continue anyway, after all this just means -- * we'll fail later, when we actually intend to drop some capabilities. */ -+ * we'll fail later, when we actually intend to drop some capabilities or try to set securebits. */ - } -+ if (ret_before_caps) -+ /* Return the capabilities as they have been before setting CAP_SETPCAP */ -+ *ret_before_caps = TAKE_PTR(caps); -+ -+ return 0; -+} -+ -+int capability_bounding_set_drop(uint64_t keep, bool right_now) { -+ _cleanup_cap_free_ cap_t before_cap = NULL, after_cap = NULL; -+ int r; -+ -+ /* If we are run as PID 1 we will lack CAP_SETPCAP by default -+ * in the effective set (yes, the kernel drops that when -+ * executing init!), so get it back temporarily so that we can -+ * call PR_CAPBSET_DROP. */ -+ -+ r = capability_gain_cap_setpcap(&before_cap); -+ if (r < 0) -+ return r; - - after_cap = cap_dup(before_cap); - if (!after_cap) -diff --git a/src/basic/capability-util.h b/src/basic/capability-util.h -index fcc59da..fdf6ef8 100644 ---- a/src/basic/capability-util.h -+++ b/src/basic/capability-util.h -@@ -14,6 +14,7 @@ - - unsigned cap_last_cap(void); - int have_effective_cap(int value); -+int capability_gain_cap_setpcap(cap_t *return_caps); - int capability_bounding_set_drop(uint64_t keep, bool right_now); - int capability_bounding_set_drop_usermode(uint64_t keep); - -diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c -index e94fcfa..6210347 100644 ---- a/src/basic/cgroup-util.c -+++ b/src/basic/cgroup-util.c -@@ -652,14 +652,13 @@ int cg_remove_xattr(const char *controller, const char *path, const char *name) - return 0; - } - --int cg_pid_get_path(const char *controller, pid_t pid, char **path) { -+int cg_pid_get_path(const char *controller, pid_t pid, char **ret_path) { - _cleanup_fclose_ FILE *f = NULL; - const char *fs, *controller_str; - int unified, r; -- size_t cs = 0; - -- assert(path); - assert(pid >= 0); -+ assert(ret_path); - - if (controller) { - if (!cg_controller_is_valid(controller)) -@@ -675,8 +674,6 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) { - controller_str = SYSTEMD_CGROUP_CONTROLLER_LEGACY; - else - controller_str = controller; -- -- cs = strlen(controller_str); - } - - fs = procfs_file_alloca(pid, "cgroup"); -@@ -688,13 +685,13 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) { - - for (;;) { - _cleanup_free_ char *line = NULL; -- char *e, *p; -+ char *e; - - r = read_line(f, LONG_LINE_MAX, &line); - if (r < 0) - return r; - if (r == 0) -- break; -+ return -ENODATA; - - if (unified) { - e = startswith(line, "0:"); -@@ -706,9 +703,6 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) { - continue; - } else { - char *l; -- size_t k; -- const char *word, *state; -- bool found = false; - - l = strchr(line, ':'); - if (!l) -@@ -718,31 +712,27 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) { - e = strchr(l, ':'); - if (!e) - continue; -- - *e = 0; -- FOREACH_WORD_SEPARATOR(word, k, l, ",", state) -- if (k == cs && memcmp(word, controller_str, cs) == 0) { -- found = true; -- break; -- } -- if (!found) -+ -+ r = string_contains_word(l, ",", controller_str); -+ if (r < 0) -+ return r; -+ if (r == 0) - continue; - } - -- p = strdup(e + 1); -- if (!p) -+ char *path = strdup(e + 1); -+ if (!path) - return -ENOMEM; - - /* Truncate suffix indicating the process is a zombie */ -- e = endswith(p, " (deleted)"); -+ e = endswith(path, " (deleted)"); - if (e) - *e = 0; - -- *path = p; -+ *ret_path = path; - return 0; - } -- -- return -ENODATA; - } - - int cg_install_release_agent(const char *controller, const char *agent) { -diff --git a/src/basic/copy.c b/src/basic/copy.c -index b384010..be4ca62 100644 ---- a/src/basic/copy.c -+++ b/src/basic/copy.c -@@ -22,8 +22,10 @@ - #include "missing_syscall.h" - #include "mountpoint-util.h" - #include "nulstr-util.h" -+#include "rm-rf.h" - #include "selinux-util.h" - #include "stat-util.h" -+#include "stdio-util.h" - #include "string-util.h" - #include "strv.h" - #include "time-util.h" -@@ -394,6 +396,188 @@ static int fd_copy_symlink( - return 0; - } - -+/* Encapsulates the database we store potential hardlink targets in */ -+typedef struct HardlinkContext { -+ int dir_fd; /* An fd to the directory we use as lookup table. Never AT_FDCWD. Lazily created, when -+ * we add the first entry. */ -+ -+ /* These two fields are used to create the hardlink repository directory above — via -+ * mkdirat(parent_fd, subdir) — and are kept so that we can automatically remove the directory again -+ * when we are done. */ -+ int parent_fd; /* Possibly AT_FDCWD */ -+ char *subdir; -+} HardlinkContext; -+ -+static int hardlink_context_setup( -+ HardlinkContext *c, -+ int dt, -+ const char *to, -+ CopyFlags copy_flags) { -+ -+ _cleanup_close_ int dt_copy = -1; -+ int r; -+ -+ assert(c); -+ assert(c->dir_fd < 0 && c->dir_fd != AT_FDCWD); -+ assert(c->parent_fd < 0); -+ assert(!c->subdir); -+ -+ /* If hardlink recreation is requested we have to maintain a database of inodes that are potential -+ * hardlink sources. Given that generally disk sizes have to be assumed to be larger than what fits -+ * into physical RAM we cannot maintain that database in dynamic memory alone. Here we opt to -+ * maintain it on disk, to simplify things: inside the destination directory we'll maintain a -+ * temporary directory consisting of hardlinks of every inode we copied that might be subject of -+ * hardlinks. We can then use that as hardlink source later on. Yes, this means additional disk IO -+ * but thankfully Linux is optimized for this kind of thing. If this ever becomes a performance -+ * bottleneck we can certainly place an in-memory hash table in front of this, but for the beginning, -+ * let's keep things simple, and just use the disk as lookup table for inodes. -+ * -+ * Note that this should have zero performance impact as long as .n_link of all files copied remains -+ * <= 0, because in that case we will not actually allocate the hardlink inode lookup table directory -+ * on disk (we do so lazily, when the first candidate with .n_link > 1 is seen). This means, in the -+ * common case where hardlinks are not used at all or only for few files the fact that we store the -+ * table on disk shouldn't matter perfomance-wise. */ -+ -+ if (!FLAGS_SET(copy_flags, COPY_HARDLINKS)) -+ return 0; -+ -+ if (dt == AT_FDCWD) -+ dt_copy = AT_FDCWD; -+ else if (dt < 0) -+ return -EBADF; -+ else { -+ dt_copy = fcntl(dt, F_DUPFD_CLOEXEC, 3); -+ if (dt_copy < 0) -+ return -errno; -+ } -+ -+ r = tempfn_random_child(to, "hardlink", &c->subdir); -+ if (r < 0) -+ return r; -+ -+ c->parent_fd = TAKE_FD(dt_copy); -+ -+ /* We don't actually create the directory we keep the table in here, that's done on-demand when the -+ * first entry is added, using hardlink_context_realize() below. */ -+ return 1; -+} -+ -+static int hardlink_context_realize(HardlinkContext *c) { -+ int r; -+ -+ if (!c) -+ return 0; -+ -+ if (c->dir_fd >= 0) /* Already realized */ -+ return 1; -+ -+ if (c->parent_fd < 0 && c->parent_fd != AT_FDCWD) /* Not configured */ -+ return 0; -+ -+ assert(c->subdir); -+ -+ if (mkdirat(c->parent_fd, c->subdir, 0700) < 0) -+ return -errno; -+ -+ c->dir_fd = openat(c->parent_fd, c->subdir, O_RDONLY|O_DIRECTORY|O_CLOEXEC); -+ if (c->dir_fd < 0) { -+ r = -errno; -+ (void) unlinkat(c->parent_fd, c->subdir, AT_REMOVEDIR); -+ return r; -+ } -+ -+ return 1; -+} -+ -+static void hardlink_context_destroy(HardlinkContext *c) { -+ int r; -+ -+ assert(c); -+ -+ /* Automatically remove the hardlink lookup table directory again after we are done. This is used via -+ * _cleanup_() so that we really delete this, even on failure. */ -+ -+ if (c->dir_fd >= 0) { -+ r = rm_rf_children(TAKE_FD(c->dir_fd), REMOVE_PHYSICAL, NULL); /* consumes dir_fd in all cases, even on failure */ -+ if (r < 0) -+ log_debug_errno(r, "Failed to remove hardlink store (%s) contents, ignoring: %m", c->subdir); -+ -+ assert(c->parent_fd >= 0 || c->parent_fd == AT_FDCWD); -+ assert(c->subdir); -+ -+ if (unlinkat(c->parent_fd, c->subdir, AT_REMOVEDIR) < 0) -+ log_debug_errno(errno, "Failed to remove hardlink store (%s) directory, ignoring: %m", c->subdir); -+ } -+ -+ assert_cc(AT_FDCWD < 0); -+ c->parent_fd = safe_close(c->parent_fd); -+ -+ c->subdir = mfree(c->subdir); -+} -+ -+static int try_hardlink( -+ HardlinkContext *c, -+ const struct stat *st, -+ int dt, -+ const char *to) { -+ -+ char dev_ino[DECIMAL_STR_MAX(dev_t)*2 + DECIMAL_STR_MAX(uint64_t) + 4]; -+ -+ assert(st); -+ assert(dt >= 0 || dt == AT_FDCWD); -+ assert(to); -+ -+ if (!c) /* No temporary hardlink directory, don't bother */ -+ return 0; -+ -+ if (st->st_nlink <= 1) /* Source not hardlinked, don't bother */ -+ return 0; -+ -+ if (c->dir_fd < 0) /* not yet realized, hence empty */ -+ return 0; -+ -+ xsprintf(dev_ino, "%u:%u:%" PRIu64, major(st->st_dev), minor(st->st_dev), (uint64_t) st->st_ino); -+ if (linkat(c->dir_fd, dev_ino, dt, to, 0) < 0) { -+ if (errno != ENOENT) /* doesn't exist in store yet */ -+ log_debug_errno(errno, "Failed to hardlink %s to %s, ignoring: %m", dev_ino, to); -+ return 0; -+ } -+ -+ return 1; -+} -+ -+static int memorize_hardlink( -+ HardlinkContext *c, -+ const struct stat *st, -+ int dt, -+ const char *to) { -+ -+ char dev_ino[DECIMAL_STR_MAX(dev_t)*2 + DECIMAL_STR_MAX(uint64_t) + 4]; -+ int r; -+ -+ assert(st); -+ assert(dt >= 0 || dt == AT_FDCWD); -+ assert(to); -+ -+ if (!c) /* No temporary hardlink directory, don't bother */ -+ return 0; -+ -+ if (st->st_nlink <= 1) /* Source not hardlinked, don't bother */ -+ return 0; -+ -+ r = hardlink_context_realize(c); /* Create the hardlink store lazily */ -+ if (r < 0) -+ return r; -+ -+ xsprintf(dev_ino, "%u:%u:%" PRIu64, major(st->st_dev), minor(st->st_dev), (uint64_t) st->st_ino); -+ if (linkat(dt, to, c->dir_fd, dev_ino, 0) < 0) { -+ log_debug_errno(errno, "Failed to hardlink %s to %s, ignoring: %m", to, dev_ino); -+ return 0; -+ } -+ -+ return 1; -+} -+ - static int fd_copy_regular( - int df, - const char *from, -@@ -403,6 +587,7 @@ static int fd_copy_regular( - uid_t override_uid, - gid_t override_gid, - CopyFlags copy_flags, -+ HardlinkContext *hardlink_context, - copy_progress_bytes_t progress, - void *userdata) { - -@@ -414,6 +599,12 @@ static int fd_copy_regular( - assert(st); - assert(to); - -+ r = try_hardlink(hardlink_context, st, dt, to); -+ if (r < 0) -+ return r; -+ if (r > 0) /* worked! */ -+ return 0; -+ - fdf = openat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); - if (fdf < 0) - return -errno; -@@ -456,6 +647,7 @@ static int fd_copy_regular( - (void) unlinkat(dt, to, 0); - } - -+ (void) memorize_hardlink(hardlink_context, st, dt, to); - return r; - } - -@@ -467,13 +659,20 @@ static int fd_copy_fifo( - const char *to, - uid_t override_uid, - gid_t override_gid, -- CopyFlags copy_flags) { -+ CopyFlags copy_flags, -+ HardlinkContext *hardlink_context) { - int r; - - assert(from); - assert(st); - assert(to); - -+ r = try_hardlink(hardlink_context, st, dt, to); -+ if (r < 0) -+ return r; -+ if (r > 0) /* worked! */ -+ return 0; -+ - if (copy_flags & COPY_MAC_CREATE) { - r = mac_selinux_create_file_prepare_at(dt, to, S_IFIFO); - if (r < 0) -@@ -494,6 +693,7 @@ static int fd_copy_fifo( - if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0) - r = -errno; - -+ (void) memorize_hardlink(hardlink_context, st, dt, to); - return r; - } - -@@ -505,13 +705,20 @@ static int fd_copy_node( - const char *to, - uid_t override_uid, - gid_t override_gid, -- CopyFlags copy_flags) { -+ CopyFlags copy_flags, -+ HardlinkContext *hardlink_context) { - int r; - - assert(from); - assert(st); - assert(to); - -+ r = try_hardlink(hardlink_context, st, dt, to); -+ if (r < 0) -+ return r; -+ if (r > 0) /* worked! */ -+ return 0; -+ - if (copy_flags & COPY_MAC_CREATE) { - r = mac_selinux_create_file_prepare_at(dt, to, st->st_mode & S_IFMT); - if (r < 0) -@@ -532,6 +739,7 @@ static int fd_copy_node( - if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0) - r = -errno; - -+ (void) memorize_hardlink(hardlink_context, st, dt, to); - return r; - } - -@@ -546,11 +754,17 @@ static int fd_copy_directory( - uid_t override_uid, - gid_t override_gid, - CopyFlags copy_flags, -+ HardlinkContext *hardlink_context, - const char *display_path, - copy_progress_path_t progress_path, - copy_progress_bytes_t progress_bytes, - void *userdata) { - -+ _cleanup_(hardlink_context_destroy) HardlinkContext our_hardlink_context = { -+ .dir_fd = -1, -+ .parent_fd = -1, -+ }; -+ - _cleanup_close_ int fdf = -1, fdt = -1; - _cleanup_closedir_ DIR *d = NULL; - struct dirent *de; -@@ -570,6 +784,16 @@ static int fd_copy_directory( - if (fdf < 0) - return -errno; - -+ if (!hardlink_context) { -+ /* If recreating hardlinks is requested let's set up a context for that now. */ -+ r = hardlink_context_setup(&our_hardlink_context, dt, to, copy_flags); -+ if (r < 0) -+ return r; -+ if (r > 0) /* It's enabled and allocated, let's now use the same context for all recursive -+ * invocations from here down */ -+ hardlink_context = &our_hardlink_context; -+ } -+ - d = take_fdopendir(&fdf); - if (!d) - return -errno; -@@ -668,15 +892,15 @@ static int fd_copy_directory( - continue; - } - -- q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, depth_left-1, override_uid, override_gid, copy_flags, child_display_path, progress_path, progress_bytes, userdata); -+ q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, depth_left-1, override_uid, override_gid, copy_flags, hardlink_context, child_display_path, progress_path, progress_bytes, userdata); - } else if (S_ISREG(buf.st_mode)) -- q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags, progress_bytes, userdata); -+ q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags, hardlink_context, progress_bytes, userdata); - else if (S_ISLNK(buf.st_mode)) - q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags); - else if (S_ISFIFO(buf.st_mode)) -- q = fd_copy_fifo(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags); -+ q = fd_copy_fifo(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags, hardlink_context); - else if (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode) || S_ISSOCK(buf.st_mode)) -- q = fd_copy_node(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags); -+ q = fd_copy_node(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags, hardlink_context); - else - q = -EOPNOTSUPP; - -@@ -730,15 +954,15 @@ int copy_tree_at_full( - return -errno; - - if (S_ISREG(st.st_mode)) -- return fd_copy_regular(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags, progress_bytes, userdata); -+ return fd_copy_regular(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags, NULL, progress_bytes, userdata); - else if (S_ISDIR(st.st_mode)) -- return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, COPY_DEPTH_MAX, override_uid, override_gid, copy_flags, NULL, progress_path, progress_bytes, userdata); -+ return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, COPY_DEPTH_MAX, override_uid, override_gid, copy_flags, NULL, NULL, progress_path, progress_bytes, userdata); - else if (S_ISLNK(st.st_mode)) - return fd_copy_symlink(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags); - else if (S_ISFIFO(st.st_mode)) -- return fd_copy_fifo(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags); -+ return fd_copy_fifo(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags, NULL); - else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) || S_ISSOCK(st.st_mode)) -- return fd_copy_node(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags); -+ return fd_copy_node(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags, NULL); - else - return -EOPNOTSUPP; - } -@@ -762,7 +986,7 @@ int copy_directory_fd_full( - if (!S_ISDIR(st.st_mode)) - return -ENOTDIR; - -- return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags, NULL, progress_path, progress_bytes, userdata); -+ return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags, NULL, NULL, progress_path, progress_bytes, userdata); - } - - int copy_directory_full( -@@ -784,7 +1008,7 @@ int copy_directory_full( - if (!S_ISDIR(st.st_mode)) - return -ENOTDIR; - -- return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags, NULL, progress_path, progress_bytes, userdata); -+ return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags, NULL, NULL, progress_path, progress_bytes, userdata); - } - - int copy_file_fd_full( -@@ -969,6 +1193,21 @@ int copy_times(int fdf, int fdt, CopyFlags flags) { - return 0; - } - -+int copy_access(int fdf, int fdt) { -+ struct stat st; -+ -+ assert(fdf >= 0); -+ assert(fdt >= 0); -+ -+ if (fstat(fdf, &st) < 0) -+ return -errno; -+ -+ if (fchmod(fdt, st.st_mode & 07777) < 0) -+ return -errno; -+ -+ return 0; -+} -+ - int copy_xattr(int fdf, int fdt) { - _cleanup_free_ char *names = NULL; - int ret = 0, r; -diff --git a/src/basic/copy.h b/src/basic/copy.h -index af8e88a..843d2d7 100644 ---- a/src/basic/copy.h -+++ b/src/basic/copy.h -@@ -17,6 +17,7 @@ typedef enum CopyFlags { - COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */ - COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */ - COPY_MAC_CREATE = 1 << 7, /* Create files with the correct MAC label (currently SELinux only) */ -+ COPY_HARDLINKS = 1 << 8, /* Try to reproduce hard links */ - } CopyFlags; - - typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata); -@@ -61,4 +62,5 @@ static inline int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags cop - } - - int copy_times(int fdf, int fdt, CopyFlags flags); -+int copy_access(int fdf, int fdt); - int copy_xattr(int fdf, int fdt); -diff --git a/src/basic/dlfcn-util.c b/src/basic/dlfcn-util.c -new file mode 100644 -index 0000000..08ded96 ---- /dev/null -+++ b/src/basic/dlfcn-util.c -@@ -0,0 +1,40 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include "dlfcn-util.h" -+ -+int dlsym_many_and_warn(void *dl, int level, ...) { -+ va_list ap; -+ int r; -+ -+ /* Tries to resolve a bunch of function symbols, and logs errors about the ones it cannot -+ * resolve. Note that this function possibly modifies the supplied function pointers if the whole -+ * operation fails */ -+ -+ va_start(ap, level); -+ -+ for (;;) { -+ void (**fn)(void); -+ void (*tfn)(void); -+ const char *symbol; -+ -+ fn = va_arg(ap, typeof(fn)); -+ if (!fn) -+ break; -+ -+ symbol = va_arg(ap, typeof(symbol)); -+ -+ tfn = (typeof(tfn)) dlsym(dl, symbol); -+ if (!tfn) { -+ r = log_full_errno(level, -+ SYNTHETIC_ERRNO(ELIBBAD), -+ "Can't find symbol %s: %s", symbol, dlerror()); -+ va_end(ap); -+ return r; -+ } -+ -+ *fn = tfn; -+ } -+ -+ va_end(ap); -+ return 0; -+} -diff --git a/src/basic/dlfcn-util.h b/src/basic/dlfcn-util.h -index d254afb..df66cdf 100644 ---- a/src/basic/dlfcn-util.h -+++ b/src/basic/dlfcn-util.h -@@ -6,3 +6,5 @@ - #include "macro.h" - - DEFINE_TRIVIAL_CLEANUP_FUNC(void*, dlclose); -+ -+int dlsym_many_and_warn(void *dl, int level, ...); -diff --git a/src/basic/env-file.c b/src/basic/env-file.c -index 2647079..dc92b13 100644 ---- a/src/basic/env-file.c -+++ b/src/basic/env-file.c -@@ -209,17 +209,21 @@ static int parse_env_file_internal( - case DOUBLE_QUOTE_VALUE_ESCAPE: - state = DOUBLE_QUOTE_VALUE; - -- if (c == '"') { -+ if (strchr(SHELL_NEED_ESCAPE, c)) { -+ /* If this is a char that needs escaping, just unescape it. */ - if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) - return -ENOMEM; -- value[n_value++] = '"'; -- } else if (!strchr(NEWLINE, c)) { -+ value[n_value++] = c; -+ } else if (c != '\n') { -+ /* If other char than what needs escaping, keep the "\" in place, like the -+ * real shell does. */ - if (!GREEDY_REALLOC(value, value_alloc, n_value+3)) - return -ENOMEM; - value[n_value++] = '\\'; - value[n_value++] = c; - } - -+ /* Escaped newlines (aka "continuation lines") are eaten up entirely */ - break; - - case COMMENT: -diff --git a/src/basic/env-util.c b/src/basic/env-util.c -index b8dc989..179408c 100644 ---- a/src/basic/env-util.c -+++ b/src/basic/env-util.c -@@ -687,7 +687,7 @@ char **replace_env_argv(char **argv, char **env) { - if (e) { - int r; - -- r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE); -+ r = strv_split_full(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE); - if (r < 0) { - ret[k] = NULL; - strv_free(ret); -diff --git a/src/basic/escape.c b/src/basic/escape.c -index 116efa4..7589d59 100644 ---- a/src/basic/escape.c -+++ b/src/basic/escape.c -@@ -75,7 +75,7 @@ int cescape_char(char c, char *buf) { - return buf - buf_old; - } - --char *cescape_length(const char *s, size_t n) { -+char* cescape_length(const char *s, size_t n) { - const char *f; - char *r, *t; - -@@ -96,7 +96,7 @@ char *cescape_length(const char *s, size_t n) { - return r; - } - --char *cescape(const char *s) { -+char* cescape(const char *s) { - assert(s); - - return cescape_length(s, strlen(s)); -@@ -360,7 +360,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi - return t - r; - } - --char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) { -+char* xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) { - char *ans, *t, *prev, *prev2; - const char *f; - -@@ -427,14 +427,14 @@ char *xescape_full(const char *s, const char *bad, size_t console_width, bool ei - return ans; - } - --char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) { -+char* escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) { - if (eight_bit) - return xescape_full(str, "", console_width, true); - else - return utf8_escape_non_printable_full(str, console_width); - } - --char *octescape(const char *s, size_t len) { -+char* octescape(const char *s, size_t len) { - char *r, *t; - const char *f; - -@@ -462,7 +462,7 @@ char *octescape(const char *s, size_t len) { - - } - --static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) { -+static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) { - assert(bad); - - for (; *s; s++) { -@@ -481,7 +481,7 @@ static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, b - return t; - } - --char *shell_escape(const char *s, const char *bad) { -+char* shell_escape(const char *s, const char *bad) { - char *r, *t; - - r = new(char, strlen(s)*2+1); -diff --git a/src/basic/escape.h b/src/basic/escape.h -index 0b00b11..fa26781 100644 ---- a/src/basic/escape.h -+++ b/src/basic/escape.h -@@ -43,8 +43,8 @@ typedef enum EscapeStyle { - * syntax (a string enclosed in $'') instead of plain quotes. */ - } EscapeStyle; - --char *cescape(const char *s); --char *cescape_length(const char *s, size_t n); -+char* cescape(const char *s); -+char* cescape_length(const char *s, size_t n); - int cescape_char(char c, char *buf); - - int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret); -@@ -56,12 +56,12 @@ static inline int cunescape(const char *s, UnescapeFlags flags, char **ret) { - } - int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit, bool accept_nul); - --char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits); --static inline char *xescape(const char *s, const char *bad) { -+char* xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits); -+static inline char* xescape(const char *s, const char *bad) { - return xescape_full(s, bad, SIZE_MAX, false); - } --char *octescape(const char *s, size_t len); --char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit); -+char* octescape(const char *s, size_t len); -+char* escape_non_printable_full(const char *str, size_t console_width, bool eight_bit); - --char *shell_escape(const char *s, const char *bad); -+char* shell_escape(const char *s, const char *bad); - char* shell_maybe_quote(const char *s, EscapeStyle style); -diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c -index ac9bf60..d64dddd 100644 ---- a/src/basic/extract-word.c -+++ b/src/basic/extract-word.c -@@ -14,6 +14,7 @@ - #include "log.h" - #include "macro.h" - #include "string-util.h" -+#include "strv.h" - #include "utf8.h" - - int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) { -@@ -86,25 +87,30 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra - return -EINVAL; - } - -- if (flags & EXTRACT_CUNESCAPE) { -+ if (flags & (EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS)) { - bool eight_bit = false; - char32_t u; - -- r = cunescape_one(*p, (size_t) -1, &u, &eight_bit, false); -- if (r < 0) { -- if (flags & EXTRACT_CUNESCAPE_RELAX) { -- s[sz++] = '\\'; -- s[sz++] = c; -- } else -- return -EINVAL; -- } else { -+ if ((flags & EXTRACT_CUNESCAPE) && -+ (r = cunescape_one(*p, (size_t) -1, &u, &eight_bit, false)) >= 0) { -+ /* A valid escaped sequence */ -+ assert(r >= 1); -+ - (*p) += r - 1; - - if (eight_bit) - s[sz++] = u; - else - sz += utf8_encode_unichar(s + sz, u); -- } -+ } else if ((flags & EXTRACT_UNESCAPE_SEPARATORS) && -+ strchr(separators, **p)) -+ /* An escaped separator char */ -+ s[sz++] = c; -+ else if (flags & EXTRACT_CUNESCAPE_RELAX) { -+ s[sz++] = '\\'; -+ s[sz++] = c; -+ } else -+ return -EINVAL; - } else - s[sz++] = c; - -diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h -index e2d4338..f028577 100644 ---- a/src/basic/extract-word.h -+++ b/src/basic/extract-word.h -@@ -7,9 +7,10 @@ typedef enum ExtractFlags { - EXTRACT_RELAX = 1 << 0, - EXTRACT_CUNESCAPE = 1 << 1, - EXTRACT_CUNESCAPE_RELAX = 1 << 2, -- EXTRACT_UNQUOTE = 1 << 3, -- EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 4, -- EXTRACT_RETAIN_ESCAPE = 1 << 5, -+ EXTRACT_UNESCAPE_SEPARATORS = 1 << 3, -+ EXTRACT_UNQUOTE = 1 << 4, -+ EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 5, -+ EXTRACT_RETAIN_ESCAPE = 1 << 6, - } ExtractFlags; - - int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags); -diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c -index 75a6282..14b12b2 100644 ---- a/src/basic/fd-util.c -+++ b/src/basic/fd-util.c -@@ -976,6 +976,6 @@ int read_nr_open(void) { - return v; - } - -- /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */ -+ /* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */ - return 1024 * 1024; - } -diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c -index 34a2260..7f8b8b2 100644 ---- a/src/basic/fs-util.c -+++ b/src/basic/fs-util.c -@@ -120,7 +120,7 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char - if (!IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM)) /* FAT returns EPERM on link()… */ - return -errno; - -- /* OK, neither RENAME_NOREPLACE nor linkat()+unlinkat() worked. Let's then fallback to the racy TOCTOU -+ /* OK, neither RENAME_NOREPLACE nor linkat()+unlinkat() worked. Let's then fall back to the racy TOCTOU - * vulnerable accessat(F_OK) check followed by classic, replacing renameat(), we have nothing better. */ - - if (faccessat(newdirfd, newpath, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) -@@ -229,6 +229,7 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { - int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { - bool do_chown, do_chmod; - struct stat st; -+ int r; - - /* Change ownership and access mode of the specified fd. Tries to do so safely, ensuring that at no - * point in time the access mode is above the old access mode under the old ownership or the new -@@ -259,18 +260,22 @@ int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { - if (do_chown && do_chmod) { - mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */ - -- if (((minimal ^ st.st_mode) & 07777) != 0) -- if (fchmod_opath(fd, minimal & 07777) < 0) -- return -errno; -+ if (((minimal ^ st.st_mode) & 07777) != 0) { -+ r = fchmod_opath(fd, minimal & 07777); -+ if (r < 0) -+ return r; -+ } - } - - if (do_chown) - if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0) - return -errno; - -- if (do_chmod) -- if (fchmod_opath(fd, mode & 07777) < 0) -- return -errno; -+ if (do_chmod) { -+ r = fchmod_opath(fd, mode & 07777); -+ if (r < 0) -+ return r; -+ } - - return do_chown || do_chmod; - } -diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c -index 67c4391..77cebd9 100644 ---- a/src/basic/hashmap.c -+++ b/src/basic/hashmap.c -@@ -1,6 +1,7 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - - #include -+#include - #include - #include - -@@ -19,7 +20,6 @@ - #include "strv.h" - - #if ENABLE_DEBUG_HASHMAP --#include - #include "list.h" - #endif - -@@ -189,7 +189,6 @@ assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3)); - * a handful of directly stored entries in a hashmap. When a hashmap - * outgrows direct storage, it gets its own key for indirect storage. */ - static uint8_t shared_hash_key[HASH_KEY_SIZE]; --static bool shared_hash_key_initialized; - - /* Fields that all hashmap/set types must have */ - struct HashmapBase { -@@ -323,12 +322,12 @@ static void n_entries_dec(HashmapBase *h) { - h->n_direct_entries--; - } - --static void *storage_ptr(HashmapBase *h) { -+static void* storage_ptr(HashmapBase *h) { - return h->has_indirect ? h->indirect.storage - : h->direct.storage; - } - --static uint8_t *hash_key(HashmapBase *h) { -+static uint8_t* hash_key(HashmapBase *h) { - return h->has_indirect ? h->indirect.hash_key - : shared_hash_key; - } -@@ -371,16 +370,16 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { - memcpy(hash_key, current, sizeof(current)); - } - --static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) { -+static struct hashmap_base_entry* bucket_at(HashmapBase *h, unsigned idx) { - return (struct hashmap_base_entry*) - ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); - } - --static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) { -+static struct plain_hashmap_entry* plain_bucket_at(Hashmap *h, unsigned idx) { - return (struct plain_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); - } - --static struct ordered_hashmap_entry *ordered_bucket_at(OrderedHashmap *h, unsigned idx) { -+static struct ordered_hashmap_entry* ordered_bucket_at(OrderedHashmap *h, unsigned idx) { - return (struct ordered_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); - } - -@@ -388,13 +387,13 @@ static struct set_entry *set_bucket_at(Set *h, unsigned idx) { - return (struct set_entry*) bucket_at(HASHMAP_BASE(h), idx); - } - --static struct ordered_hashmap_entry *bucket_at_swap(struct swap_entries *swap, unsigned idx) { -+static struct ordered_hashmap_entry* bucket_at_swap(struct swap_entries *swap, unsigned idx) { - return &swap->e[idx - _IDX_SWAP_BEGIN]; - } - - /* Returns a pointer to the bucket at index idx. - * Understands real indexes and swap indexes, hence "_virtual". */ --static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_entries *swap, -+static struct hashmap_base_entry* bucket_at_virtual(HashmapBase *h, struct swap_entries *swap, - unsigned idx) { - if (idx < _IDX_SWAP_BEGIN) - return bucket_at(h, idx); -@@ -405,7 +404,7 @@ static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_ - assert_not_reached("Invalid index"); - } - --static dib_raw_t *dib_raw_ptr(HashmapBase *h) { -+static dib_raw_t* dib_raw_ptr(HashmapBase *h) { - return (dib_raw_t*) - ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h)); - } -@@ -503,7 +502,7 @@ static unsigned prev_idx(HashmapBase *h, unsigned idx) { - return (n_buckets(h) + idx - 1U) % n_buckets(h); - } - --static void *entry_value(HashmapBase *h, struct hashmap_base_entry *e) { -+static void* entry_value(HashmapBase *h, struct hashmap_base_entry *e) { - switch (h->type) { - - case HASHMAP_TYPE_PLAIN: -@@ -730,16 +729,12 @@ bool _hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **ke - return true; - } - --bool set_iterate(const Set *s, Iterator *i, void **value) { -- return _hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL); --} -- - #define HASHMAP_FOREACH_IDX(idx, h, i) \ - for ((i) = ITERATOR_FIRST, (idx) = hashmap_iterate_entry((h), &(i)); \ - (idx != IDX_NIL); \ - (idx) = hashmap_iterate_entry((h), &(i))) - --IteratedCache *_hashmap_iterated_cache_new(HashmapBase *h) { -+IteratedCache* _hashmap_iterated_cache_new(HashmapBase *h) { - IteratedCache *cache; - - assert(h); -@@ -768,7 +763,11 @@ static void reset_direct_storage(HashmapBase *h) { - memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets); - } - --static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { -+static void shared_hash_key_initialize(void) { -+ random_bytes(shared_hash_key, sizeof(shared_hash_key)); -+} -+ -+static struct HashmapBase* hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { - HashmapBase *h; - const struct hashmap_type_info *hi = &hashmap_type_info[type]; - bool up; -@@ -790,10 +789,8 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu - - reset_direct_storage(h); - -- if (!shared_hash_key_initialized) { -- random_bytes(shared_hash_key, sizeof(shared_hash_key)); -- shared_hash_key_initialized= true; -- } -+ static pthread_once_t once = PTHREAD_ONCE_INIT; -+ assert_se(pthread_once(&once, shared_hash_key_initialize) == 0); - - #if ENABLE_DEBUG_HASHMAP - h->debug.func = func; -@@ -848,6 +845,16 @@ int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBU - return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS); - } - -+int _ordered_hashmap_ensure_put(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS) { -+ int r; -+ -+ r = _ordered_hashmap_ensure_allocated(h, hash_ops HASHMAP_DEBUG_PASS_ARGS); -+ if (r < 0) -+ return r; -+ -+ return ordered_hashmap_put(*h, key, value); -+} -+ - static void hashmap_free_no_clear(HashmapBase *h) { - assert(!h->has_indirect); - assert(h->n_direct_entries == 0); -@@ -866,7 +873,7 @@ static void hashmap_free_no_clear(HashmapBase *h) { - free(h); - } - --HashmapBase *_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) { -+HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) { - if (h) { - _hashmap_clear(h, default_free_key, default_free_value); - hashmap_free_no_clear(h); -@@ -1323,7 +1330,7 @@ int hashmap_update(Hashmap *h, const void *key, void *value) { - return 0; - } - --void *_hashmap_get(HashmapBase *h, const void *key) { -+void* _hashmap_get(HashmapBase *h, const void *key) { - struct hashmap_base_entry *e; - unsigned hash, idx; - -@@ -1339,7 +1346,7 @@ void *_hashmap_get(HashmapBase *h, const void *key) { - return entry_value(h, e); - } - --void *hashmap_get2(Hashmap *h, const void *key, void **key2) { -+void* hashmap_get2(Hashmap *h, const void *key, void **key2) { - struct plain_hashmap_entry *e; - unsigned hash, idx; - -@@ -1368,7 +1375,7 @@ bool _hashmap_contains(HashmapBase *h, const void *key) { - return bucket_scan(h, hash, key) != IDX_NIL; - } - --void *_hashmap_remove(HashmapBase *h, const void *key) { -+void* _hashmap_remove(HashmapBase *h, const void *key) { - struct hashmap_base_entry *e; - unsigned hash, idx; - void *data; -@@ -1388,7 +1395,7 @@ void *_hashmap_remove(HashmapBase *h, const void *key) { - return data; - } - --void *hashmap_remove2(Hashmap *h, const void *key, void **rkey) { -+void* hashmap_remove2(Hashmap *h, const void *key, void **rkey) { - struct plain_hashmap_entry *e; - unsigned hash, idx; - void *data; -@@ -1506,7 +1513,7 @@ int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_ - return 0; - } - --void *_hashmap_remove_value(HashmapBase *h, const void *key, void *value) { -+void* _hashmap_remove_value(HashmapBase *h, const void *key, void *value) { - struct hashmap_base_entry *e; - unsigned hash, idx; - -@@ -1536,7 +1543,7 @@ static unsigned find_first_entry(HashmapBase *h) { - return hashmap_iterate_entry(h, &i); - } - --void *_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) { -+void* _hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) { - struct hashmap_base_entry *e; - void *key, *data; - unsigned idx; -@@ -1711,7 +1718,7 @@ int _hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) { - return 0; - } - --HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) { -+HashmapBase* _hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) { - HashmapBase *copy; - int r; - -@@ -1739,7 +1746,7 @@ HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS) { - return copy; - } - --char **_hashmap_get_strv(HashmapBase *h) { -+char** _hashmap_get_strv(HashmapBase *h) { - char **sv; - Iterator i; - unsigned idx, n; -@@ -1756,7 +1763,7 @@ char **_hashmap_get_strv(HashmapBase *h) { - return sv; - } - --void *ordered_hashmap_next(OrderedHashmap *h, const void *key) { -+void* ordered_hashmap_next(OrderedHashmap *h, const void *key) { - struct ordered_hashmap_entry *e; - unsigned hash, idx; - -@@ -1961,7 +1968,7 @@ int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void - return 0; - } - --IteratedCache *iterated_cache_free(IteratedCache *cache) { -+IteratedCache* iterated_cache_free(IteratedCache *cache) { - if (cache) { - free(cache->keys.ptr); - free(cache->values.ptr); -diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h -index 6009441..890f90a 100644 ---- a/src/basic/hashmap.h -+++ b/src/basic/hashmap.h -@@ -83,8 +83,8 @@ typedef struct { - # define HASHMAP_DEBUG_PASS_ARGS - #endif - --Hashmap *_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); --OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); -+Hashmap* _hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); -+OrderedHashmap* _ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); - #define hashmap_new(ops) _hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) - #define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) - -@@ -96,39 +96,39 @@ OrderedHashmap *_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DE - 0; \ - }) - --HashmapBase *_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value); --static inline Hashmap *hashmap_free(Hashmap *h) { -+HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value); -+static inline Hashmap* hashmap_free(Hashmap *h) { - return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL); - } --static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) { -+static inline OrderedHashmap* ordered_hashmap_free(OrderedHashmap *h) { - return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, NULL); - } - --static inline Hashmap *hashmap_free_free(Hashmap *h) { -+static inline Hashmap* hashmap_free_free(Hashmap *h) { - return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free); - } --static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) { -+static inline OrderedHashmap* ordered_hashmap_free_free(OrderedHashmap *h) { - return (void*) _hashmap_free(HASHMAP_BASE(h), NULL, free); - } - --static inline Hashmap *hashmap_free_free_key(Hashmap *h) { -+static inline Hashmap* hashmap_free_free_key(Hashmap *h) { - return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL); - } --static inline OrderedHashmap *ordered_hashmap_free_free_key(OrderedHashmap *h) { -+static inline OrderedHashmap* ordered_hashmap_free_free_key(OrderedHashmap *h) { - return (void*) _hashmap_free(HASHMAP_BASE(h), free, NULL); - } - --static inline Hashmap *hashmap_free_free_free(Hashmap *h) { -+static inline Hashmap* hashmap_free_free_free(Hashmap *h) { - return (void*) _hashmap_free(HASHMAP_BASE(h), free, free); - } --static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) { -+static inline OrderedHashmap* ordered_hashmap_free_free_free(OrderedHashmap *h) { - return (void*) _hashmap_free(HASHMAP_BASE(h), free, free); - } - --IteratedCache *iterated_cache_free(IteratedCache *cache); -+IteratedCache* iterated_cache_free(IteratedCache *cache); - int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries); - --HashmapBase *_hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS); -+HashmapBase* _hashmap_copy(HashmapBase *h HASHMAP_DEBUG_PARAMS); - #define hashmap_copy(h) ((Hashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS)) - #define ordered_hashmap_copy(h) ((OrderedHashmap*) _hashmap_copy(HASHMAP_BASE(h) HASHMAP_DEBUG_SRC_ARGS)) - -@@ -137,11 +137,14 @@ int _ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops - #define hashmap_ensure_allocated(h, ops) _hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) - #define ordered_hashmap_ensure_allocated(h, ops) _ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) - --IteratedCache *_hashmap_iterated_cache_new(HashmapBase *h); --static inline IteratedCache *hashmap_iterated_cache_new(Hashmap *h) { -+int _ordered_hashmap_ensure_put(OrderedHashmap **h, const struct hash_ops *hash_ops, const void *key, void *value HASHMAP_DEBUG_PARAMS); -+#define ordered_hashmap_ensure_put(s, ops, key, value) _ordered_hashmap_ensure_put(s, ops, key, value HASHMAP_DEBUG_SRC_ARGS) -+ -+IteratedCache* _hashmap_iterated_cache_new(HashmapBase *h); -+static inline IteratedCache* hashmap_iterated_cache_new(Hashmap *h) { - return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h)); - } --static inline IteratedCache *ordered_hashmap_iterated_cache_new(OrderedHashmap *h) { -+static inline IteratedCache* ordered_hashmap_iterated_cache_new(OrderedHashmap *h) { - return (IteratedCache*) _hashmap_iterated_cache_new(HASHMAP_BASE(h)); - } - -@@ -163,7 +166,7 @@ static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, vo - return hashmap_replace(PLAIN_HASHMAP(h), key, value); - } - --void *_hashmap_get(HashmapBase *h, const void *key); -+void* _hashmap_get(HashmapBase *h, const void *key); - static inline void *hashmap_get(Hashmap *h, const void *key) { - return _hashmap_get(HASHMAP_BASE(h), key); - } -@@ -171,7 +174,7 @@ static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) { - return _hashmap_get(HASHMAP_BASE(h), key); - } - --void *hashmap_get2(Hashmap *h, const void *key, void **rkey); -+void* hashmap_get2(Hashmap *h, const void *key, void **rkey); - static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) { - return hashmap_get2(PLAIN_HASHMAP(h), key, rkey); - } -@@ -184,7 +187,7 @@ static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) - return _hashmap_contains(HASHMAP_BASE(h), key); - } - --void *_hashmap_remove(HashmapBase *h, const void *key); -+void* _hashmap_remove(HashmapBase *h, const void *key); - static inline void *hashmap_remove(Hashmap *h, const void *key) { - return _hashmap_remove(HASHMAP_BASE(h), key); - } -@@ -192,17 +195,17 @@ static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) { - return _hashmap_remove(HASHMAP_BASE(h), key); - } - --void *hashmap_remove2(Hashmap *h, const void *key, void **rkey); -+void* hashmap_remove2(Hashmap *h, const void *key, void **rkey); - static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) { - return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey); - } - --void *_hashmap_remove_value(HashmapBase *h, const void *key, void *value); -+void* _hashmap_remove_value(HashmapBase *h, const void *key, void *value); - static inline void *hashmap_remove_value(Hashmap *h, const void *key, void *value) { - return _hashmap_remove_value(HASHMAP_BASE(h), key, value); - } - --static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { -+static inline void* ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { - return hashmap_remove_value(PLAIN_HASHMAP(h), key, value); - } - -@@ -388,13 +391,13 @@ static inline void *ordered_hashmap_first_key(OrderedHashmap *h) { - }) - - /* no hashmap_next */ --void *ordered_hashmap_next(OrderedHashmap *h, const void *key); -+void* ordered_hashmap_next(OrderedHashmap *h, const void *key); - --char **_hashmap_get_strv(HashmapBase *h); --static inline char **hashmap_get_strv(Hashmap *h) { -+char** _hashmap_get_strv(HashmapBase *h); -+static inline char** hashmap_get_strv(Hashmap *h) { - return _hashmap_get_strv(HASHMAP_BASE(h)); - } --static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { -+static inline char** ordered_hashmap_get_strv(OrderedHashmap *h) { - return _hashmap_get_strv(HASHMAP_BASE(h)); - } - -@@ -404,17 +407,25 @@ static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { - * the entries were inserted. - * It is safe to remove the current entry. - */ --#define HASHMAP_FOREACH(e, h, i) \ -- for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); ) -- --#define ORDERED_HASHMAP_FOREACH(e, h, i) \ -- for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); ) -- --#define HASHMAP_FOREACH_KEY(e, k, h, i) \ -- for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) -- --#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ -- for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) -+#define _HASHMAP_FOREACH(e, h, i) \ -+ for (Iterator i = ITERATOR_FIRST; hashmap_iterate((h), &i, (void**)&(e), NULL); ) -+#define HASHMAP_FOREACH(e, h) \ -+ _HASHMAP_FOREACH(e, h, UNIQ_T(i, UNIQ)) -+ -+#define _ORDERED_HASHMAP_FOREACH(e, h, i) \ -+ for (Iterator i = ITERATOR_FIRST; ordered_hashmap_iterate((h), &i, (void**)&(e), NULL); ) -+#define ORDERED_HASHMAP_FOREACH(e, h) \ -+ _ORDERED_HASHMAP_FOREACH(e, h, UNIQ_T(i, UNIQ)) -+ -+#define _HASHMAP_FOREACH_KEY(e, k, h, i) \ -+ for (Iterator i = ITERATOR_FIRST; hashmap_iterate((h), &i, (void**)&(e), (const void**) &(k)); ) -+#define HASHMAP_FOREACH_KEY(e, k, h) \ -+ _HASHMAP_FOREACH_KEY(e, k, h, UNIQ_T(i, UNIQ)) -+ -+#define _ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ -+ for (Iterator i = ITERATOR_FIRST; ordered_hashmap_iterate((h), &i, (void**)&(e), (const void**) &(k)); ) -+#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h) \ -+ _ORDERED_HASHMAP_FOREACH_KEY(e, k, h, UNIQ_T(i, UNIQ)) - - DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); - DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); -diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c -index ea50e26..8783ab3 100644 ---- a/src/basic/in-addr-util.c -+++ b/src/basic/in-addr-util.c -@@ -402,46 +402,6 @@ int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned - return 0; - } - --int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { -- _cleanup_free_ char *x = NULL; -- size_t l; -- int r; -- -- assert(u); -- assert(ret); -- -- /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly -- * handle IPv6 link-local addresses. */ -- -- if (family != AF_INET6) -- goto fallback; -- if (ifindex <= 0) -- goto fallback; -- -- r = in_addr_is_link_local(family, u); -- if (r < 0) -- return r; -- if (r == 0) -- goto fallback; -- -- l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1; -- x = new(char, l); -- if (!x) -- return -ENOMEM; -- -- errno = 0; -- if (!inet_ntop(family, u, x, l)) -- return errno_or_else(EINVAL); -- -- sprintf(strchr(x, 0), "%%%i", ifindex); -- -- *ret = TAKE_PTR(x); -- return 0; -- --fallback: -- return in_addr_to_string(family, u, ret); --} -- - int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret) { - _cleanup_free_ char *ip_str = NULL, *x = NULL; - int r; -@@ -795,13 +755,13 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct - - DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func); - --static void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) { -+void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) { - assert(addr); - - siphash24_compress(addr, sizeof(*addr), state); - } - --static int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) { -+int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) { - return memcmp(a, b, sizeof(*a)); - } - -diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h -index dc3f575..e5df2a8 100644 ---- a/src/basic/in-addr-util.h -+++ b/src/basic/in-addr-util.h -@@ -12,6 +12,7 @@ - union in_addr_union { - struct in_addr in; - struct in6_addr in6; -+ uint8_t bytes[CONST_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))]; - }; - - struct in_addr_data { -@@ -40,8 +41,13 @@ int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, u - int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen); - int in_addr_to_string(int family, const union in_addr_union *u, char **ret); - int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret); --int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret); - int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret); -+static inline int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { -+ return in_addr_port_ifindex_name_to_string(family, u, 0, ifindex, NULL, ret); -+} -+static inline int in_addr_port_to_string(int family, const union in_addr_union *u, uint16_t port, char **ret) { -+ return in_addr_port_ifindex_name_to_string(family, u, port, 0, NULL, ret); -+} - int in_addr_from_string(int family, const char *s, union in_addr_union *ret); - int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret); - -@@ -74,5 +80,8 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) { - * See also oss-fuzz#11344. */ - #define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} }) - -+void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state); -+int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b); -+ - extern const struct hash_ops in_addr_data_hash_ops; - extern const struct hash_ops in6_addr_hash_ops; -diff --git a/src/basic/io-util.c b/src/basic/io-util.c -index 18baadb..460649d 100644 ---- a/src/basic/io-util.c -+++ b/src/basic/io-util.c -@@ -153,10 +153,8 @@ int pipe_eof(int fd) { - int r; - - r = fd_wait_for_event(fd, POLLIN, 0); -- if (r < 0) -+ if (r <= 0) - return r; -- if (r == 0) -- return 0; - - return !!(r & POLLHUP); - } -diff --git a/src/basic/label.c b/src/basic/label.c -index 741c43c..107028e 100644 ---- a/src/basic/label.c -+++ b/src/basic/label.c -@@ -5,6 +5,7 @@ - #include - - #include "btrfs-util.h" -+#include "fs-util.h" - #include "label.h" - #include "macro.h" - #include "selinux-util.h" -@@ -45,6 +46,27 @@ int symlink_label(const char *old_path, const char *new_path) { - return mac_smack_fix(new_path, 0); - } - -+int symlink_atomic_label(const char *from, const char *to) { -+ int r; -+ -+ assert(from); -+ assert(to); -+ -+ r = mac_selinux_create_file_prepare(to, S_IFLNK); -+ if (r < 0) -+ return r; -+ -+ if (symlink_atomic(from, to) < 0) -+ r = -errno; -+ -+ mac_selinux_create_file_clear(); -+ -+ if (r < 0) -+ return r; -+ -+ return mac_smack_fix(to, 0); -+} -+ - int mknod_label(const char *pathname, mode_t mode, dev_t dev) { - int r; - -diff --git a/src/basic/label.h b/src/basic/label.h -index 6dc0f71..d99d824 100644 ---- a/src/basic/label.h -+++ b/src/basic/label.h -@@ -17,6 +17,7 @@ static inline int label_fix(const char *path, LabelFixFlags flags) { - int mkdir_label(const char *path, mode_t mode); - int mkdirat_label(int dirfd, const char *path, mode_t mode); - int symlink_label(const char *old_path, const char *new_path); -+int symlink_atomic_label(const char *from, const char *to); - int mknod_label(const char *pathname, mode_t mode, dev_t dev); - - int btrfs_subvol_make_label(const char *path); -diff --git a/src/basic/list.h b/src/basic/list.h -index f7f9700..b62c374 100644 ---- a/src/basic/list.h -+++ b/src/basic/list.h -@@ -169,3 +169,18 @@ - - #define LIST_IS_EMPTY(head) \ - (!(head)) -+ -+/* Join two lists tail to head: a->b, c->d to a->b->c->d and de-initialise second list */ -+#define LIST_JOIN(name,a,b) \ -+ do { \ -+ assert(b); \ -+ if (!(a)) \ -+ (a) = (b); \ -+ else { \ -+ typeof(*(a)) *_head = (b), *_tail; \ -+ LIST_FIND_TAIL(name, (a), _tail); \ -+ _tail->name##_next = _head; \ -+ _head->name##_prev = _tail; \ -+ } \ -+ (b) = NULL; \ -+ } while (false) -diff --git a/src/basic/log.c b/src/basic/log.c -index c6fe203..899a842 100644 ---- a/src/basic/log.c -+++ b/src/basic/log.c -@@ -838,7 +838,6 @@ _noreturn_ void log_assert_failed_realm( - const char *file, - int line, - const char *func) { -- (void) log_open(); - log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func, - "Assertion '%s' failed at %s:%u, function %s(). Aborting."); - abort(); -@@ -850,7 +849,6 @@ _noreturn_ void log_assert_failed_unreachable_realm( - const char *file, - int line, - const char *func) { -- (void) log_open(); - log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func, - "Code should not be reached '%s' at %s:%u, function %s(). Aborting."); - abort(); -diff --git a/src/basic/log.h b/src/basic/log.h -index 15807d3..137d210 100644 ---- a/src/basic/log.h -+++ b/src/basic/log.h -@@ -234,12 +234,12 @@ void log_assert_failed_return_realm( - #define log_full_errno(level, error, ...) \ - log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__) - --#define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__) -+#define log_full(level, ...) (void) log_full_errno((level), 0, __VA_ARGS__) - - int log_emergency_level(void); - - /* Normal logging */ --#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) -+#define log_debug(...) log_full_errno(LOG_DEBUG, 0, __VA_ARGS__) - #define log_info(...) log_full(LOG_INFO, __VA_ARGS__) - #define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) - #define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) -diff --git a/src/basic/macro.h b/src/basic/macro.h -index ceea817..41c2c32 100644 ---- a/src/basic/macro.h -+++ b/src/basic/macro.h -@@ -538,6 +538,9 @@ static inline int __coverity_check_and_return__(int condition) { - (y) = (_t); \ - } while (false) - -+#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL })) -+#define STRV_MAKE_EMPTY ((char*[1]) { NULL }) -+ - /* Iterates through a specified list of pointers. Accepts NULL pointers, but uses (void*) -1 as internal marker for EOL. */ - #define FOREACH_POINTER(p, x, ...) \ - for (typeof(p) *_l = (typeof(p)[]) { ({ p = x; }), ##__VA_ARGS__, (void*) -1 }; \ -diff --git a/src/basic/meson.build b/src/basic/meson.build -index 90924d6..42d0754 100644 ---- a/src/basic/meson.build -+++ b/src/basic/meson.build -@@ -39,6 +39,7 @@ basic_sources = files(''' - device-nodes.h - dirent-util.c - dirent-util.h -+ dlfcn-util.c - dlfcn-util.h - efivars.c - efivars.h -diff --git a/src/basic/missing_capability.h b/src/basic/missing_capability.h -index dd6bccd..c52cd44 100644 ---- a/src/basic/missing_capability.h -+++ b/src/basic/missing_capability.h -@@ -5,24 +5,35 @@ - - /* 3a101b8de0d39403b2c7e5c23fd0b005668acf48 (3.16) */ - #ifndef CAP_AUDIT_READ --#define CAP_AUDIT_READ 37 -- --#undef CAP_LAST_CAP --#define CAP_LAST_CAP CAP_AUDIT_READ -+# define CAP_AUDIT_READ 37 - #endif - - /* 980737282232b752bb14dab96d77665c15889c36 (5.8) */ - #ifndef CAP_PERFMON --#define CAP_PERFMON 38 -- --#undef CAP_LAST_CAP --#define CAP_LAST_CAP CAP_PERFMON -+# define CAP_PERFMON 38 - #endif - - /* a17b53c4a4b55ec322c132b6670743612229ee9c (5.8) */ - #ifndef CAP_BPF --#define CAP_BPF 39 -+# define CAP_BPF 39 -+#endif - --#undef CAP_LAST_CAP --#define CAP_LAST_CAP CAP_BPF -+/* 124ea650d3072b005457faed69909221c2905a1f (5.9) */ -+#ifndef CAP_CHECKPOINT_RESTORE -+# define CAP_CHECKPOINT_RESTORE 40 -+#endif -+ -+#define SYSTEMD_CAP_LAST_CAP CAP_CHECKPOINT_RESTORE -+ -+#ifdef CAP_LAST_CAP -+# if CAP_LAST_CAP > SYSTEMD_CAP_LAST_CAP -+# if DEVELOPER_MODE && defined(TEST_CAPABILITY_C) -+# warning "The capability list here is outdated" -+# endif -+# else -+# undef CAP_LAST_CAP -+# endif -+#endif -+#ifndef CAP_LAST_CAP -+# define CAP_LAST_CAP SYSTEMD_CAP_LAST_CAP - #endif -diff --git a/src/basic/missing_loop.h b/src/basic/missing_loop.h -new file mode 100644 -index 0000000..5326777 ---- /dev/null -+++ b/src/basic/missing_loop.h -@@ -0,0 +1,15 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#include -+ -+#ifndef LOOP_CONFIGURE -+struct loop_config { -+ __u32 fd; -+ __u32 block_size; -+ struct loop_info64 info; -+ __u64 __reserved[8]; -+}; -+ -+#define LOOP_CONFIGURE 0x4C0A -+#endif -diff --git a/src/basic/missing_network.h b/src/basic/missing_network.h -index 2578794..a25a148 100644 ---- a/src/basic/missing_network.h -+++ b/src/basic/missing_network.h -@@ -6,6 +6,11 @@ - #define IPV6_UNICAST_IF 76 - #endif - -+/* linux/in6.h or netinet/in.h */ -+#ifndef IPV6_TRANSPARENT -+#define IPV6_TRANSPARENT 75 -+#endif -+ - /* Not exposed but defined at include/net/ip.h */ - #ifndef IPV4_MIN_MTU - #define IPV4_MIN_MTU 68 -diff --git a/src/basic/missing_socket.h b/src/basic/missing_socket.h -index 8c3fec1..c4f3344 100644 ---- a/src/basic/missing_socket.h -+++ b/src/basic/missing_socket.h -@@ -63,6 +63,10 @@ struct sockaddr_vm { - #define IP_TRANSPARENT 19 - #endif - -+#ifndef IPV6_FREEBIND -+#define IPV6_FREEBIND 78 -+#endif -+ - /* linux/sockios.h */ - #ifndef SIOCGSKNS - #define SIOCGSKNS 0x894C -diff --git a/src/basic/missing_stat.h b/src/basic/missing_stat.h -index 5116206..7bdc8a7 100644 ---- a/src/basic/missing_stat.h -+++ b/src/basic/missing_stat.h -@@ -8,44 +8,128 @@ - #include - #endif - --/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+/* Thew newest definition we are aware of (fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60; 5.8) */ -+#define STATX_DEFINITION { \ -+ __u32 stx_mask; \ -+ __u32 stx_blksize; \ -+ __u64 stx_attributes; \ -+ __u32 stx_nlink; \ -+ __u32 stx_uid; \ -+ __u32 stx_gid; \ -+ __u16 stx_mode; \ -+ __u16 __spare0[1]; \ -+ __u64 stx_ino; \ -+ __u64 stx_size; \ -+ __u64 stx_blocks; \ -+ __u64 stx_attributes_mask; \ -+ struct statx_timestamp stx_atime; \ -+ struct statx_timestamp stx_btime; \ -+ struct statx_timestamp stx_ctime; \ -+ struct statx_timestamp stx_mtime; \ -+ __u32 stx_rdev_major; \ -+ __u32 stx_rdev_minor; \ -+ __u32 stx_dev_major; \ -+ __u32 stx_dev_minor; \ -+ __u64 stx_mnt_id; \ -+ __u64 __spare2; \ -+ __u64 __spare3[12]; \ -+} -+ - #if !HAVE_STRUCT_STATX - struct statx_timestamp { - __s64 tv_sec; - __u32 tv_nsec; - __s32 __reserved; - }; --struct statx { -- __u32 stx_mask; -- __u32 stx_blksize; -- __u64 stx_attributes; -- __u32 stx_nlink; -- __u32 stx_uid; -- __u32 stx_gid; -- __u16 stx_mode; -- __u16 __spare0[1]; -- __u64 stx_ino; -- __u64 stx_size; -- __u64 stx_blocks; -- __u64 stx_attributes_mask; -- struct statx_timestamp stx_atime; -- struct statx_timestamp stx_btime; -- struct statx_timestamp stx_ctime; -- struct statx_timestamp stx_mtime; -- __u32 stx_rdev_major; -- __u32 stx_rdev_minor; -- __u32 stx_dev_major; -- __u32 stx_dev_minor; -- __u64 __spare2[14]; --}; -+ -+struct statx STATX_DEFINITION; - #endif - -+/* Always define the newest version we are aware of as a distinct type, so that we can use it even if glibc -+ * defines an older definition */ -+struct new_statx STATX_DEFINITION; -+ - /* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ --#ifndef STATX_BTIME --#define STATX_BTIME 0x00000800U -+#ifndef AT_STATX_SYNC_AS_STAT -+#define AT_STATX_SYNC_AS_STAT 0x0000 -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef AT_STATX_FORCE_SYNC -+#define AT_STATX_FORCE_SYNC 0x2000 - #endif - - /* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ - #ifndef AT_STATX_DONT_SYNC - #define AT_STATX_DONT_SYNC 0x4000 - #endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_TYPE -+#define STATX_TYPE 0x00000001U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_MODE -+#define STATX_MODE 0x00000002U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_NLINK -+#define STATX_NLINK 0x00000004U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_UID -+#define STATX_UID 0x00000008U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_GID -+#define STATX_GID 0x00000010U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_ATIME -+#define STATX_ATIME 0x00000020U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_MTIME -+#define STATX_MTIME 0x00000040U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_CTIME -+#define STATX_CTIME 0x00000080U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_INO -+#define STATX_INO 0x00000100U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_SIZE -+#define STATX_SIZE 0x00000200U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_BLOCKS -+#define STATX_BLOCKS 0x00000400U -+#endif -+ -+/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ -+#ifndef STATX_BTIME -+#define STATX_BTIME 0x00000800U -+#endif -+ -+/* fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60 (5.8) */ -+#ifndef STATX_MNT_ID -+#define STATX_MNT_ID 0x00001000U -+#endif -+ -+/* 80340fe3605c0e78cfe496c3b3878be828cfdbfe (5.8) */ -+#ifndef STATX_ATTR_MOUNT_ROOT -+#define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */ -+#endif -diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h -index 41164ea..a2acdc6 100644 ---- a/src/basic/missing_syscall.h -+++ b/src/basic/missing_syscall.h -@@ -33,39 +33,49 @@ static inline int missing_pivot_root(const char *new_root, const char *put_old) - - /* ======================================================================= */ - --#if !HAVE_MEMFD_CREATE -+#if defined __x86_64__ -+# define systemd_NR_memfd_create 319 -+#elif defined __arm__ -+# define systemd_NR_memfd_create 385 -+#elif defined __aarch64__ -+# define systemd_NR_memfd_create 279 -+#elif defined(__powerpc__) -+# define systemd_NR_memfd_create 360 -+#elif defined __s390__ -+# define systemd_NR_memfd_create 350 -+#elif defined _MIPS_SIM -+# if _MIPS_SIM == _MIPS_SIM_ABI32 -+# define systemd_NR_memfd_create 4354 -+# endif -+# if _MIPS_SIM == _MIPS_SIM_NABI32 -+# define systemd_NR_memfd_create 6318 -+# endif -+# if _MIPS_SIM == _MIPS_SIM_ABI64 -+# define systemd_NR_memfd_create 5314 -+# endif -+#elif defined __i386__ -+# define systemd_NR_memfd_create 356 -+#elif defined __arc__ -+# define systemd_NR_memfd_create 279 -+#else -+# warning "memfd_create() syscall number unknown for your architecture" -+#endif -+ - /* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_memfd_create && __NR_memfd_create >= 0) --# if defined __NR_memfd_create --# undef __NR_memfd_create --# endif --# if defined __x86_64__ --# define __NR_memfd_create 319 --# elif defined __arm__ --# define __NR_memfd_create 385 --# elif defined __aarch64__ --# define __NR_memfd_create 279 --# elif defined __s390__ --# define __NR_memfd_create 350 --# elif defined _MIPS_SIM --# if _MIPS_SIM == _MIPS_SIM_ABI32 --# define __NR_memfd_create 4354 --# endif --# if _MIPS_SIM == _MIPS_SIM_NABI32 --# define __NR_memfd_create 6318 --# endif --# if _MIPS_SIM == _MIPS_SIM_ABI64 --# define __NR_memfd_create 5314 --# endif --# elif defined __i386__ --# define __NR_memfd_create 356 --# elif defined __arc__ --# define __NR_memfd_create 279 --# else --# warning "__NR_memfd_create unknown for your architecture" --# endif -+#if defined __NR_memfd_create && __NR_memfd_create >= 0 -+# if defined systemd_NR_memfd_create -+assert_cc(__NR_memfd_create == systemd_NR_memfd_create); -+# endif -+#else -+# if defined __NR_memfd_create -+# undef __NR_memfd_create - # endif -+# if defined systemd_NR_memfd_create -+# define __NR_memfd_create systemd_NR_memfd_create -+# endif -+#endif - -+#if !HAVE_MEMFD_CREATE - static inline int missing_memfd_create(const char *name, unsigned int flags) { - # ifdef __NR_memfd_create - return syscall(__NR_memfd_create, name, flags); -@@ -80,45 +90,53 @@ static inline int missing_memfd_create(const char *name, unsigned int flags) { - - /* ======================================================================= */ - --#if !HAVE_GETRANDOM -+#if defined __x86_64__ -+# define systemd_NR_getrandom 318 -+#elif defined(__i386__) -+# define systemd_NR_getrandom 355 -+#elif defined(__arm__) -+# define systemd_NR_getrandom 384 -+#elif defined(__aarch64__) -+# define systemd_NR_getrandom 278 -+#elif defined(__ia64__) -+# define systemd_NR_getrandom 1339 -+#elif defined(__m68k__) -+# define systemd_NR_getrandom 352 -+#elif defined(__s390x__) -+# define systemd_NR_getrandom 349 -+#elif defined(__powerpc__) -+# define systemd_NR_getrandom 359 -+#elif defined _MIPS_SIM -+# if _MIPS_SIM == _MIPS_SIM_ABI32 -+# define systemd_NR_getrandom 4353 -+# endif -+# if _MIPS_SIM == _MIPS_SIM_NABI32 -+# define systemd_NR_getrandom 6317 -+# endif -+# if _MIPS_SIM == _MIPS_SIM_ABI64 -+# define systemd_NR_getrandom 5313 -+# endif -+#elif defined(__arc__) -+# define systemd_NR_getrandom 278 -+#else -+# warning "getrandom() syscall number unknown for your architecture" -+#endif -+ - /* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_getrandom && __NR_getrandom >= 0) --# if defined __NR_getrandom --# undef __NR_getrandom --# endif --# if defined __x86_64__ --# define __NR_getrandom 318 --# elif defined(__i386__) --# define __NR_getrandom 355 --# elif defined(__arm__) --# define __NR_getrandom 384 --# elif defined(__aarch64__) --# define __NR_getrandom 278 --# elif defined(__ia64__) --# define __NR_getrandom 1339 --# elif defined(__m68k__) --# define __NR_getrandom 352 --# elif defined(__s390x__) --# define __NR_getrandom 349 --# elif defined(__powerpc__) --# define __NR_getrandom 359 --# elif defined _MIPS_SIM --# if _MIPS_SIM == _MIPS_SIM_ABI32 --# define __NR_getrandom 4353 --# endif --# if _MIPS_SIM == _MIPS_SIM_NABI32 --# define __NR_getrandom 6317 --# endif --# if _MIPS_SIM == _MIPS_SIM_ABI64 --# define __NR_getrandom 5313 --# endif --# elif defined(__arc__) --# define __NR_getrandom 278 --# else --# warning "__NR_getrandom unknown for your architecture" --# endif -+#if defined __NR_getrandom && __NR_getrandom >= 0 -+# if defined systemd_NR_getrandom -+assert_cc(__NR_getrandom == systemd_NR_getrandom); -+# endif -+#else -+# if defined __NR_getrandom -+# undef __NR_getrandom -+# endif -+# if defined systemd_NR_getrandom -+# define __NR_getrandom systemd_NR_getrandom - # endif -+#endif - -+#if !HAVE_GETRANDOM - static inline int missing_getrandom(void *buffer, size_t count, unsigned flags) { - # ifdef __NR_getrandom - return syscall(__NR_getrandom, buffer, count, flags); -@@ -133,9 +151,14 @@ static inline int missing_getrandom(void *buffer, size_t count, unsigned flags) - - /* ======================================================================= */ - -+/* The syscall has been defined since forever, but the glibc wrapper was missing. */ - #if !HAVE_GETTID - static inline pid_t missing_gettid(void) { -+# if defined __NR_gettid && __NR_gettid >= 0 - return (pid_t) syscall(__NR_gettid); -+# else -+# error "__NR_gettid not defined" -+# endif - } - - # define gettid missing_gettid -@@ -143,27 +166,39 @@ static inline pid_t missing_gettid(void) { - - /* ======================================================================= */ - --#if !HAVE_NAME_TO_HANDLE_AT -+#if defined(__x86_64__) -+# define systemd_NR_name_to_handle_at 303 -+#elif defined(__i386__) -+# define systemd_NR_name_to_handle_at 341 -+#elif defined(__arm__) -+# define systemd_NR_name_to_handle_at 370 -+#elif defined __aarch64__ -+# define systemd_NR_name_to_handle_at 264 -+#elif defined(__powerpc__) -+# define systemd_NR_name_to_handle_at 345 -+#elif defined __s390__ || defined __s390x__ -+# define systemd_NR_name_to_handle_at 335 -+#elif defined(__arc__) -+# define systemd_NR_name_to_handle_at 264 -+#else -+# warning "name_to_handle_at number is not defined" -+#endif -+ - /* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_name_to_handle_at && __NR_name_to_handle_at >= 0) --# if defined __NR_name_to_handle_at --# undef __NR_name_to_handle_at --# endif --# if defined(__x86_64__) --# define __NR_name_to_handle_at 303 --# elif defined(__i386__) --# define __NR_name_to_handle_at 341 --# elif defined(__arm__) --# define __NR_name_to_handle_at 370 --# elif defined(__powerpc__) --# define __NR_name_to_handle_at 345 --# elif defined(__arc__) --# define __NR_name_to_handle_at 264 --# else --# error "__NR_name_to_handle_at is not defined" --# endif -+#if defined __NR_name_to_handle_at && __NR_name_to_handle_at >= 0 -+# if defined systemd_NR_name_to_handle_at -+assert_cc(__NR_name_to_handle_at == systemd_NR_name_to_handle_at); - # endif -+#else -+# if defined __NR_name_to_handle_at -+# undef __NR_name_to_handle_at -+# endif -+# if defined systemd_NR_name_to_handle_at -+# define __NR_name_to_handle_at systemd_NR_name_to_handle_at -+# endif -+#endif - -+#if !HAVE_NAME_TO_HANDLE_AT - struct file_handle { - unsigned int handle_bytes; - int handle_type; -@@ -184,23 +219,39 @@ static inline int missing_name_to_handle_at(int fd, const char *name, struct fil - - /* ======================================================================= */ - --#if !HAVE_SETNS -+#if defined __aarch64__ -+# define systemd_NR_setns 268 -+#elif defined __arm__ -+# define systemd_NR_setns 375 -+#elif defined(__x86_64__) -+# define systemd_NR_setns 308 -+#elif defined(__i386__) -+# define systemd_NR_setns 346 -+#elif defined(__powerpc__) -+# define systemd_NR_setns 350 -+#elif defined __s390__ || defined __s390x__ -+# define systemd_NR_setns 339 -+#elif defined(__arc__) -+# define systemd_NR_setns 268 -+#else -+# warning "setns() syscall number unknown for your architecture" -+#endif -+ - /* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_setns && __NR_setns >= 0) --# if defined __NR_setns --# undef __NR_setns --# endif --# if defined(__x86_64__) --# define __NR_setns 308 --# elif defined(__i386__) --# define __NR_setns 346 --# elif defined(__arc__) --# define __NR_setns 268 --# else --# error "__NR_setns is not defined" --# endif -+#if defined __NR_setns && __NR_setns >= 0 -+# if defined systemd_NR_setns -+assert_cc(__NR_setns == systemd_NR_setns); - # endif -+#else -+# if defined __NR_setns -+# undef __NR_setns -+# endif -+# if defined systemd_NR_setns -+# define __NR_setns systemd_NR_setns -+# endif -+#endif - -+#if !HAVE_SETNS - static inline int missing_setns(int fd, int nstype) { - # ifdef __NR_setns - return syscall(__NR_setns, fd, nstype); -@@ -225,41 +276,49 @@ static inline pid_t raw_getpid(void) { - - /* ======================================================================= */ - --#if !HAVE_RENAMEAT2 -+#if defined __x86_64__ -+# define systemd_NR_renameat2 316 -+#elif defined __arm__ -+# define systemd_NR_renameat2 382 -+#elif defined __aarch64__ -+# define systemd_NR_renameat2 276 -+#elif defined _MIPS_SIM -+# if _MIPS_SIM == _MIPS_SIM_ABI32 -+# define systemd_NR_renameat2 4351 -+# endif -+# if _MIPS_SIM == _MIPS_SIM_NABI32 -+# define systemd_NR_renameat2 6315 -+# endif -+# if _MIPS_SIM == _MIPS_SIM_ABI64 -+# define systemd_NR_renameat2 5311 -+# endif -+#elif defined __i386__ -+# define systemd_NR_renameat2 353 -+#elif defined __powerpc64__ -+# define systemd_NR_renameat2 357 -+#elif defined __s390__ || defined __s390x__ -+# define systemd_NR_renameat2 347 -+#elif defined __arc__ -+# define systemd_NR_renameat2 276 -+#else -+# warning "renameat2() syscall number unknown for your architecture" -+#endif -+ - /* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_renameat2 && __NR_renameat2 >= 0) --# if defined __NR_renameat2 --# undef __NR_renameat2 --# endif --# if defined __x86_64__ --# define __NR_renameat2 316 --# elif defined __arm__ --# define __NR_renameat2 382 --# elif defined __aarch64__ --# define __NR_renameat2 276 --# elif defined _MIPS_SIM --# if _MIPS_SIM == _MIPS_SIM_ABI32 --# define __NR_renameat2 4351 --# endif --# if _MIPS_SIM == _MIPS_SIM_NABI32 --# define __NR_renameat2 6315 --# endif --# if _MIPS_SIM == _MIPS_SIM_ABI64 --# define __NR_renameat2 5311 --# endif --# elif defined __i386__ --# define __NR_renameat2 353 --# elif defined __powerpc64__ --# define __NR_renameat2 357 --# elif defined __s390__ || defined __s390x__ --# define __NR_renameat2 347 --# elif defined __arc__ --# define __NR_renameat2 276 --# else --# warning "__NR_renameat2 unknown for your architecture" --# endif -+#if defined __NR_renameat2 && __NR_renameat2 >= 0 -+# if defined systemd_NR_renameat2 -+assert_cc(__NR_renameat2 == systemd_NR_renameat2); - # endif -+#else -+# if defined __NR_renameat2 -+# undef __NR_renameat2 -+# endif -+# if defined systemd_NR_renameat2 -+# define __NR_renameat2 systemd_NR_renameat2 -+# endif -+#endif - -+#if !HAVE_RENAMEAT2 - static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) { - # ifdef __NR_renameat2 - return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags); -@@ -326,31 +385,39 @@ static inline key_serial_t missing_request_key(const char *type, const char *des - - /* ======================================================================= */ - --#if !HAVE_COPY_FILE_RANGE -+#if defined(__x86_64__) -+# define systemd_NR_copy_file_range 326 -+#elif defined(__i386__) -+# define systemd_NR_copy_file_range 377 -+#elif defined __s390__ -+# define systemd_NR_copy_file_range 375 -+#elif defined __arm__ -+# define systemd_NR_copy_file_range 391 -+#elif defined __aarch64__ -+# define systemd_NR_copy_file_range 285 -+#elif defined __powerpc__ -+# define systemd_NR_copy_file_range 379 -+#elif defined __arc__ -+# define systemd_NR_copy_file_range 285 -+#else -+# warning "copy_file_range() syscall number unknown for your architecture" -+#endif -+ - /* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_copy_file_range && __NR_copy_file_range >= 0) --# if defined __NR_copy_file_range --# undef __NR_copy_file_range --# endif --# if defined(__x86_64__) --# define __NR_copy_file_range 326 --# elif defined(__i386__) --# define __NR_copy_file_range 377 --# elif defined __s390__ --# define __NR_copy_file_range 375 --# elif defined __arm__ --# define __NR_copy_file_range 391 --# elif defined __aarch64__ --# define __NR_copy_file_range 285 --# elif defined __powerpc__ --# define __NR_copy_file_range 379 --# elif defined __arc__ --# define __NR_copy_file_range 285 --# else --# warning "__NR_copy_file_range not defined for your architecture" --# endif -+#if defined __NR_copy_file_range && __NR_copy_file_range >= 0 -+# if defined systemd_NR_copy_file_range -+assert_cc(__NR_copy_file_range == systemd_NR_copy_file_range); - # endif -+#else -+# if defined __NR_copy_file_range -+# undef __NR_copy_file_range -+# endif -+# if defined systemd_NR_copy_file_range -+# define __NR_copy_file_range systemd_NR_copy_file_range -+# endif -+#endif - -+#if !HAVE_COPY_FILE_RANGE - static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in, - int fd_out, loff_t *off_out, - size_t len, -@@ -368,31 +435,41 @@ static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in, - - /* ======================================================================= */ - --#if !HAVE_BPF -+#if defined __i386__ -+# define systemd_NR_bpf 357 -+#elif defined __x86_64__ -+# define systemd_NR_bpf 321 -+#elif defined __aarch64__ -+# define systemd_NR_bpf 280 -+#elif defined __arm__ -+# define systemd_NR_bpf 386 -+#elif defined(__powerpc__) -+# define systemd_NR_bpf 361 -+#elif defined __sparc__ -+# define systemd_NR_bpf 349 -+#elif defined __s390__ -+# define systemd_NR_bpf 351 -+#elif defined __tilegx__ -+# define systemd_NR_bpf 280 -+#else -+# warning "bpf() syscall number unknown for your architecture" -+#endif -+ - /* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_bpf && __NR_bpf >= 0) --# if defined __NR_bpf --# undef __NR_bpf --# endif --# if defined __i386__ --# define __NR_bpf 357 --# elif defined __x86_64__ --# define __NR_bpf 321 --# elif defined __aarch64__ --# define __NR_bpf 280 --# elif defined __arm__ --# define __NR_bpf 386 --# elif defined __sparc__ --# define __NR_bpf 349 --# elif defined __s390__ --# define __NR_bpf 351 --# elif defined __tilegx__ --# define __NR_bpf 280 --# else --# warning "__NR_bpf not defined for your architecture" --# endif -+#if defined __NR_bpf && __NR_bpf >= 0 -+# if defined systemd_NR_bpf -+assert_cc(__NR_bpf == systemd_NR_bpf); -+# endif -+#else -+# if defined __NR_bpf -+# undef __NR_bpf - # endif -+# if defined systemd_NR_bpf -+# define __NR_bpf systemd_NR_bpf -+# endif -+#endif - -+#if !HAVE_BPF - union bpf_attr; - - static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) { -@@ -410,69 +487,84 @@ static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) { - /* ======================================================================= */ - - #ifndef __IGNORE_pkey_mprotect -+# if defined __i386__ -+# define systemd_NR_pkey_mprotect 380 -+# elif defined __x86_64__ -+# define systemd_NR_pkey_mprotect 329 -+# elif defined __aarch64__ -+# define systemd_NR_pkey_mprotect 288 -+# elif defined __arm__ -+# define systemd_NR_pkey_mprotect 394 -+# elif defined __powerpc__ -+# define systemd_NR_pkey_mprotect 386 -+# elif defined __s390__ -+# define systemd_NR_pkey_mprotect 384 -+# elif defined _MIPS_SIM -+# if _MIPS_SIM == _MIPS_SIM_ABI32 -+# define systemd_NR_pkey_mprotect 4363 -+# endif -+# if _MIPS_SIM == _MIPS_SIM_NABI32 -+# define systemd_NR_pkey_mprotect 6327 -+# endif -+# if _MIPS_SIM == _MIPS_SIM_ABI64 -+# define systemd_NR_pkey_mprotect 5323 -+# endif -+# else -+# warning "pkey_mprotect() syscall number unknown for your architecture" -+# endif -+ - /* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_pkey_mprotect && __NR_pkey_mprotect >= 0) -+# if defined __NR_pkey_mprotect && __NR_pkey_mprotect >= 0 -+# if defined systemd_NR_pkey_mprotect -+assert_cc(__NR_pkey_mprotect == systemd_NR_pkey_mprotect); -+# endif -+# else - # if defined __NR_pkey_mprotect - # undef __NR_pkey_mprotect - # endif --# if defined __i386__ --# define __NR_pkey_mprotect 380 --# elif defined __x86_64__ --# define __NR_pkey_mprotect 329 --# elif defined __arm__ --# define __NR_pkey_mprotect 394 --# elif defined __aarch64__ --# define __NR_pkey_mprotect 394 --# elif defined __powerpc__ --# define __NR_pkey_mprotect 386 --# elif defined __s390__ --# define __NR_pkey_mprotect 384 --# elif defined _MIPS_SIM --# if _MIPS_SIM == _MIPS_SIM_ABI32 --# define __NR_pkey_mprotect 4363 --# endif --# if _MIPS_SIM == _MIPS_SIM_NABI32 --# define __NR_pkey_mprotect 6327 --# endif --# if _MIPS_SIM == _MIPS_SIM_ABI64 --# define __NR_pkey_mprotect 5323 --# endif --# else --# warning "__NR_pkey_mprotect not defined for your architecture" -+# if defined systemd_NR_pkey_mprotect -+# define __NR_pkey_mprotect systemd_NR_pkey_mprotect - # endif - # endif - #endif - - /* ======================================================================= */ - --#if !HAVE_STATX -+#if defined __aarch64__ -+# define systemd_NR_statx 291 -+#elif defined __arm__ -+# define systemd_NR_statx 397 -+#elif defined __alpha__ -+# define systemd_NR_statx 522 -+#elif defined __i386__ || defined __powerpc64__ -+# define systemd_NR_statx 383 -+#elif defined __s390__ || defined __s390x__ -+# define systemd_NR_statx 379 -+#elif defined __sparc__ -+# define systemd_NR_statx 360 -+#elif defined __x86_64__ -+# define systemd_NR_statx 332 -+#else -+# warning "statx() syscall number unknown for your architecture" -+#endif -+ - /* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_statx && __NR_statx >= 0) --# if defined __NR_statx --# undef __NR_statx --# endif --# if defined __aarch64__ || defined __arm__ --# define __NR_statx 397 --# elif defined __alpha__ --# define __NR_statx 522 --# elif defined __i386__ || defined __powerpc64__ --# define __NR_statx 383 --# elif defined __sparc__ --# define __NR_statx 360 --# elif defined __x86_64__ --# define __NR_statx 332 --# else --# warning "__NR_statx not defined for your architecture" --# endif -+#if defined __NR_statx && __NR_statx >= 0 -+# if defined systemd_NR_statx -+assert_cc(__NR_statx == systemd_NR_statx); -+# endif -+#else -+# if defined __NR_statx -+# undef __NR_statx -+# endif -+# if defined systemd_NR_statx -+# define __NR_statx systemd_NR_statx - # endif -- --struct statx; - #endif - --/* This typedef is supposed to be always defined. */ --typedef struct statx struct_statx; -- - #if !HAVE_STATX -+struct statx; -+ - static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) { - # ifdef __NR_statx - return syscall(__NR_statx, dfd, filename, flags, mask, buffer); -@@ -481,12 +573,18 @@ static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flag - return -1; - # endif - } -+#endif - --# define statx missing_statx -+/* This typedef is supposed to be always defined. */ -+typedef struct statx struct_statx; -+ -+#if !HAVE_STATX -+# define statx(dfd, filename, flags, mask, buffer) missing_statx(dfd, filename, flags, mask, buffer) - #endif - --#if !HAVE_SET_MEMPOLICY -+/* ======================================================================= */ - -+#if !HAVE_SET_MEMPOLICY - enum { - MPOL_DEFAULT, - MPOL_PREFERRED, -@@ -515,7 +613,7 @@ static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask, - unsigned long maxnode, void *addr, - unsigned long flags) { - long i; --# ifdef __NR_get_mempolicy -+# if defined __NR_get_mempolicy && __NR_get_mempolicy >= 0 - i = syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags); - # else - errno = ENOSYS; -@@ -524,47 +622,85 @@ static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask, - return i; - } - --#define get_mempolicy missing_get_mempolicy -+# define get_mempolicy missing_get_mempolicy - #endif - --#if !HAVE_PIDFD_OPEN --/* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_pidfd_open && __NR_pidfd_open >= 0) --# if defined __NR_pidfd_open --# undef __NR_pidfd_open --# endif --# define __NR_pidfd_open 434 -+/* ======================================================================= */ -+ -+/* should be always defined, see kernel 39036cd2727395c3369b1051005da74059a85317 */ -+#if defined(__alpha__) -+# define systemd_NR_pidfd_send_signal 534 -+#else -+# define systemd_NR_pidfd_send_signal 424 - #endif --static inline int pidfd_open(pid_t pid, unsigned flags) { --#ifdef __NR_pidfd_open -- return syscall(__NR_pidfd_open, pid, flags); -+ -+/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -+#if defined __NR_pidfd_send_signal && __NR_pidfd_send_signal >= 0 -+# if defined systemd_NR_pidfd_send_signal -+assert_cc(__NR_pidfd_send_signal == systemd_NR_pidfd_send_signal); -+# endif - #else -+# if defined __NR_pidfd_send_signal -+# undef __NR_pidfd_send_signal -+# endif -+# define __NR_pidfd_send_signal systemd_NR_pidfd_send_signal -+#endif -+ -+#if !HAVE_PIDFD_SEND_SIGNAL -+static inline int missing_pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) { -+# ifdef __NR_pidfd_open -+ return syscall(__NR_pidfd_send_signal, fd, sig, info, flags); -+# else - errno = ENOSYS; - return -1; --#endif -+# endif - } -+ -+# define pidfd_send_signal missing_pidfd_send_signal - #endif - --#if !HAVE_PIDFD_SEND_SIGNAL --/* may be (invalid) negative number due to libseccomp, see PR 13319 */ --# if ! (defined __NR_pidfd_send_signal && __NR_pidfd_send_signal >= 0) --# if defined __NR_pidfd_send_signal --# undef __NR_pidfd_send_signal --# endif --# define __NR_pidfd_send_signal 424 -+/* should be always defined, see kernel 7615d9e1780e26e0178c93c55b73309a5dc093d7 */ -+#if defined(__alpha__) -+# define systemd_NR_pidfd_open 544 -+#else -+# define systemd_NR_pidfd_open 434 - #endif --static inline int pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) { --#ifdef __NR_pidfd_open -- return syscall(__NR_pidfd_send_signal, fd, sig, info, flags); -+ -+/* may be (invalid) negative number due to libseccomp, see PR 13319 */ -+#if defined __NR_pidfd_open && __NR_pidfd_open >= 0 -+# if defined systemd_NR_pidfd_open -+assert_cc(__NR_pidfd_open == systemd_NR_pidfd_open); -+# endif - #else -+# if defined __NR_pidfd_open -+# undef __NR_pidfd_open -+# endif -+# define __NR_pidfd_open systemd_NR_pidfd_open -+#endif -+ -+#if !HAVE_PIDFD_OPEN -+static inline int missing_pidfd_open(pid_t pid, unsigned flags) { -+# ifdef __NR_pidfd_open -+ return syscall(__NR_pidfd_open, pid, flags); -+# else - errno = ENOSYS; - return -1; --#endif -+# endif - } -+ -+# define pidfd_open missing_pidfd_open - #endif - -+/* ======================================================================= */ -+ - #if !HAVE_RT_SIGQUEUEINFO --static inline int rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info) { -+static inline int missing_rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *info) { -+# if defined __NR_rt_sigqueueinfo && __NR_rt_sigqueueinfo >= 0 - return syscall(__NR_rt_sigqueueinfo, tgid, sig, info); -+# else -+# error "__NR_rt_sigqueueinfo not defined" -+# endif - } -+ -+# define rt_sigqueueinfo missing_rt_sigqueueinfo - #endif -diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c -index 6ebc2b9..eea8f1c 100644 ---- a/src/basic/mkdir.c -+++ b/src/basic/mkdir.c -@@ -5,6 +5,7 @@ - #include - - #include "alloc-util.h" -+#include "fd-util.h" - #include "format-util.h" - #include "fs-util.h" - #include "macro.h" -@@ -106,7 +107,7 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, ui - /* return immediately if directory exists */ - e = strrchr(path, '/'); - if (!e) -- return -EINVAL; -+ return 0; - - if (e == path) - return 0; -@@ -187,3 +188,54 @@ int mkdir_p(const char *path, mode_t mode) { - int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) { - return mkdir_p_internal(prefix, path, mode, uid, gid, flags, mkdir_errno_wrapper); - } -+ -+int mkdir_p_root(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m) { -+ _cleanup_free_ char *pp = NULL; -+ _cleanup_close_ int dfd = -1; -+ const char *bn; -+ int r; -+ -+ pp = dirname_malloc(p); -+ if (!pp) -+ return -ENOMEM; -+ -+ /* Not top-level? */ -+ if (!(path_equal(pp, "/") || isempty(pp) || path_equal(pp, "."))) { -+ -+ /* Recurse up */ -+ r = mkdir_p_root(root, pp, uid, gid, m); -+ if (r < 0) -+ return r; -+ } -+ -+ bn = basename(p); -+ if (path_equal(bn, "/") || isempty(bn) || path_equal(bn, ".")) -+ return 0; -+ -+ if (!filename_is_valid(bn)) -+ return -EINVAL; -+ -+ dfd = chase_symlinks_and_open(pp, root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_DIRECTORY, NULL); -+ if (dfd < 0) -+ return dfd; -+ -+ if (mkdirat(dfd, bn, m) < 0) { -+ if (errno == EEXIST) -+ return 0; -+ -+ return -errno; -+ } -+ -+ if (uid_is_valid(uid) || gid_is_valid(gid)) { -+ _cleanup_close_ int nfd = -1; -+ -+ nfd = openat(dfd, bn, O_RDONLY|O_CLOEXEC|O_DIRECTORY); -+ if (nfd < 0) -+ return -errno; -+ -+ if (fchown(nfd, uid, gid) < 0) -+ return -errno; -+ } -+ -+ return 1; -+} -diff --git a/src/basic/mkdir.h b/src/basic/mkdir.h -index 8bfaaf4..fc66a7d 100644 ---- a/src/basic/mkdir.h -+++ b/src/basic/mkdir.h -@@ -26,3 +26,5 @@ typedef int (*mkdir_func_t)(const char *pathname, mode_t mode); - int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); - int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); - int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); -+ -+int mkdir_p_root(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m); -diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c -index df1f0ac..681da74 100644 ---- a/src/basic/mountpoint-util.c -+++ b/src/basic/mountpoint-util.c -@@ -8,9 +8,12 @@ - #include "fd-util.h" - #include "fileio.h" - #include "fs-util.h" -+#include "missing_stat.h" -+#include "missing_syscall.h" - #include "mountpoint-util.h" - #include "parse-util.h" - #include "path-util.h" -+#include "stat-util.h" - #include "stdio-util.h" - #include "strv.h" - -@@ -32,6 +35,8 @@ int name_to_handle_at_loop( - _cleanup_free_ struct file_handle *h = NULL; - size_t n = ORIGINAL_MAX_HANDLE_SZ; - -+ assert((flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH)) == 0); -+ - /* We need to invoke name_to_handle_at() in a loop, given that it might return EOVERFLOW when the specified - * buffer is too small. Note that in contrast to what the docs might suggest, MAX_HANDLE_SZ is only good as a - * start value, it is not an upper bound on the buffer size required. -@@ -86,13 +91,16 @@ int name_to_handle_at_loop( - } - } - --static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) { -+static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *ret_mnt_id) { - char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)]; - _cleanup_free_ char *fdinfo = NULL; - _cleanup_close_ int subfd = -1; - char *p; - int r; - -+ assert(ret_mnt_id); -+ assert((flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH)) == 0); -+ - if ((flags & AT_EMPTY_PATH) && isempty(filename)) - xsprintf(path, "/proc/self/fdinfo/%i", fd); - else { -@@ -121,41 +129,49 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id - p += strspn(p, WHITESPACE); - p[strcspn(p, WHITESPACE)] = 0; - -- return safe_atoi(p, mnt_id); -+ return safe_atoi(p, ret_mnt_id); - } - - int fd_is_mount_point(int fd, const char *filename, int flags) { - _cleanup_free_ struct file_handle *h = NULL, *h_parent = NULL; - int mount_id = -1, mount_id_parent = -1; - bool nosupp = false, check_st_dev = true; -+ STRUCT_STATX_DEFINE(sx); - struct stat a, b; - int r; - - assert(fd >= 0); - assert(filename); -+ assert((flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH)) == 0); - -- /* First we will try the name_to_handle_at() syscall, which -- * tells us the mount id and an opaque file "handle". It is -- * not supported everywhere though (kernel compile-time -- * option, not all file systems are hooked up). If it works -- * the mount id is usually good enough to tell us whether -- * something is a mount point. -+ /* First we will try statx()' STATX_ATTR_MOUNT_ROOT attribute, which is our ideal API, available -+ * since kernel 5.8. -+ * -+ * If that fails, our second try is the name_to_handle_at() syscall, which tells us the mount id and -+ * an opaque file "handle". It is not supported everywhere though (kernel compile-time option, not -+ * all file systems are hooked up). If it works the mount id is usually good enough to tell us -+ * whether something is a mount point. - * -- * If that didn't work we will try to read the mount id from -- * /proc/self/fdinfo/. This is almost as good as -- * name_to_handle_at(), however, does not return the -- * opaque file handle. The opaque file handle is pretty useful -- * to detect the root directory, which we should always -- * consider a mount point. Hence we use this only as -- * fallback. Exporting the mnt_id in fdinfo is a pretty recent -+ * If that didn't work we will try to read the mount id from /proc/self/fdinfo/. This is almost -+ * as good as name_to_handle_at(), however, does not return the opaque file handle. The opaque file -+ * handle is pretty useful to detect the root directory, which we should always consider a mount -+ * point. Hence we use this only as fallback. Exporting the mnt_id in fdinfo is a pretty recent - * kernel addition. - * -- * As last fallback we do traditional fstat() based st_dev -- * comparisons. This is how things were traditionally done, -- * but unionfs breaks this since it exposes file -- * systems with a variety of st_dev reported. Also, btrfs -- * subvolumes have different st_dev, even though they aren't -- * real mounts of their own. */ -+ * As last fallback we do traditional fstat() based st_dev comparisons. This is how things were -+ * traditionally done, but unionfs breaks this since it exposes file systems with a variety of st_dev -+ * reported. Also, btrfs subvolumes have different st_dev, even though they aren't real mounts of -+ * their own. */ -+ -+ if (statx(fd, filename, (FLAGS_SET(flags, AT_SYMLINK_FOLLOW) ? 0 : AT_SYMLINK_NOFOLLOW) | -+ (flags & AT_EMPTY_PATH) | -+ AT_NO_AUTOMOUNT, 0, &sx) < 0) { -+ if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) -+ return -errno; -+ -+ /* If statx() is not available or forbidden, fall back to name_to_handle_at() below */ -+ } else if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) /* yay! */ -+ return FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT); - - r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags); - if (IN_SET(r, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) -@@ -166,7 +182,7 @@ int fd_is_mount_point(int fd, const char *filename, int flags) { - goto fallback_fdinfo; - else if (r == -EOPNOTSUPP) - /* This kernel or file system does not support name_to_handle_at(), hence let's see if the upper fs -- * supports it (in which case it is a mount point), otherwise fallback to the traditional stat() -+ * supports it (in which case it is a mount point), otherwise fall back to the traditional stat() - * logic */ - nosupp = true; - else if (r < 0) -@@ -278,8 +294,21 @@ int path_is_mount_point(const char *t, const char *root, int flags) { - } - - int path_get_mnt_id(const char *path, int *ret) { -+ STRUCT_NEW_STATX_DEFINE(buf); - int r; - -+ if (statx(AT_FDCWD, path, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_MNT_ID, &buf.sx) < 0) { -+ if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) -+ return -errno; -+ -+ /* Fall back to name_to_handle_at() and then fdinfo if statx is not supported or we lack -+ * privileges */ -+ -+ } else if (FLAGS_SET(buf.nsx.stx_mask, STATX_MNT_ID)) { -+ *ret = buf.nsx.stx_mnt_id; -+ return 0; -+ } -+ - r = name_to_handle_at_loop(AT_FDCWD, path, NULL, ret, 0); - if (IN_SET(r, -EOPNOTSUPP, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) /* kernel/fs don't support this, or seccomp blocks access, or untriggered mount, or name_to_handle_at() is flaky */ - return fd_fdinfo_mnt_id(AT_FDCWD, path, 0, ret); -diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c -index 7fdb47e..8309843 100644 ---- a/src/basic/ordered-set.c -+++ b/src/basic/ordered-set.c -@@ -4,6 +4,27 @@ - #include "ordered-set.h" - #include "strv.h" - -+int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) { -+ if (*s) -+ return 0; -+ -+ *s = _ordered_set_new(ops HASHMAP_DEBUG_PASS_ARGS); -+ if (!*s) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS) { -+ int r; -+ -+ r = _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_PASS_ARGS); -+ if (r < 0) -+ return r; -+ -+ return ordered_set_put(*s, p); -+} -+ - int ordered_set_consume(OrderedSet *s, void *p) { - int r; - -@@ -49,12 +70,11 @@ int ordered_set_put_strdupv(OrderedSet *s, char **l) { - - int ordered_set_put_string_set(OrderedSet *s, OrderedSet *l) { - int n = 0, r; -- Iterator i; - char *p; - - /* Like ordered_set_put_strv, but for an OrderedSet of strings */ - -- ORDERED_SET_FOREACH(p, l, i) { -+ ORDERED_SET_FOREACH(p, l) { - r = ordered_set_put_strdup(s, p); - if (r < 0) - return r; -@@ -67,7 +87,6 @@ int ordered_set_put_string_set(OrderedSet *s, OrderedSet *l) { - - void ordered_set_print(FILE *f, const char *field, OrderedSet *s) { - bool space = false; -- Iterator i; - char *p; - - if (ordered_set_isempty(s)) -@@ -75,7 +94,7 @@ void ordered_set_print(FILE *f, const char *field, OrderedSet *s) { - - fputs(field, f); - -- ORDERED_SET_FOREACH(p, s, i) -+ ORDERED_SET_FOREACH(p, s) - fputs_with_space(f, p, NULL, &space); - - fputc('\n', f); -diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h -index a42a57e..c942aaf 100644 ---- a/src/basic/ordered-set.h -+++ b/src/basic/ordered-set.h -@@ -7,20 +7,16 @@ - - typedef struct OrderedSet OrderedSet; - --static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) { -- return (OrderedSet*) ordered_hashmap_new(ops); -+static inline OrderedSet* _ordered_set_new(const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) { -+ return (OrderedSet*) _ordered_hashmap_new(ops HASHMAP_DEBUG_PASS_ARGS); - } -+#define ordered_set_new(ops) _ordered_set_new(ops HASHMAP_DEBUG_SRC_ARGS) - --static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) { -- if (*s) -- return 0; -+int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS); -+#define ordered_set_ensure_allocated(s, ops) _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_SRC_ARGS) - -- *s = ordered_set_new(ops); -- if (!*s) -- return -ENOMEM; -- -- return 0; --} -+int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS); -+#define ordered_set_ensure_put(s, hash_ops, key) _ordered_set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS) - - static inline OrderedSet* ordered_set_free(OrderedSet *s) { - return (OrderedSet*) ordered_hashmap_free((OrderedHashmap*) s); -@@ -58,7 +54,7 @@ static inline void* ordered_set_steal_first(OrderedSet *s) { - return ordered_hashmap_steal_first((OrderedHashmap*) s); - } - --static inline char **ordered_set_get_strv(OrderedSet *s) { -+static inline char** ordered_set_get_strv(OrderedSet *s) { - return _hashmap_get_strv(HASHMAP_BASE((OrderedHashmap*) s)); - } - -@@ -68,8 +64,10 @@ int ordered_set_put_strdupv(OrderedSet *s, char **l); - int ordered_set_put_string_set(OrderedSet *s, OrderedSet *l); - void ordered_set_print(FILE *f, const char *field, OrderedSet *s); - --#define ORDERED_SET_FOREACH(e, s, i) \ -- for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); ) -+#define _ORDERED_SET_FOREACH(e, s, i) \ -+ for (Iterator i = ITERATOR_FIRST; ordered_set_iterate((s), &i, (void**)&(e)); ) -+#define ORDERED_SET_FOREACH(e, s) \ -+ _ORDERED_SET_FOREACH(e, s, UNIQ_T(i, UNIQ)) - - DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free); - DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free); -diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c -index 44f0438..818c905 100644 ---- a/src/basic/parse-util.c -+++ b/src/basic/parse-util.c -@@ -16,6 +16,9 @@ - #include "missing_network.h" - #include "parse-util.h" - #include "process-util.h" -+#if HAVE_SECCOMP -+#include "seccomp-util.h" -+#endif - #include "stat-util.h" - #include "string-util.h" - #include "strv.h" -@@ -314,6 +317,7 @@ int parse_errno(const char *t) { - return e; - } - -+#if HAVE_SECCOMP - int parse_syscall_and_errno(const char *in, char **name, int *error) { - _cleanup_free_ char *n = NULL; - char *p; -@@ -332,7 +336,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) { - - p = strchr(in, ':'); - if (p) { -- e = parse_errno(p + 1); -+ e = seccomp_parse_errno_or_action(p + 1); - if (e < 0) - return e; - -@@ -351,6 +355,7 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) { - - return 0; - } -+#endif - - static const char *mangle_base(const char *s, unsigned *base) { - const char *k; -diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h -index 9a516ce..2cee65c 100644 ---- a/src/basic/parse-util.h -+++ b/src/basic/parse-util.h -@@ -19,7 +19,9 @@ int parse_mtu(int family, const char *s, uint32_t *ret); - int parse_size(const char *t, uint64_t base, uint64_t *size); - int parse_range(const char *t, unsigned *lower, unsigned *upper); - int parse_errno(const char *t); -+#if HAVE_SECCOMP - int parse_syscall_and_errno(const char *in, char **name, int *error); -+#endif - - #define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30) - #define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29) -diff --git a/src/basic/path-lookup.c b/src/basic/path-lookup.c -index 52968de..3ea851c 100644 ---- a/src/basic/path-lookup.c -+++ b/src/basic/path-lookup.c -@@ -27,7 +27,7 @@ int xdg_user_runtime_dir(char **ret, const char *suffix) { - if (!e) - return -ENXIO; - -- j = strjoin(e, suffix); -+ j = path_join(e, suffix); - if (!j) - return -ENOMEM; - -@@ -44,7 +44,7 @@ int xdg_user_config_dir(char **ret, const char *suffix) { - - e = getenv("XDG_CONFIG_HOME"); - if (e) -- j = strjoin(e, suffix); -+ j = path_join(e, suffix); - else { - _cleanup_free_ char *home = NULL; - -@@ -52,7 +52,7 @@ int xdg_user_config_dir(char **ret, const char *suffix) { - if (r < 0) - return r; - -- j = strjoin(home, "/.config", suffix); -+ j = path_join(home, "/.config", suffix); - } - - if (!j) -@@ -76,7 +76,7 @@ int xdg_user_data_dir(char **ret, const char *suffix) { - - e = getenv("XDG_DATA_HOME"); - if (e) -- j = strjoin(e, suffix); -+ j = path_join(e, suffix); - else { - _cleanup_free_ char *home = NULL; - -@@ -84,7 +84,7 @@ int xdg_user_data_dir(char **ret, const char *suffix) { - if (r < 0) - return r; - -- j = strjoin(home, "/.local/share", suffix); -+ j = path_join(home, "/.local/share", suffix); - } - if (!j) - return -ENOMEM; -diff --git a/src/basic/path-lookup.h b/src/basic/path-lookup.h -index ae37f9f..ee3d810 100644 ---- a/src/basic/path-lookup.h -+++ b/src/basic/path-lookup.h -@@ -21,7 +21,7 @@ struct LookupPaths { - char **search_path; - - /* Where we shall create or remove our installation symlinks, aka "configuration", and where the user/admin -- * shall place his own unit files. */ -+ * shall place their own unit files. */ - char *persistent_config; - char *runtime_config; - -diff --git a/src/basic/path-util.c b/src/basic/path-util.c -index c4e022b..9e44f2e 100644 ---- a/src/basic/path-util.c -+++ b/src/basic/path-util.c -@@ -14,6 +14,7 @@ - - #include "alloc-util.h" - #include "extract-word.h" -+#include "fd-util.h" - #include "fs-util.h" - #include "glob-util.h" - #include "log.h" -@@ -638,12 +639,26 @@ int find_binary(const char *name, char **ret) { - return -ENOMEM; - - if (access(j, X_OK) >= 0) { -- /* Found it! */ -+ _cleanup_free_ char *with_dash; - -- if (ret) -- *ret = path_simplify(TAKE_PTR(j), false); -+ with_dash = strjoin(j, "/"); -+ if (!with_dash) -+ return -ENOMEM; - -- return 0; -+ /* If this passes, it must be a directory, and so should be skipped. */ -+ if (access(with_dash, X_OK) >= 0) -+ continue; -+ -+ /** -+ * We can't just `continue` inverting this case, since we need to update last_error. -+ */ -+ if (errno == ENOTDIR) { -+ /* Found it! */ -+ if (ret) -+ *ret = path_simplify(TAKE_PTR(j), false); -+ -+ return 0; -+ } - } - - /* PATH entries which we don't have access to are ignored, as per tradition. */ -@@ -726,18 +741,6 @@ int fsck_exists(const char *fstype) { - return binary_is_good(checker); - } - --int mkfs_exists(const char *fstype) { -- const char *mkfs; -- -- assert(fstype); -- -- if (streq(fstype, "auto")) -- return -EINVAL; -- -- mkfs = strjoina("mkfs.", fstype); -- return binary_is_good(mkfs); --} -- - int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) { - char *p; - int r; -@@ -1139,3 +1142,9 @@ bool prefixed_path_strv_contains(char **l, const char *path) { - - return false; - } -+ -+bool credential_name_valid(const char *s) { -+ /* We want that credential names are both valid in filenames (since that's our primary way to pass -+ * them around) and as fdnames (which is how we might want to pass them around eventually) */ -+ return filename_is_valid(s) && fdname_is_valid(s); -+} -diff --git a/src/basic/path-util.h b/src/basic/path-util.h -index 30031fc..1afbebd 100644 ---- a/src/basic/path-util.h -+++ b/src/basic/path-util.h -@@ -85,7 +85,6 @@ int find_binary(const char *name, char **filename); - bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update); - - int fsck_exists(const char *fstype); --int mkfs_exists(const char *fstype); - - /* Iterates through the path prefixes of the specified path, going up - * the tree, to root. Also returns "" (and not "/"!) for the root -@@ -174,3 +173,5 @@ static inline const char *empty_to_root(const char *path) { - - bool path_strv_contains(char **l, const char *path); - bool prefixed_path_strv_contains(char **l, const char *path); -+ -+bool credential_name_valid(const char *s); -diff --git a/src/basic/procfs-util.c b/src/basic/procfs-util.c -index 7aaf95b..38f9fa1 100644 ---- a/src/basic/procfs-util.c -+++ b/src/basic/procfs-util.c -@@ -65,7 +65,7 @@ int procfs_tasks_set_limit(uint64_t limit) { - - if (limit == 0) /* This makes no sense, we are userspace and hence count as tasks too, and we want to live, - * hence the limit conceptually has to be above 0. Also, most likely if anyone asks for a zero -- * limit he/she probably means "no limit", hence let's better refuse this to avoid -+ * limit they probably mean "no limit", hence let's better refuse this to avoid - * confusion. */ - return -EINVAL; - -diff --git a/src/basic/quota-util.c b/src/basic/quota-util.c -index e048f55..96ea9ee 100644 ---- a/src/basic/quota-util.c -+++ b/src/basic/quota-util.c -@@ -34,7 +34,7 @@ int quotactl_path(int cmd, const char *path, int id, void *addr) { - r = get_block_device(path, &devno); - if (r < 0) - return r; -- if (devno == 0) -+ if (devno == 0) /* Doesn't have a block device */ - return -ENODEV; - - return quotactl_devno(cmd, devno, id, addr); -diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c -index 23cdfa4..01ff6bb 100644 ---- a/src/basic/rm-rf.c -+++ b/src/basic/rm-rf.c -@@ -23,6 +23,46 @@ static bool is_physical_fs(const struct statfs *sfs) { - return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs); - } - -+static int unlinkat_harder( -+ int dfd, -+ const char *filename, -+ int unlink_flags, -+ RemoveFlags remove_flags) { -+ -+ struct stat st; -+ int r; -+ -+ /* Like unlinkat(), but tries harder: if we get EACCESS we'll try to set the r/w/x bits on the -+ * directory. This is useful if we run unprivileged and have some files where the w bit is -+ * missing. */ -+ -+ if (unlinkat(dfd, filename, unlink_flags) >= 0) -+ return 0; -+ if (errno != EACCES || !FLAGS_SET(remove_flags, REMOVE_CHMOD)) -+ return -errno; -+ -+ if (fstat(dfd, &st) < 0) -+ return -errno; -+ if (!S_ISDIR(st.st_mode)) -+ return -ENOTDIR; -+ if ((st.st_mode & 0700) == 0700) /* Already set? */ -+ return -EACCES; /* original error */ -+ if (st.st_uid != geteuid()) /* this only works if the UID matches ours */ -+ return -EACCES; -+ -+ if (fchmod(dfd, (st.st_mode | 0700) & 07777) < 0) -+ return -errno; -+ -+ if (unlinkat(dfd, filename, unlink_flags) < 0) { -+ r = -errno; -+ /* Try to restore the original access mode if this didn't work */ -+ (void) fchmod(dfd, st.st_mode & 07777); -+ return r; -+ } -+ -+ return 0; -+} -+ - int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { - _cleanup_closedir_ DIR *d = NULL; - struct dirent *de; -@@ -132,17 +172,15 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { - if (r < 0 && ret == 0) - ret = r; - -- if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) { -- if (ret == 0 && errno != ENOENT) -- ret = -errno; -- } -+ r = unlinkat_harder(fd, de->d_name, AT_REMOVEDIR, flags); -+ if (r < 0 && r != -ENOENT && ret == 0) -+ ret = r; - - } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { - -- if (unlinkat(fd, de->d_name, 0) < 0) { -- if (ret == 0 && errno != ENOENT) -- ret = -errno; -- } -+ r = unlinkat_harder(fd, de->d_name, 0, flags); -+ if (r < 0 && r != -ENOENT && ret == 0) -+ ret = r; - } - } - return ret; -diff --git a/src/basic/rm-rf.h b/src/basic/rm-rf.h -index 40cbff2..0edf01e 100644 ---- a/src/basic/rm-rf.h -+++ b/src/basic/rm-rf.h -@@ -11,6 +11,7 @@ typedef enum RemoveFlags { - REMOVE_PHYSICAL = 1 << 2, /* If not set, only removes files on tmpfs, never physical file systems */ - REMOVE_SUBVOLUME = 1 << 3, /* Drop btrfs subvolumes in the tree too */ - REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */ -+ REMOVE_CHMOD = 1 << 5, /* chmod() for write access if we cannot delete something */ - } RemoveFlags; - - int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev); -diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c -index c94ee26..9b3b15d 100644 ---- a/src/basic/selinux-util.c -+++ b/src/basic/selinux-util.c -@@ -35,14 +35,17 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free); - static int mac_selinux_reload(int seqno); - - static int cached_use = -1; -+static bool initialized = false; -+static int (*enforcing_status_func)(void) = security_getenforce; -+static int last_policyload = 0; - static struct selabel_handle *label_hnd = NULL; - - #define log_enforcing(...) \ -- log_full(security_getenforce() != 0 ? LOG_ERR : LOG_WARNING, __VA_ARGS__) -+ log_full(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, __VA_ARGS__) - - #define log_enforcing_errno(error, ...) \ - ({ \ -- bool _enforcing = security_getenforce() != 0; \ -+ bool _enforcing = mac_selinux_enforcing(); \ - int _level = _enforcing ? LOG_ERR : LOG_WARNING; \ - int _e = (error); \ - \ -@@ -66,32 +69,33 @@ bool mac_selinux_use(void) { - #endif - } - -+bool mac_selinux_enforcing(void) { -+#if HAVE_SELINUX -+ return enforcing_status_func() != 0; -+#else -+ return false; -+#endif -+} -+ - void mac_selinux_retest(void) { - #if HAVE_SELINUX - cached_use = -1; - #endif - } - --int mac_selinux_init(void) { - #if HAVE_SELINUX -+static int open_label_db(void) { -+ struct selabel_handle *hnd; - usec_t before_timestamp, after_timestamp; - struct mallinfo before_mallinfo, after_mallinfo; - char timespan[FORMAT_TIMESPAN_MAX]; - int l; - -- selinux_set_callback(SELINUX_CB_POLICYLOAD, (union selinux_callback) mac_selinux_reload); -- -- if (label_hnd) -- return 0; -- -- if (!mac_selinux_use()) -- return 0; -- - before_mallinfo = mallinfo(); - before_timestamp = now(CLOCK_MONOTONIC); - -- label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); -- if (!label_hnd) -+ hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); -+ if (!hnd) - return log_enforcing_errno(errno, "Failed to initialize SELinux labeling handle: %m"); - - after_timestamp = now(CLOCK_MONOTONIC); -@@ -103,37 +107,97 @@ int mac_selinux_init(void) { - format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0), - (l+1023)/1024); - --#endif -+ /* release memory after measurement */ -+ if (label_hnd) -+ selabel_close(label_hnd); -+ label_hnd = TAKE_PTR(hnd); -+ - return 0; - } -+#endif - --void mac_selinux_finish(void) { -+int mac_selinux_init(void) { -+#if HAVE_SELINUX -+ int r; -+ -+ if (initialized) -+ return 0; -+ -+ if (!mac_selinux_use()) -+ return 0; -+ -+ r = selinux_status_open(/* no netlink fallback */ 0); -+ if (r < 0) -+ return log_enforcing_errno(errno, "Failed to open SELinux status page: %m"); - -+ r = open_label_db(); -+ if (r < 0) { -+ selinux_status_close(); -+ return r; -+ } -+ -+ /* save the current policyload sequence number, so `mac_selinux_maybe_reload()` does -+ not trigger on first call without any actual change */ -+ last_policyload = selinux_status_policyload(); -+ -+ /* now that the SELinux status page has been successfully opened, -+ retrieve the enforcing status over it (to avoid system calls in `security_getenforce()`) */ -+ enforcing_status_func = selinux_status_getenforce; -+ -+ initialized = true; -+#endif -+ return 0; -+} -+ -+void mac_selinux_maybe_reload(void) { - #if HAVE_SELINUX -- if (!label_hnd) -+ int r; -+ -+ if (!initialized) - return; - -- selabel_close(label_hnd); -- label_hnd = NULL; -+ r = selinux_status_updated(); -+ if (r < 0) -+ log_debug_errno(errno, "Failed to update SELinux from status page: %m"); -+ if (r > 0) { -+ int policyload; -+ -+ log_debug("SELinux status page update"); -+ -+ /* from libselinux > 3.1 callbacks gets automatically called, see -+ https://github.com/SELinuxProject/selinux/commit/05bdc03130d741e53e1fb45a958d0a2c184be503 */ -+ -+ /* only reload on policy changes, not enforcing status changes */ -+ policyload = selinux_status_policyload(); -+ if (policyload != last_policyload) { -+ mac_selinux_reload(policyload); -+ last_policyload = policyload; -+ } -+ } - #endif - } - -+void mac_selinux_finish(void) { -+ - #if HAVE_SELINUX --static int mac_selinux_reload(int seqno) { -- struct selabel_handle *backup_label_hnd; -+ if (label_hnd) { -+ selabel_close(label_hnd); -+ label_hnd = NULL; -+ } - -- if (!label_hnd) -- return 0; -+ enforcing_status_func = security_getenforce; -+ -+ selinux_status_close(); - -- backup_label_hnd = TAKE_PTR(label_hnd); -+ initialized = false; -+#endif -+} -+ -+#if HAVE_SELINUX -+static int mac_selinux_reload(int seqno) { -+ log_debug("SELinux reload %d", seqno); - -- /* try to initialize new handle -- * on success close backup -- * on failure restore backup */ -- if (mac_selinux_init() == 0) -- selabel_close(backup_label_hnd); -- else -- label_hnd = backup_label_hnd; -+ (void) open_label_db(); - - return 0; - } -@@ -167,7 +231,7 @@ int mac_selinux_fix_container(const char *path, const char *inside_path, LabelFi - return -errno; - - /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */ -- (void) avc_netlink_check_nb(); -+ mac_selinux_maybe_reload(); - - if (selabel_lookup_raw(label_hnd, &fcon, inside_path, st.st_mode) < 0) { - r = -errno; -@@ -363,7 +427,7 @@ static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode) - assert(path_is_absolute(abspath)); - - /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */ -- (void) avc_netlink_check_nb(); -+ mac_selinux_maybe_reload(); - - r = selabel_lookup_raw(label_hnd, &filecon, abspath, mode); - if (r < 0) { -@@ -507,7 +571,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { - path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path)); - - /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */ -- (void) avc_netlink_check_nb(); -+ mac_selinux_maybe_reload(); - - if (path_is_absolute(path)) - r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK); -diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h -index d053b00..a982289 100644 ---- a/src/basic/selinux-util.h -+++ b/src/basic/selinux-util.h -@@ -17,8 +17,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon); - - bool mac_selinux_use(void); - void mac_selinux_retest(void); -+bool mac_selinux_enforcing(void); - - int mac_selinux_init(void); -+void mac_selinux_maybe_reload(void); - void mac_selinux_finish(void); - - int mac_selinux_fix_container(const char *path, const char *inside_path, LabelFixFlags flags); -diff --git a/src/basic/set.h b/src/basic/set.h -index e4fc1e3..7170eea 100644 ---- a/src/basic/set.h -+++ b/src/basic/set.h -@@ -13,14 +13,14 @@ - 0; \ - }) - --Set *_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); -+Set* _set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); - #define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS) - --static inline Set *set_free(Set *s) { -+static inline Set* set_free(Set *s) { - return (Set*) _hashmap_free(HASHMAP_BASE(s), NULL, NULL); - } - --static inline Set *set_free_free(Set *s) { -+static inline Set* set_free_free(Set *s) { - return (Set*) _hashmap_free(HASHMAP_BASE(s), free, NULL); - } - -@@ -34,7 +34,7 @@ int _set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG - int set_put(Set *s, const void *key); - /* no set_update */ - /* no set_replace */ --static inline void *set_get(const Set *s, void *key) { -+static inline void *set_get(const Set *s, const void *key) { - return _hashmap_get(HASHMAP_BASE((Set *) s), key); - } - /* no set_get2 */ -@@ -77,7 +77,9 @@ static inline unsigned set_buckets(const Set *s) { - return _hashmap_buckets(HASHMAP_BASE((Set *) s)); - } - --bool set_iterate(const Set *s, Iterator *i, void **value); -+static inline bool set_iterate(const Set *s, Iterator *i, void **value) { -+ return _hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL); -+} - - static inline void set_clear(Set *s) { - _hashmap_clear(HASHMAP_BASE(s), NULL, NULL); -@@ -133,8 +135,10 @@ int _set_put_strdupv(Set **s, char **l HASHMAP_DEBUG_PARAMS); - - int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags); - --#define SET_FOREACH(e, s, i) \ -- for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); ) -+#define _SET_FOREACH(e, s, i) \ -+ for (Iterator i = ITERATOR_FIRST; set_iterate((s), &i, (void**)&(e)); ) -+#define SET_FOREACH(e, s) \ -+ _SET_FOREACH(e, s, UNIQ_T(i, UNIQ)) - - #define SET_FOREACH_MOVE(e, d, s) \ - for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); ) -diff --git a/src/basic/siphash24.h b/src/basic/siphash24.h -index 7f799ed..fe43256 100644 ---- a/src/basic/siphash24.h -+++ b/src/basic/siphash24.h -@@ -6,6 +6,8 @@ - #include - #include - -+#include "time-util.h" -+ - struct siphash { - uint64_t v0; - uint64_t v1; -@@ -25,6 +27,10 @@ static inline void siphash24_compress_boolean(bool in, struct siphash *state) { - siphash24_compress(&i, sizeof i, state); - } - -+static inline void siphash24_compress_usec_t(usec_t in, struct siphash *state) { -+ siphash24_compress(&in, sizeof in, state); -+} -+ - static inline void siphash24_compress_string(const char *in, struct siphash *state) { - if (!in) - return; -diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c -index 8043a97..7bb0746 100644 ---- a/src/basic/smack-util.c -+++ b/src/basic/smack-util.c -@@ -106,7 +106,7 @@ int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { - - int mac_smack_apply_pid(pid_t pid, const char *label) { - const char *p; -- int r = 0; -+ int r; - - assert(label); - -@@ -232,7 +232,7 @@ int mac_smack_fix_container(const char *path, const char *inside_path, LabelFixF - } - - int mac_smack_copy(const char *dest, const char *src) { -- int r = 0; -+ int r; - _cleanup_free_ char *label = NULL; - - assert(dest); -diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c -index ec52d81..dd69eaa 100644 ---- a/src/basic/socket-label.c -+++ b/src/basic/socket-label.c -@@ -80,15 +80,15 @@ int socket_address_listen( - } - - if (free_bind) { -- r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true); -+ r = socket_set_freebind(fd, socket_address_family(a), true); - if (r < 0) -- log_warning_errno(r, "IP_FREEBIND failed: %m"); -+ log_warning_errno(r, "IP_FREEBIND/IPV6_FREEBIND failed: %m"); - } - - if (transparent) { -- r = setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, true); -+ r = socket_set_transparent(fd, socket_address_family(a), true); - if (r < 0) -- log_warning_errno(r, "IP_TRANSPARENT failed: %m"); -+ log_warning_errno(r, "IP_TRANSPARENT/IPV6_TRANSPARENT failed: %m"); - } - } - -diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c -index fb12659..f2e1148 100644 ---- a/src/basic/socket-util.c -+++ b/src/basic/socket-util.c -@@ -26,6 +26,7 @@ - #include "macro.h" - #include "memory-util.h" - #include "missing_socket.h" -+#include "missing_network.h" - #include "parse-util.h" - #include "path-util.h" - #include "process-util.h" -@@ -68,7 +69,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { - if (a->sockaddr.in.sin_port == 0) - return -EINVAL; - -- if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) -+ if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM)) - return -EINVAL; - - return 0; -@@ -80,7 +81,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { - if (a->sockaddr.in6.sin6_port == 0) - return -EINVAL; - -- if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) -+ if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM)) - return -EINVAL; - - return 0; -@@ -114,7 +115,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { - } - } - -- if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET)) -+ if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET)) - return -EINVAL; - - return 0; -@@ -124,7 +125,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { - if (a->size != sizeof(struct sockaddr_nl)) - return -EINVAL; - -- if (!IN_SET(a->type, SOCK_RAW, SOCK_DGRAM)) -+ if (!IN_SET(a->type, 0, SOCK_RAW, SOCK_DGRAM)) - return -EINVAL; - - return 0; -@@ -133,7 +134,7 @@ int socket_address_verify(const SocketAddress *a, bool strict) { - if (a->size != sizeof(struct sockaddr_vm)) - return -EINVAL; - -- if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) -+ if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM)) - return -EINVAL; - - return 0; -@@ -399,19 +400,23 @@ int sockaddr_pretty( - if (r < 0) - return -ENOMEM; - } else { -- char a[INET6_ADDRSTRLEN]; -+ char a[INET6_ADDRSTRLEN], ifname[IF_NAMESIZE + 1]; - - inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)); -+ if (sa->in6.sin6_scope_id != 0) -+ format_ifname_full(sa->in6.sin6_scope_id, ifname, FORMAT_IFNAME_IFINDEX); - - if (include_port) { - r = asprintf(&p, -- "[%s]:%u", -+ "[%s]:%u%s%s", - a, -- be16toh(sa->in6.sin6_port)); -+ be16toh(sa->in6.sin6_port), -+ sa->in6.sin6_scope_id != 0 ? "%" : "", -+ sa->in6.sin6_scope_id != 0 ? ifname : ""); - if (r < 0) - return -ENOMEM; - } else { -- p = strdup(a); -+ p = sa->in6.sin6_scope_id != 0 ? strjoin(a, "%", ifname) : strdup(a); - if (!p) - return -ENOMEM; - } -@@ -617,40 +622,64 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b - return false; - } - --int fd_inc_sndbuf(int fd, size_t n) { -+int fd_set_sndbuf(int fd, size_t n, bool increase) { - int r, value; - socklen_t l = sizeof(value); - -+ if (n > INT_MAX) -+ return -ERANGE; -+ - r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); -- if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) -+ if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) - return 0; - -- /* If we have the privileges we will ignore the kernel limit. */ -+ /* First, try to set the buffer size with SO_SNDBUF. */ -+ r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n); -+ if (r < 0) -+ return r; - -- if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) { -- r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n); -- if (r < 0) -- return r; -- } -+ /* SO_SNDBUF above may set to the kernel limit, instead of the requested size. -+ * So, we need to check the actual buffer size here. */ -+ l = sizeof(value); -+ r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); -+ if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) -+ return 1; -+ -+ /* If we have the privileges we will ignore the kernel limit. */ -+ r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n); -+ if (r < 0) -+ return r; - - return 1; - } - --int fd_inc_rcvbuf(int fd, size_t n) { -+int fd_set_rcvbuf(int fd, size_t n, bool increase) { - int r, value; - socklen_t l = sizeof(value); - -+ if (n > INT_MAX) -+ return -ERANGE; -+ - r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); -- if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) -+ if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) - return 0; - -- /* If we have the privileges we will ignore the kernel limit. */ -+ /* First, try to set the buffer size with SO_RCVBUF. */ -+ r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n); -+ if (r < 0) -+ return r; - -- if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) { -- r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n); -- if (r < 0) -- return r; -- } -+ /* SO_RCVBUF above may set to the kernel limit, instead of the requested size. -+ * So, we need to check the actual buffer size here. */ -+ l = sizeof(value); -+ r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); -+ if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2) -+ return 1; -+ -+ /* If we have the privileges we will ignore the kernel limit. */ -+ r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n); -+ if (r < 0) -+ return r; - - return 1; - } -@@ -664,17 +693,19 @@ static const char* const ip_tos_table[] = { - - DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); - --bool ifname_valid_full(const char *p, bool alternative) { -+bool ifname_valid_full(const char *p, IfnameValidFlags flags) { - bool numeric = true; - - /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources - * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We - * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */ - -+ assert(!(flags & ~_IFNAME_VALID_ALL)); -+ - if (isempty(p)) - return false; - -- if (alternative) { -+ if (flags & IFNAME_VALID_ALTERNATIVE) { - if (strlen(p) >= ALTIFNAMSIZ) - return false; - } else { -@@ -685,22 +716,27 @@ bool ifname_valid_full(const char *p, bool alternative) { - if (dot_or_dot_dot(p)) - return false; - -- while (*p) { -- if ((unsigned char) *p >= 127U) -+ for (const char *t = p; *t; t++) { -+ if ((unsigned char) *t >= 127U) - return false; - -- if ((unsigned char) *p <= 32U) -+ if ((unsigned char) *t <= 32U) - return false; - -- if (IN_SET(*p, ':', '/')) -+ if (IN_SET(*t, ':', '/')) - return false; - -- numeric = numeric && (*p >= '0' && *p <= '9'); -- p++; -+ numeric = numeric && (*t >= '0' && *t <= '9'); - } - -- if (numeric) -- return false; -+ if (numeric) { -+ if (!(flags & IFNAME_VALID_NUMERIC)) -+ return false; -+ -+ /* Verify that the number is well-formatted and in range. */ -+ if (parse_ifindex(p) < 0) -+ return false; -+ } - - return true; - } -@@ -1085,12 +1121,10 @@ int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) { - * reference paths in the abstract namespace that include NUL bytes in the name. */ - - l = strlen(path); -- if (l == 0) -+ if (l < 2) - return -EINVAL; - if (!IN_SET(path[0], '/', '@')) - return -EINVAL; -- if (path[1] == 0) -- return -EINVAL; - - /* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than - * the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket -@@ -1173,13 +1207,28 @@ ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) { - return n; - } - --int socket_pass_pktinfo(int fd, bool b) { -+int socket_get_family(int fd, int *ret) { - int af; - socklen_t sl = sizeof(af); - - if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0) - return -errno; - -+ if (sl != sizeof(af)) -+ return -EINVAL; -+ -+ return af; -+} -+ -+int socket_set_recvpktinfo(int fd, int af, bool b) { -+ int r; -+ -+ if (af == AF_UNSPEC) { -+ r = socket_get_family(fd, &af); -+ if (r < 0) -+ return r; -+ } -+ - switch (af) { - - case AF_INET: -@@ -1195,3 +1244,142 @@ int socket_pass_pktinfo(int fd, bool b) { - return -EAFNOSUPPORT; - } - } -+ -+int socket_set_recverr(int fd, int af, bool b) { -+ int r; -+ -+ if (af == AF_UNSPEC) { -+ r = socket_get_family(fd, &af); -+ if (r < 0) -+ return r; -+ } -+ -+ switch (af) { -+ -+ case AF_INET: -+ return setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, b); -+ -+ case AF_INET6: -+ return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, b); -+ -+ default: -+ return -EAFNOSUPPORT; -+ } -+} -+ -+int socket_set_recvttl(int fd, int af, bool b) { -+ int r; -+ -+ if (af == AF_UNSPEC) { -+ r = socket_get_family(fd, &af); -+ if (r < 0) -+ return r; -+ } -+ -+ switch (af) { -+ -+ case AF_INET: -+ return setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, b); -+ -+ case AF_INET6: -+ return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, b); -+ -+ default: -+ return -EAFNOSUPPORT; -+ } -+} -+ -+int socket_set_ttl(int fd, int af, int ttl) { -+ int r; -+ -+ if (af == AF_UNSPEC) { -+ r = socket_get_family(fd, &af); -+ if (r < 0) -+ return r; -+ } -+ -+ switch (af) { -+ -+ case AF_INET: -+ return setsockopt_int(fd, IPPROTO_IP, IP_TTL, ttl); -+ -+ case AF_INET6: -+ return setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, ttl); -+ -+ default: -+ return -EAFNOSUPPORT; -+ } -+} -+ -+int socket_set_unicast_if(int fd, int af, int ifi) { -+ be32_t ifindex_be = htobe32(ifi); -+ int r; -+ -+ if (af == AF_UNSPEC) { -+ r = socket_get_family(fd, &af); -+ if (r < 0) -+ return r; -+ } -+ -+ switch (af) { -+ -+ case AF_INET: -+ if (setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)) < 0) -+ return -errno; -+ -+ return 0; -+ -+ case AF_INET6: -+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)) < 0) -+ return -errno; -+ -+ return 0; -+ -+ default: -+ return -EAFNOSUPPORT; -+ } -+} -+ -+int socket_set_freebind(int fd, int af, bool b) { -+ int r; -+ -+ if (af == AF_UNSPEC) { -+ r = socket_get_family(fd, &af); -+ if (r < 0) -+ return r; -+ } -+ -+ switch (af) { -+ -+ case AF_INET: -+ return setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, b); -+ -+ case AF_INET6: -+ return setsockopt_int(fd, IPPROTO_IPV6, IPV6_FREEBIND, b); -+ -+ default: -+ return -EAFNOSUPPORT; -+ } -+} -+ -+int socket_set_transparent(int fd, int af, bool b) { -+ int r; -+ -+ if (af == AF_UNSPEC) { -+ r = socket_get_family(fd, &af); -+ if (r < 0) -+ return r; -+ } -+ -+ switch (af) { -+ -+ case AF_INET: -+ return setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, b); -+ -+ case AF_INET6: -+ return setsockopt_int(fd, IPPROTO_IPV6, IPV6_TRANSPARENT, b); -+ -+ default: -+ return -EAFNOSUPPORT; -+ } -+} -diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h -index 9e02e39..c36f90f 100644 ---- a/src/basic/socket-util.h -+++ b/src/basic/socket-util.h -@@ -118,15 +118,26 @@ int netlink_family_from_string(const char *s) _pure_; - - bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b); - --int fd_inc_sndbuf(int fd, size_t n); --int fd_inc_rcvbuf(int fd, size_t n); -+int fd_set_sndbuf(int fd, size_t n, bool increase); -+static inline int fd_inc_sndbuf(int fd, size_t n) { -+ return fd_set_sndbuf(fd, n, true); -+} -+int fd_set_rcvbuf(int fd, size_t n, bool increase); -+static inline int fd_inc_rcvbuf(int fd, size_t n) { -+ return fd_set_rcvbuf(fd, n, true); -+} - - int ip_tos_to_string_alloc(int i, char **s); - int ip_tos_from_string(const char *s); - --bool ifname_valid_full(const char *p, bool alternative); -+typedef enum { -+ IFNAME_VALID_ALTERNATIVE = 1 << 0, -+ IFNAME_VALID_NUMERIC = 1 << 1, -+ _IFNAME_VALID_ALL = IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC, -+} IfnameValidFlags; -+bool ifname_valid_full(const char *p, IfnameValidFlags flags); - static inline bool ifname_valid(const char *p) { -- return ifname_valid_full(p, false); -+ return ifname_valid_full(p, 0); - } - bool address_label_valid(const char *p); - -@@ -205,6 +216,35 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng - strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \ - }) - -+#define SOCKADDR_LEN(sa) \ -+ ({ \ -+ const union sockaddr_union *__sa = &(sa); \ -+ size_t _len; \ -+ switch(__sa->sa.sa_family) { \ -+ case AF_INET: \ -+ _len = sizeof(struct sockaddr_in); \ -+ break; \ -+ case AF_INET6: \ -+ _len = sizeof(struct sockaddr_in6); \ -+ break; \ -+ case AF_UNIX: \ -+ _len = SOCKADDR_UN_LEN(__sa->un); \ -+ break; \ -+ case AF_PACKET: \ -+ _len = SOCKADDR_LL_LEN(__sa->ll); \ -+ break; \ -+ case AF_NETLINK: \ -+ _len = sizeof(struct sockaddr_nl); \ -+ break; \ -+ case AF_VSOCK: \ -+ _len = sizeof(struct sockaddr_vm); \ -+ break; \ -+ default: \ -+ assert_not_reached("invalid socket family"); \ -+ } \ -+ _len; \ -+ }) -+ - int socket_ioctl_fd(void); - - int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path); -@@ -221,4 +261,11 @@ int socket_bind_to_ifindex(int fd, int ifindex); - - ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags); - --int socket_pass_pktinfo(int fd, bool b); -+int socket_get_family(int fd, int *ret); -+int socket_set_recvpktinfo(int fd, int af, bool b); -+int socket_set_recverr(int fd, int af, bool b); -+int socket_set_recvttl(int fd, int af, bool b); -+int socket_set_ttl(int fd, int af, int ttl); -+int socket_set_unicast_if(int fd, int af, int ifi); -+int socket_set_freebind(int fd, int af, bool b); -+int socket_set_transparent(int fd, int af, bool b); -diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c -index 904584a..574815b 100644 ---- a/src/basic/stat-util.c -+++ b/src/basic/stat-util.c -@@ -15,6 +15,7 @@ - #include "macro.h" - #include "missing_fs.h" - #include "missing_magic.h" -+#include "missing_syscall.h" - #include "parse-util.h" - #include "stat-util.h" - #include "string-util.h" -@@ -413,3 +414,59 @@ bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { - a->st_ino == b->st_ino && - (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */ - } -+ -+int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx) { -+ static bool avoid_statx = false; -+ struct stat st; -+ -+ if (!avoid_statx) { -+ if (statx(dfd, path, flags, mask, sx) < 0) { -+ if (!ERRNO_IS_NOT_SUPPORTED(errno) && errno != EPERM) -+ return -errno; -+ -+ /* If statx() is not supported or if we see EPERM (which might indicate seccomp -+ * filtering or so), let's do a fallback. Not that on EACCES we'll not fall back, -+ * since that is likely an indication of fs access issues, which we should -+ * propagate */ -+ } else -+ return 0; -+ -+ avoid_statx = true; -+ } -+ -+ /* Only do fallback if fstatat() supports the flag too, or if it's one of the sync flags, which are -+ * OK to ignore */ -+ if ((flags & ~(AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW| -+ AT_STATX_SYNC_AS_STAT|AT_STATX_FORCE_SYNC|AT_STATX_DONT_SYNC)) != 0) -+ return -EOPNOTSUPP; -+ -+ if (fstatat(dfd, path, &st, flags & (AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW)) < 0) -+ return -errno; -+ -+ *sx = (struct statx) { -+ .stx_mask = STATX_TYPE|STATX_MODE| -+ STATX_NLINK|STATX_UID|STATX_GID| -+ STATX_ATIME|STATX_MTIME|STATX_CTIME| -+ STATX_INO|STATX_SIZE|STATX_BLOCKS, -+ .stx_blksize = st.st_blksize, -+ .stx_nlink = st.st_nlink, -+ .stx_uid = st.st_uid, -+ .stx_gid = st.st_gid, -+ .stx_mode = st.st_mode, -+ .stx_ino = st.st_ino, -+ .stx_size = st.st_size, -+ .stx_blocks = st.st_blocks, -+ .stx_rdev_major = major(st.st_rdev), -+ .stx_rdev_minor = minor(st.st_rdev), -+ .stx_dev_major = major(st.st_dev), -+ .stx_dev_minor = minor(st.st_dev), -+ .stx_atime.tv_sec = st.st_atim.tv_sec, -+ .stx_atime.tv_nsec = st.st_atim.tv_nsec, -+ .stx_mtime.tv_sec = st.st_mtim.tv_sec, -+ .stx_mtime.tv_nsec = st.st_mtim.tv_nsec, -+ .stx_ctime.tv_sec = st.st_ctim.tv_sec, -+ .stx_ctime.tv_nsec = st.st_ctim.tv_nsec, -+ }; -+ -+ return 0; -+} -diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h -index 59aedcb..26ecd63 100644 ---- a/src/basic/stat-util.h -+++ b/src/basic/stat-util.h -@@ -10,6 +10,7 @@ - #include - - #include "macro.h" -+#include "missing_stat.h" - - int is_symlink(const char *path); - int is_dir(const char *path, bool follow); -@@ -91,3 +92,24 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret - int proc_mounted(void); - - bool stat_inode_unmodified(const struct stat *a, const struct stat *b); -+ -+int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx); -+ -+#if HAS_FEATURE_MEMORY_SANITIZER -+# warning "Explicitly initializing struct statx, to work around msan limitation. Please remove as soon as msan has been updated to not require this." -+# define STRUCT_STATX_DEFINE(var) \ -+ struct statx var = {} -+# define STRUCT_NEW_STATX_DEFINE(var) \ -+ union { \ -+ struct statx sx; \ -+ struct new_statx nsx; \ -+ } var = {} -+#else -+# define STRUCT_STATX_DEFINE(var) \ -+ struct statx var -+# define STRUCT_NEW_STATX_DEFINE(var) \ -+ union { \ -+ struct statx sx; \ -+ struct new_statx nsx; \ -+ } var -+#endif -diff --git a/src/basic/string-util.c b/src/basic/string-util.c -index 755a37f..ab725d0 100644 ---- a/src/basic/string-util.c -+++ b/src/basic/string-util.c -@@ -8,12 +8,14 @@ - - #include "alloc-util.h" - #include "escape.h" -+#include "extract-word.h" - #include "fileio.h" - #include "gunicode.h" - #include "locale-util.h" - #include "macro.h" - #include "memory-util.h" - #include "string-util.h" -+#include "strv.h" - #include "terminal-util.h" - #include "utf8.h" - #include "util.h" -@@ -110,83 +112,6 @@ char* first_word(const char *s, const char *word) { - return (char*) p; - } - --static size_t strcspn_escaped(const char *s, const char *reject) { -- bool escaped = false; -- int n; -- -- for (n = 0; s[n] != '\0'; n++) { -- if (escaped) -- escaped = false; -- else if (s[n] == '\\') -- escaped = true; -- else if (strchr(reject, s[n])) -- break; -- } -- -- return n; --} -- --/* Split a string into words. */ --const char* split( -- const char **state, -- size_t *l, -- const char *separator, -- SplitFlags flags) { -- -- const char *current; -- -- assert(state); -- assert(l); -- -- if (!separator) -- separator = WHITESPACE; -- -- current = *state; -- -- if (*current == '\0') /* already at the end? */ -- return NULL; -- -- current += strspn(current, separator); /* skip leading separators */ -- if (*current == '\0') { /* at the end now? */ -- *state = current; -- return NULL; -- } -- -- if (FLAGS_SET(flags, SPLIT_QUOTES)) { -- -- if (strchr(QUOTES, *current)) { -- /* We are looking at a quote */ -- *l = strcspn_escaped(current + 1, CHAR_TO_STR(*current)); -- if (current[*l + 1] != *current || -- (current[*l + 2] != 0 && !strchr(separator, current[*l + 2]))) { -- /* right quote missing or garbage at the end */ -- if (FLAGS_SET(flags, SPLIT_RELAX)) { -- *state = current + *l + 1 + (current[*l + 1] != '\0'); -- return current + 1; -- } -- *state = current; -- return NULL; -- } -- *state = current++ + *l + 2; -- -- } else { -- /* We are looking at a something that is not a quote */ -- *l = strcspn_escaped(current, separator); -- if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) { -- /* unfinished escape */ -- *state = current; -- return NULL; -- } -- *state = current + *l; -- } -- } else { -- *l = strcspn(current, separator); -- *state = current + *l; -- } -- -- return current; --} -- - char *strnappend(const char *s, const char *suffix, size_t b) { - size_t a; - char *r; -@@ -1207,3 +1132,30 @@ int string_extract_line(const char *s, size_t i, char **ret) { - c++; - } - } -+ -+int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word) { -+ /* In the default mode with no separators specified, we split on whitespace and -+ * don't coalesce separators. */ -+ const ExtractFlags flags = separators ? EXTRACT_DONT_COALESCE_SEPARATORS : 0; -+ -+ const char *found = NULL; -+ -+ for (const char *p = string;;) { -+ _cleanup_free_ char *w = NULL; -+ int r; -+ -+ r = extract_first_word(&p, &w, separators, flags); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; -+ -+ found = strv_find(words, w); -+ if (found) -+ break; -+ } -+ -+ if (ret_word) -+ *ret_word = found; -+ return !!found; -+} -diff --git a/src/basic/string-util.h b/src/basic/string-util.h -index 0913145..cefbda3 100644 ---- a/src/basic/string-util.h -+++ b/src/basic/string-util.h -@@ -108,24 +108,6 @@ char *endswith_no_case(const char *s, const char *postfix) _pure_; - - char *first_word(const char *s, const char *word) _pure_; - --typedef enum SplitFlags { -- SPLIT_QUOTES = 0x01 << 0, -- SPLIT_RELAX = 0x01 << 1, --} SplitFlags; -- --/* Smelly. Do not use this anymore. Use extract_first_word() instead! */ --const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags); -- --/* Similar, don't use this anymore */ --#define FOREACH_WORD(word, length, s, state) \ -- _FOREACH_WORD(word, length, s, WHITESPACE, 0, state) -- --#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \ -- _FOREACH_WORD(word, length, s, separator, 0, state) -- --#define _FOREACH_WORD(word, length, s, separator, flags, state) \ -- for ((state) = (s), (word) = split(&(state), &(length), (separator), (flags)); (word); (word) = split(&(state), &(length), (separator), (flags))) -- - char *strnappend(const char *s, const char *suffix, size_t length); - - char *strjoin_real(const char *x, ...) _sentinel_; -@@ -135,8 +117,8 @@ char *strjoin_real(const char *x, ...) _sentinel_; - ({ \ - const char *_appendees_[] = { a, __VA_ARGS__ }; \ - char *_d_, *_p_; \ -- size_t _len_ = 0; \ -- size_t _i_; \ -+ size_t _len_ = 0; \ -+ size_t _i_; \ - for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ - _len_ += strlen(_appendees_[_i_]); \ - _p_ = _d_ = newa(char, _len_ + 1); \ -@@ -152,7 +134,6 @@ char *delete_trailing_chars(char *s, const char *bad); - char *truncate_nl(char *s); - - static inline char *skip_leading_chars(const char *s, const char *bad) { -- - if (!s) - return NULL; - -@@ -231,11 +212,9 @@ REENABLE_WARNING; - - /* Like startswith(), but operates on arbitrary memory blocks */ - static inline void *memory_startswith(const void *p, size_t sz, const char *token) { -- size_t n; -- - assert(token); - -- n = strlen(token); -+ size_t n = strlen(token); - if (sz < n) - return NULL; - -@@ -251,20 +230,17 @@ static inline void *memory_startswith(const void *p, size_t sz, const char *toke - * It works only for ASCII strings. - */ - static inline void *memory_startswith_no_case(const void *p, size_t sz, const char *token) { -- size_t n, i; -- - assert(token); - -- n = strlen(token); -+ size_t n = strlen(token); - if (sz < n) - return NULL; - - assert(p); - -- for (i = 0; i < n; i++) { -+ for (size_t i = 0; i < n; i++) - if (ascii_tolower(((char *)p)[i]) != ascii_tolower(token[i])) - return NULL; -- } - - return (uint8_t*) p + n; - } -@@ -286,3 +262,8 @@ char* string_erase(char *x); - - int string_truncate_lines(const char *s, size_t n_lines, char **ret); - int string_extract_line(const char *s, size_t i, char **ret); -+ -+int string_contains_word_strv(const char *string, const char *separators, char **words, const char **ret_word); -+static inline int string_contains_word(const char *string, const char *separators, const char *word) { -+ return string_contains_word_strv(string, separators, STRV_MAKE(word), NULL); -+} -diff --git a/src/basic/strv.c b/src/basic/strv.c -index 858e1e6..e4ecf40 100644 ---- a/src/basic/strv.c -+++ b/src/basic/strv.c -@@ -256,44 +256,6 @@ int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix) { - return 0; - } - --char **strv_split_full(const char *s, const char *separator, SplitFlags flags) { -- const char *word, *state; -- size_t l; -- size_t n, i; -- char **r; -- -- assert(s); -- -- if (!separator) -- separator = WHITESPACE; -- -- s += strspn(s, separator); -- if (isempty(s)) -- return new0(char*, 1); -- -- n = 0; -- _FOREACH_WORD(word, l, s, separator, flags, state) -- n++; -- -- r = new(char*, n+1); -- if (!r) -- return NULL; -- -- i = 0; -- _FOREACH_WORD(word, l, s, separator, flags, state) { -- r[i] = strndup(word, l); -- if (!r[i]) { -- strv_free(r); -- return NULL; -- } -- -- i++; -- } -- -- r[i] = NULL; -- return r; --} -- - char **strv_split_newlines(const char *s) { - char **l; - size_t n; -@@ -317,7 +279,7 @@ char **strv_split_newlines(const char *s) { - return l; - } - --int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) { -+int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags) { - _cleanup_strv_free_ char **l = NULL; - size_t n = 0, allocated = 0; - int r; -@@ -353,6 +315,58 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract - return (int) n; - } - -+int strv_split_colon_pairs(char ***t, const char *s) { -+ _cleanup_strv_free_ char **l = NULL; -+ size_t n = 0, allocated = 0; -+ int r; -+ -+ assert(t); -+ assert(s); -+ -+ for (;;) { -+ _cleanup_free_ char *first = NULL, *second = NULL, *tuple = NULL, *second_or_empty = NULL; -+ -+ r = extract_first_word(&s, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; -+ -+ const char *p = tuple; -+ r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, -+ &first, &second, NULL); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ continue; -+ /* Enforce that at most 2 colon-separated words are contained in each group */ -+ if (!isempty(p)) -+ return -EINVAL; -+ -+ second_or_empty = strdup(strempty(second)); -+ if (!second_or_empty) -+ return -ENOMEM; -+ -+ if (!GREEDY_REALLOC(l, allocated, n + 3)) -+ return -ENOMEM; -+ -+ l[n++] = TAKE_PTR(first); -+ l[n++] = TAKE_PTR(second_or_empty); -+ -+ l[n] = NULL; -+ } -+ -+ if (!l) { -+ l = new0(char*, 1); -+ if (!l) -+ return -ENOMEM; -+ } -+ -+ *t = TAKE_PTR(l); -+ -+ return (int) n; -+} -+ - char *strv_join_prefix(char * const *l, const char *separator, const char *prefix) { - char * const *s; - char *r, *e; -diff --git a/src/basic/strv.h b/src/basic/strv.h -index 2ad927b..9468edc 100644 ---- a/src/basic/strv.h -+++ b/src/basic/strv.h -@@ -72,13 +72,24 @@ static inline bool strv_isempty(char * const *l) { - return !l || !*l; - } - --char **strv_split_full(const char *s, const char *separator, SplitFlags flags); --static inline char **strv_split(const char *s, const char *separator) { -- return strv_split_full(s, separator, 0); --} - char **strv_split_newlines(const char *s); - --int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags); -+int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags); -+static inline char **strv_split(const char *s, const char *separators) { -+ char **ret; -+ int r; -+ -+ r = strv_split_full(&ret, s, separators, 0); -+ if (r < 0) -+ return NULL; -+ -+ return ret; -+} -+ -+/* Given a string containing white-space separated tuples of words themselves separated by ':', -+ * returns a vector of strings. If the second element in a tuple is missing, the corresponding -+ * string in the vector is an empty string. */ -+int strv_split_colon_pairs(char ***t, const char *s); - - char *strv_join_prefix(char * const *l, const char *separator, const char *prefix); - static inline char *strv_join(char * const *l, const char *separator) { -@@ -118,10 +129,6 @@ bool strv_overlap(char * const *a, char * const *b) _pure_; - char **strv_sort(char **l); - void strv_print(char * const *l); - --#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL })) -- --#define STRV_MAKE_EMPTY ((char*[1]) { NULL }) -- - #define strv_from_stdarg_alloca(first) \ - ({ \ - char **_l; \ -diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h -index 67634b4..42a129c 100644 ---- a/src/basic/terminal-util.h -+++ b/src/basic/terminal-util.h -@@ -11,21 +11,41 @@ - #include "time-util.h" - - /* Regular colors */ -+#define ANSI_BLACK "\x1B[0;30m" /* Some type of grey usually. */ - #define ANSI_RED "\x1B[0;31m" - #define ANSI_GREEN "\x1B[0;32m" - #define ANSI_YELLOW "\x1B[0;33m" - #define ANSI_BLUE "\x1B[0;34m" - #define ANSI_MAGENTA "\x1B[0;35m" -+#define ANSI_CYAN "\x1B[0;36m" -+#define ANSI_WHITE "\x1B[0;37m" /* This is actually rendered as light grey, legible even on a white -+ * background. See ANSI_HIGHLIGHT_WHITE for real white. */ -+ -+#define ANSI_BRIGHT_BLACK "\x1B[0;90m" -+#define ANSI_BRIGHT_RED "\x1B[0;91m" -+#define ANSI_BRIGHT_GREEN "\x1B[0;92m" -+#define ANSI_BRIGHT_YELLOW "\x1B[0;93m" -+#define ANSI_BRIGHT_BLUE "\x1B[0;94m" -+#define ANSI_BRIGHT_MAGENTA "\x1B[0;95m" -+#define ANSI_BRIGHT_CYAN "\x1B[0;96m" -+#define ANSI_BRIGHT_WHITE "\x1B[0;97m" -+ - #define ANSI_GREY "\x1B[0;38;5;245m" - - /* Bold/highlighted */ --#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m" --#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m" --#define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;38;5;185m" --#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m" --#define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m" --#define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38;5;245m" --#define ANSI_HIGHLIGHT_YELLOW4 "\x1B[0;1;38;5;100m" -+#define ANSI_HIGHLIGHT_BLACK "\x1B[0;1;30m" -+#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m" -+#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m" -+#define _ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m" /* This yellow is currently not displayed well by some terminals */ -+#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m" -+#define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m" -+#define ANSI_HIGHLIGHT_CYAN "\x1B[0;1;36m" -+#define ANSI_HIGHLIGHT_WHITE "\x1B[0;1;37m" -+#define ANSI_HIGHLIGHT_YELLOW4 "\x1B[0;1;38;5;100m" -+#define ANSI_HIGHLIGHT_KHAKI3 "\x1B[0;1;38;5;185m" -+#define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38;5;245m" -+ -+#define ANSI_HIGHLIGHT_YELLOW ANSI_HIGHLIGHT_KHAKI3 /* Replacement yellow that is more legible */ - - /* Underlined */ - #define ANSI_GREY_UNDERLINE "\x1B[0;4;38;5;245m" -@@ -124,18 +144,38 @@ bool dev_console_colors_enabled(void); - - DEFINE_ANSI_FUNC(normal, NORMAL); - DEFINE_ANSI_FUNC(highlight, HIGHLIGHT); -+DEFINE_ANSI_FUNC(black, BLACK); - DEFINE_ANSI_FUNC(red, RED); - DEFINE_ANSI_FUNC(green, GREEN); - DEFINE_ANSI_FUNC(yellow, YELLOW); - DEFINE_ANSI_FUNC(blue, BLUE); - DEFINE_ANSI_FUNC(magenta, MAGENTA); -+DEFINE_ANSI_FUNC(cyan, CYAN); -+DEFINE_ANSI_FUNC(white, WHITE); - DEFINE_ANSI_FUNC(grey, GREY); -+ -+DEFINE_ANSI_FUNC(bright_black, BRIGHT_BLACK); -+DEFINE_ANSI_FUNC(bright_red, BRIGHT_RED); -+DEFINE_ANSI_FUNC(bright_green, BRIGHT_GREEN); -+DEFINE_ANSI_FUNC(bright_yellow, BRIGHT_YELLOW); -+DEFINE_ANSI_FUNC(bright_blue, BRIGHT_BLUE); -+DEFINE_ANSI_FUNC(bright_magenta, BRIGHT_MAGENTA); -+DEFINE_ANSI_FUNC(bright_cyan, BRIGHT_CYAN); -+DEFINE_ANSI_FUNC(bright_white, BRIGHT_WHITE); -+ -+DEFINE_ANSI_FUNC(highlight_black, HIGHLIGHT_BLACK); - DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED); - DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN); - DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW); - DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE); - DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA); -+DEFINE_ANSI_FUNC(highlight_cyan, HIGHLIGHT_CYAN); - DEFINE_ANSI_FUNC(highlight_grey, HIGHLIGHT_GREY); -+DEFINE_ANSI_FUNC(highlight_white, HIGHLIGHT_WHITE); -+ -+static inline const char* _ansi_highlight_yellow(void) { -+ return colors_enabled() ? _ANSI_HIGHLIGHT_YELLOW : ""; -+} - - DEFINE_ANSI_FUNC_UNDERLINE(underline, UNDERLINE, NORMAL); - DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline, HIGHLIGHT_UNDERLINE, HIGHLIGHT); -diff --git a/src/basic/time-util.c b/src/basic/time-util.c -index 15cc1b8..7fa3b48 100644 ---- a/src/basic/time-util.c -+++ b/src/basic/time-util.c -@@ -23,6 +23,7 @@ - #include "path-util.h" - #include "process-util.h" - #include "stat-util.h" -+#include "string-table.h" - #include "string-util.h" - #include "strv.h" - #include "time-util.h" -@@ -243,12 +244,28 @@ struct timespec *timespec_store(struct timespec *ts, usec_t u) { - if (u == USEC_INFINITY || - u / USEC_PER_SEC >= TIME_T_MAX) { - ts->tv_sec = (time_t) -1; -- ts->tv_nsec = (long) -1; -+ ts->tv_nsec = -1L; - return ts; - } - - ts->tv_sec = (time_t) (u / USEC_PER_SEC); -- ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC); -+ ts->tv_nsec = (long) ((u % USEC_PER_SEC) * NSEC_PER_USEC); -+ -+ return ts; -+} -+ -+struct timespec *timespec_store_nsec(struct timespec *ts, nsec_t n) { -+ assert(ts); -+ -+ if (n == NSEC_INFINITY || -+ n / NSEC_PER_SEC >= TIME_T_MAX) { -+ ts->tv_sec = (time_t) -1; -+ ts->tv_nsec = -1L; -+ return ts; -+ } -+ -+ ts->tv_sec = (time_t) (n / NSEC_PER_SEC); -+ ts->tv_nsec = (long) (n % NSEC_PER_SEC); - - return ts; - } -@@ -282,12 +299,11 @@ struct timeval *timeval_store(struct timeval *tv, usec_t u) { - return tv; - } - --static char *format_timestamp_internal( -+char *format_timestamp_style( - char *buf, - size_t l, - usec_t t, -- bool utc, -- bool us) { -+ TimestampStyle style) { - - /* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our - * generated timestamps may be parsed with parse_timestamp(), and always read the same. */ -@@ -304,9 +320,27 @@ static char *format_timestamp_internal( - struct tm tm; - time_t sec; - size_t n; -+ bool utc = false, us = false; - - assert(buf); - -+ switch (style) { -+ case TIMESTAMP_PRETTY: -+ break; -+ case TIMESTAMP_US: -+ us = true; -+ break; -+ case TIMESTAMP_UTC: -+ utc = true; -+ break; -+ case TIMESTAMP_US_UTC: -+ us = true; -+ utc = true; -+ break; -+ default: -+ return NULL; -+ } -+ - if (l < (size_t) (3 + /* week day */ - 1 + 10 + /* space and date */ - 1 + 8 + /* space and time */ -@@ -380,22 +414,6 @@ static char *format_timestamp_internal( - return buf; - } - --char *format_timestamp(char *buf, size_t l, usec_t t) { -- return format_timestamp_internal(buf, l, t, false, false); --} -- --char *format_timestamp_utc(char *buf, size_t l, usec_t t) { -- return format_timestamp_internal(buf, l, t, true, false); --} -- --char *format_timestamp_us(char *buf, size_t l, usec_t t) { -- return format_timestamp_internal(buf, l, t, false, true); --} -- --char *format_timestamp_us_utc(char *buf, size_t l, usec_t t) { -- return format_timestamp_internal(buf, l, t, true, true); --} -- - char *format_timestamp_relative(char *buf, size_t l, usec_t t) { - const char *s; - usec_t n, d; -@@ -1568,3 +1586,27 @@ int time_change_fd(void) { - - return -errno; - } -+ -+static const char* const timestamp_style_table[_TIMESTAMP_STYLE_MAX] = { -+ [TIMESTAMP_PRETTY] = "pretty", -+ [TIMESTAMP_US] = "us", -+ [TIMESTAMP_UTC] = "utc", -+ [TIMESTAMP_US_UTC] = "us+utc", -+}; -+ -+/* Use the macro for enum → string to allow for aliases */ -+_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(timestamp_style, TimestampStyle,); -+ -+/* For the string → enum mapping we use the generic implementation, but also support two aliases */ -+TimestampStyle timestamp_style_from_string(const char *s) { -+ TimestampStyle t; -+ -+ t = (TimestampStyle) string_table_lookup(timestamp_style_table, ELEMENTSOF(timestamp_style_table), s); -+ if (t >= 0) -+ return t; -+ if (streq_ptr(s, "µs")) -+ return TIMESTAMP_US; -+ if (streq_ptr(s, "µs+uts")) -+ return TIMESTAMP_US_UTC; -+ return t; -+} -diff --git a/src/basic/time-util.h b/src/basic/time-util.h -index 9bbe986..cecd5ef 100644 ---- a/src/basic/time-util.h -+++ b/src/basic/time-util.h -@@ -29,6 +29,15 @@ typedef struct triple_timestamp { - usec_t boottime; - } triple_timestamp; - -+typedef enum TimestampStyle { -+ TIMESTAMP_PRETTY, -+ TIMESTAMP_US, -+ TIMESTAMP_UTC, -+ TIMESTAMP_US_UTC, -+ _TIMESTAMP_STYLE_MAX, -+ _TIMESTAMP_STYLE_INVALID = -1, -+} TimestampStyle; -+ - #define USEC_INFINITY ((usec_t) UINT64_MAX) - #define NSEC_INFINITY ((nsec_t) UINT64_MAX) - -@@ -103,17 +112,19 @@ usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock); - usec_t timespec_load(const struct timespec *ts) _pure_; - nsec_t timespec_load_nsec(const struct timespec *ts) _pure_; - struct timespec *timespec_store(struct timespec *ts, usec_t u); -+struct timespec *timespec_store_nsec(struct timespec *ts, nsec_t n); - - usec_t timeval_load(const struct timeval *tv) _pure_; - struct timeval *timeval_store(struct timeval *tv, usec_t u); - --char *format_timestamp(char *buf, size_t l, usec_t t); --char *format_timestamp_utc(char *buf, size_t l, usec_t t); --char *format_timestamp_us(char *buf, size_t l, usec_t t); --char *format_timestamp_us_utc(char *buf, size_t l, usec_t t); -+char *format_timestamp_style(char *buf, size_t l, usec_t t, TimestampStyle style); - char *format_timestamp_relative(char *buf, size_t l, usec_t t); - char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy); - -+static inline char *format_timestamp(char *buf, size_t l, usec_t t) { -+ return format_timestamp_style(buf, l, t, TIMESTAMP_PRETTY); -+} -+ - int parse_timestamp(const char *t, usec_t *usec); - - int parse_sec(const char *t, usec_t *usec); -@@ -185,3 +196,6 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) { - #endif - - int time_change_fd(void); -+ -+const char* timestamp_style_to_string(TimestampStyle t) _const_; -+TimestampStyle timestamp_style_from_string(const char *s) _pure_; -diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h -index 53419ec..1fab6c7 100644 ---- a/src/basic/unit-def.h -+++ b/src/basic/unit-def.h -@@ -9,7 +9,7 @@ - * when other criteria (cpu weight, nice level) are identical. - * In this case service units have the highest priority. */ - typedef enum UnitType { -- UNIT_SERVICE = 0, -+ UNIT_SERVICE, - UNIT_MOUNT, - UNIT_SWAP, - UNIT_SOCKET, -@@ -25,7 +25,7 @@ typedef enum UnitType { - } UnitType; - - typedef enum UnitLoadState { -- UNIT_STUB = 0, -+ UNIT_STUB, - UNIT_LOADED, - UNIT_NOT_FOUND, /* error condition #1: unit file not found */ - UNIT_BAD_SETTING, /* error condition #2: we couldn't parse some essential unit file setting */ -diff --git a/src/basic/user-util.c b/src/basic/user-util.c -index 8115065..0e96a75 100644 ---- a/src/basic/user-util.c -+++ b/src/basic/user-util.c -@@ -863,6 +863,37 @@ bool valid_gecos(const char *d) { - return true; - } - -+char *mangle_gecos(const char *d) { -+ char *mangled; -+ -+ /* Makes sure the provided string becomes valid as a GEGOS field, by dropping bad chars. glibc's -+ * putwent() only changes \n and : to spaces. We do more: replace all CC too, and remove invalid -+ * UTF-8 */ -+ -+ mangled = strdup(d); -+ if (!mangled) -+ return NULL; -+ -+ for (char *i = mangled; *i; i++) { -+ int len; -+ -+ if ((uint8_t) *i < (uint8_t) ' ' || *i == ':') { -+ *i = ' '; -+ continue; -+ } -+ -+ len = utf8_encoded_valid_unichar(i, (size_t) -1); -+ if (len < 0) { -+ *i = ' '; -+ continue; -+ } -+ -+ i += len - 1; -+ } -+ -+ return mangled; -+} -+ - bool valid_home(const char *p) { - /* Note that this function is also called by valid_shell(), any - * changes must account for that. */ -diff --git a/src/basic/user-util.h b/src/basic/user-util.h -index 1f267d2..7c142dd 100644 ---- a/src/basic/user-util.h -+++ b/src/basic/user-util.h -@@ -105,6 +105,7 @@ typedef enum ValidUserFlags { - - bool valid_user_group_name(const char *u, ValidUserFlags flags); - bool valid_gecos(const char *d); -+char *mangle_gecos(const char *d); - bool valid_home(const char *p); - - static inline bool valid_shell(const char *p) { -diff --git a/src/basic/utf8.c b/src/basic/utf8.c -index c857185..f023339 100644 ---- a/src/basic/utf8.c -+++ b/src/basic/utf8.c -@@ -123,7 +123,7 @@ int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) { - return 0; - } - --bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { -+bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) { - const char *p; - - assert(str); -@@ -140,7 +140,7 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { - r = utf8_encoded_to_unichar(p, &val); - if (r < 0 || - unichar_is_control(val) || -- (!newline && val == '\n')) -+ (!allow_newline && val == '\n')) - return false; - - length -= encoded_len; -@@ -150,18 +150,22 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { - return true; - } - --char *utf8_is_valid(const char *str) { -- const char *p; -+char *utf8_is_valid_n(const char *str, size_t len_bytes) { -+ /* Check if the string is composed of valid utf8 characters. If length len_bytes is given, stop after -+ * len_bytes. Otherwise, stop at NUL. */ - - assert(str); - -- p = str; -- while (*p) { -+ for (const char *p = str; len_bytes != (size_t) -1 ? (size_t) (p - str) < len_bytes : *p != '\0'; ) { - int len; - -- len = utf8_encoded_valid_unichar(p, (size_t) -1); -- if (len < 0) -- return NULL; -+ if (_unlikely_(*p == '\0') && len_bytes != (size_t) -1) -+ return NULL; /* embedded NUL */ -+ -+ len = utf8_encoded_valid_unichar(p, -+ len_bytes != (size_t) -1 ? len_bytes - (p - str) : (size_t) -1); -+ if (_unlikely_(len < 0)) -+ return NULL; /* invalid character */ - - p += len; - } -diff --git a/src/basic/utf8.h b/src/basic/utf8.h -index 62e99b7..f315ea0 100644 ---- a/src/basic/utf8.h -+++ b/src/basic/utf8.h -@@ -14,11 +14,14 @@ - - bool unichar_is_valid(char32_t c); - --char *utf8_is_valid(const char *s) _pure_; -+char *utf8_is_valid_n(const char *str, size_t len_bytes) _pure_; -+static inline char *utf8_is_valid(const char *s) { -+ return utf8_is_valid_n(s, (size_t) -1); -+} - char *ascii_is_valid(const char *s) _pure_; - char *ascii_is_valid_n(const char *str, size_t len); - --bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_; -+bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) _pure_; - #define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true) - - char *utf8_escape_invalid(const char *s); -diff --git a/src/basic/virt.c b/src/basic/virt.c -index c6bff6b..212b3b7 100644 ---- a/src/basic/virt.c -+++ b/src/basic/virt.c -@@ -442,6 +442,7 @@ static const char *const container_table[_VIRTUALIZATION_MAX] = { - [VIRTUALIZATION_RKT] = "rkt", - [VIRTUALIZATION_WSL] = "wsl", - [VIRTUALIZATION_PROOT] = "proot", -+ [VIRTUALIZATION_POUCH] = "pouch", - }; - - DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int); -@@ -490,6 +491,16 @@ int detect_container(void) { - } - } - -+ /* The container manager might have placed this in the /run/host hierarchy for us, which is best -+ * because we can be consumed just like that, without special privileges. */ -+ r = read_one_line_file("/run/host/container-manager", &m); -+ if (r > 0) { -+ e = m; -+ goto translate_name; -+ } -+ if (!IN_SET(r, -ENOENT, 0)) -+ return log_debug_errno(r, "Failed to read /run/systemd/container: %m"); -+ - if (getpid_cached() == 1) { - /* If we are PID 1 we can just check our own environment variable, and that's authoritative. - * We distinguish three cases: -@@ -679,6 +690,7 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = { - [VIRTUALIZATION_RKT] = "rkt", - [VIRTUALIZATION_WSL] = "wsl", - [VIRTUALIZATION_PROOT] = "proot", -+ [VIRTUALIZATION_POUCH] = "pouch", - [VIRTUALIZATION_CONTAINER_OTHER] = "container-other", - }; - -diff --git a/src/basic/virt.h b/src/basic/virt.h -index d58c582..18aa5ef 100644 ---- a/src/basic/virt.h -+++ b/src/basic/virt.h -@@ -35,6 +35,7 @@ enum { - VIRTUALIZATION_RKT, - VIRTUALIZATION_WSL, - VIRTUALIZATION_PROOT, -+ VIRTUALIZATION_POUCH, - VIRTUALIZATION_CONTAINER_OTHER, - VIRTUALIZATION_CONTAINER_LAST = VIRTUALIZATION_CONTAINER_OTHER, - -diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c -index 0125a9c..fe0735e 100644 ---- a/src/basic/xattr-util.c -+++ b/src/basic/xattr-util.c -@@ -12,6 +12,7 @@ - #include "macro.h" - #include "missing_syscall.h" - #include "sparse-endian.h" -+#include "stat-util.h" - #include "stdio-util.h" - #include "string-util.h" - #include "time-util.h" -@@ -154,12 +155,7 @@ static int parse_crtime(le64_t le, usec_t *usec) { - } - - int fd_getcrtime_at(int dirfd, const char *name, usec_t *ret, int flags) { -- struct_statx sx --#if HAS_FEATURE_MEMORY_SANITIZER -- = {} --# warning "Explicitly initializing struct statx, to work around msan limitation. Please remove as soon as msan has been updated to not require this." --#endif -- ; -+ STRUCT_STATX_DEFINE(sx); - usec_t a, b; - le64_t le; - size_t n; -diff --git a/src/boot/bless-boot.c b/src/boot/bless-boot.c -index b96e1f9..0824266 100644 ---- a/src/boot/bless-boot.c -+++ b/src/boot/bless-boot.c -@@ -34,6 +34,7 @@ static int help(int argc, char *argv[], void *userdata) { - printf("%s [OPTIONS...] COMMAND\n" - "\n%sMark the boot process as good or bad.%s\n" - "\nCommands:\n" -+ " status Show status of current boot loader entry\n" - " good Mark this boot as good\n" - " bad Mark this boot as bad\n" - " indeterminate Undo any marking as good or bad\n" -diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c -index a663fc5..f464882 100644 ---- a/src/boot/bootctl.c -+++ b/src/boot/bootctl.c -@@ -118,7 +118,7 @@ static int get_file_version(int fd, char **v) { - char *buf; - const char *s, *e; - char *x = NULL; -- int r = 0; -+ int r; - - assert(fd >= 0); - assert(v); -@@ -248,7 +248,7 @@ static int print_efi_option(uint16_t id, bool in_order) { - _cleanup_free_ char *path = NULL; - sd_id128_t partition; - bool active; -- int r = 0; -+ int r; - - r = efi_get_boot_option(id, &title, &partition, &path, &active); - if (r < 0) -@@ -888,14 +888,6 @@ static int remove_subdirs(const char *root, const char *const *subdirs) { - return r < 0 ? r : q; - } - --static int remove_machine_id_directory(const char *root, sd_id128_t machine_id) { -- char buf[SD_ID128_STRING_MAX]; -- -- assert(root); -- -- return rmdir_one(root, sd_id128_to_string(machine_id, buf)); --} -- - static int remove_binaries(const char *esp_path) { - const char *p; - int r, q; -@@ -978,8 +970,7 @@ static int remove_loader_variables(void) { - return r; - } - --static int install_loader_config(const char *esp_path, sd_id128_t machine_id) { -- char machine_string[SD_ID128_STRING_MAX]; -+static int install_loader_config(const char *esp_path) { - _cleanup_(unlink_and_freep) char *t = NULL; - _cleanup_fclose_ FILE *f = NULL; - _cleanup_close_ int fd = -1; -@@ -999,8 +990,7 @@ static int install_loader_config(const char *esp_path, sd_id128_t machine_id) { - return log_oom(); - - fprintf(f, "#timeout 3\n" -- "#console-mode keep\n" -- "default %s-*\n", sd_id128_to_string(machine_id, machine_string)); -+ "#console-mode keep\n"); - - r = fflush_sync_and_check(f); - if (r < 0) -@@ -1016,14 +1006,6 @@ static int install_loader_config(const char *esp_path, sd_id128_t machine_id) { - return 1; - } - --static int install_machine_id_directory(const char *root, sd_id128_t machine_id) { -- char buf[SD_ID128_STRING_MAX]; -- -- assert(root); -- -- return mkdir_one(root, sd_id128_to_string(machine_id, buf)); --} -- - static int help(int argc, char *argv[], void *userdata) { - _cleanup_free_ char *link = NULL; - int r; -@@ -1249,15 +1231,15 @@ static int verb_status(int argc, char *argv[], void *userdata) { - printf(" Secure Boot: %sd\n", enable_disable(is_efi_secure_boot())); - printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user"); - -- r = efi_get_reboot_to_firmware(); -- if (r > 0) -+ k = efi_get_reboot_to_firmware(); -+ if (k > 0) - printf(" Boot into FW: %sactive%s\n", ansi_highlight_yellow(), ansi_normal()); -- else if (r == 0) -+ else if (k == 0) - printf(" Boot into FW: supported\n"); -- else if (r == -EOPNOTSUPP) -+ else if (k == -EOPNOTSUPP) - printf(" Boot into FW: not supported\n"); - else { -- errno = -r; -+ errno = -k; - printf(" Boot into FW: %sfailed%s (%m)\n", ansi_highlight_red(), ansi_normal()); - } - printf("\n"); -@@ -1472,7 +1454,9 @@ static int install_random_seed(const char *esp) { - } - - r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderSystemToken", NULL, NULL, &token_size); -- if (r < 0) { -+ if (r == -ENODATA) -+ log_debug_errno(r, "LoaderSystemToken EFI variable is invalid (too short?), replacing."); -+ else if (r < 0) { - if (r != -ENOENT) - return log_error_errno(r, "Failed to test system token validity: %m"); - } else { -@@ -1531,7 +1515,6 @@ static int verb_install(int argc, char *argv[], void *userdata) { - sd_id128_t uuid = SD_ID128_NULL; - uint64_t pstart = 0, psize = 0; - uint32_t part = 0; -- sd_id128_t machine_id; - bool install; - int r; - -@@ -1543,10 +1526,6 @@ static int verb_install(int argc, char *argv[], void *userdata) { - if (r < 0) - return r; - -- r = sd_id128_get_machine(&machine_id); -- if (r < 0) -- return log_error_errno(r, "Failed to get machine id: %m"); -- - install = streq(argv[0], "install"); - - RUN_WITH_UMASK(0002) { -@@ -1568,11 +1547,7 @@ static int verb_install(int argc, char *argv[], void *userdata) { - return r; - - if (install) { -- r = install_loader_config(arg_esp_path, machine_id); -- if (r < 0) -- return r; -- -- r = install_machine_id_directory(arg_dollar_boot_path(), machine_id); -+ r = install_loader_config(arg_esp_path); - if (r < 0) - return r; - -@@ -1594,7 +1569,7 @@ static int verb_install(int argc, char *argv[], void *userdata) { - } - - static int verb_remove(int argc, char *argv[], void *userdata) { -- sd_id128_t uuid = SD_ID128_NULL, machine_id; -+ sd_id128_t uuid = SD_ID128_NULL; - int r, q; - - r = acquire_esp(false, NULL, NULL, NULL, &uuid); -@@ -1605,10 +1580,6 @@ static int verb_remove(int argc, char *argv[], void *userdata) { - if (r < 0) - return r; - -- r = sd_id128_get_machine(&machine_id); -- if (r < 0) -- return log_error_errno(r, "Failed to get machine id: %m"); -- - r = remove_binaries(arg_esp_path); - - q = remove_file(arg_esp_path, "/loader/loader.conf"); -@@ -1627,19 +1598,11 @@ static int verb_remove(int argc, char *argv[], void *userdata) { - if (q < 0 && r >= 0) - r = q; - -- q = remove_machine_id_directory(arg_esp_path, machine_id); -- if (q < 0 && r >= 0) -- r = 1; -- - if (arg_xbootldr_path) { - /* Remove the latter two also in the XBOOTLDR partition if it exists */ - q = remove_subdirs(arg_xbootldr_path, dollar_boot_subdirs); - if (q < 0 && r >= 0) - r = q; -- -- q = remove_machine_id_directory(arg_xbootldr_path, machine_id); -- if (q < 0 && r >= 0) -- r = q; - } - - (void) sync_everything(); -diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c -index ccb22d5..16dca64 100644 ---- a/src/busctl/busctl.c -+++ b/src/busctl/busctl.c -@@ -145,7 +145,6 @@ static int list_bus_names(int argc, char **argv, void *userdata) { - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_hashmap_free_ Hashmap *names = NULL; - _cleanup_(table_unrefp) Table *table = NULL; -- Iterator iterator; - char **i, *k; - void *v; - int r; -@@ -247,7 +246,7 @@ static int list_bus_names(int argc, char **argv, void *userdata) { - - table_set_header(table, arg_legend); - -- HASHMAP_FOREACH_KEY(v, k, names, iterator) { -+ HASHMAP_FOREACH_KEY(v, k, names) { - _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; - - if (v == NAME_IS_ACTIVATABLE) { -@@ -532,7 +531,7 @@ static int tree_one(sd_bus *bus, const char *service) { - static int tree(int argc, char **argv, void *userdata) { - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - char **i; -- int r = 0; -+ int r; - - /* Do superficial verification of arguments before even opening the bus */ - STRV_FOREACH(i, strv_skip(argv, 1)) -@@ -986,7 +985,6 @@ static int introspect(int argc, char **argv, void *userdata) { - _cleanup_(member_set_freep) Set *members = NULL; - unsigned name_width, type_width, signature_width, result_width, j, k = 0; - Member *m, **sorted = NULL; -- Iterator i; - const char *xml; - int r; - -@@ -1022,7 +1020,7 @@ static int introspect(int argc, char **argv, void *userdata) { - return r; - - /* Second, find the current values for them */ -- SET_FOREACH(m, members, i) { -+ SET_FOREACH(m, members) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - - if (!streq(m->type, "property")) -@@ -1105,7 +1103,7 @@ static int introspect(int argc, char **argv, void *userdata) { - - sorted = newa(Member*, set_size(members)); - -- SET_FOREACH(m, members, i) { -+ SET_FOREACH(m, members) { - if (argv[3] && !streq(argv[3], m->interface)) - continue; - -@@ -2396,7 +2394,7 @@ static int parse_argv(int argc, char *argv[]) { - assert(argc >= 0); - assert(argv); - -- while ((c = getopt_long(argc, argv, "hH:M:qj", options, NULL)) >= 0) -+ while ((c = getopt_long(argc, argv, "hH:M:qjl", options, NULL)) >= 0) - - switch (c) { - -diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c -index e6c09d1..042d83c 100644 ---- a/src/cgtop/cgtop.c -+++ b/src/cgtop/cgtop.c -@@ -582,7 +582,6 @@ static int group_compare(Group * const *a, Group * const *b) { - } - - static void display(Hashmap *a) { -- Iterator i; - Group *g; - Group **array; - signed path_columns; -@@ -596,7 +595,7 @@ static void display(Hashmap *a) { - - array = newa(Group*, hashmap_size(a)); - -- HASHMAP_FOREACH(g, a, i) -+ HASHMAP_FOREACH(g, a) - if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid) - array[n++] = g; - -diff --git a/src/core/automount.c b/src/core/automount.c -index 1f05198..4db763f 100644 ---- a/src/core/automount.c -+++ b/src/core/automount.c -@@ -507,8 +507,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) { - assert(other); - - /* Filter out invocations with bogus state */ -- if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT) -- return; -+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); -+ assert(other->type == UNIT_MOUNT); - - /* Don't propagate state changes from the mount if we are already down */ - if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)) -@@ -709,25 +709,25 @@ static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void - } - - static int automount_start_expire(Automount *a) { -- int r; - usec_t timeout; -+ int r; - - assert(a); - - if (a->timeout_idle_usec == 0) - return 0; - -- timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC); -+ timeout = MAX(a->timeout_idle_usec/3, USEC_PER_SEC); - - if (a->expire_event_source) { -- r = sd_event_source_set_time(a->expire_event_source, timeout); -+ r = sd_event_source_set_time_relative(a->expire_event_source, timeout); - if (r < 0) - return r; - - return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT); - } - -- r = sd_event_add_time( -+ r = sd_event_add_time_relative( - UNIT(a)->manager->event, - &a->expire_event_source, - CLOCK_MONOTONIC, timeout, 0, -@@ -850,7 +850,6 @@ static int automount_stop(Unit *u) { - - static int automount_serialize(Unit *u, FILE *f, FDSet *fds) { - Automount *a = AUTOMOUNT(u); -- Iterator i; - void *p; - int r; - -@@ -862,9 +861,9 @@ static int automount_serialize(Unit *u, FILE *f, FDSet *fds) { - (void) serialize_item(f, "result", automount_result_to_string(a->result)); - (void) serialize_item_format(f, "dev-id", "%lu", (unsigned long) a->dev_id); - -- SET_FOREACH(p, a->tokens, i) -+ SET_FOREACH(p, a->tokens) - (void) serialize_item_format(f, "token", "%u", PTR_TO_UINT(p)); -- SET_FOREACH(p, a->expire_tokens, i) -+ SET_FOREACH(p, a->expire_tokens) - (void) serialize_item_format(f, "expire-token", "%u", PTR_TO_UINT(p)); - - r = serialize_fd(f, fds, "pipe-fd", a->pipe_fd); -diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c -index bceb049..5da0106 100644 ---- a/src/core/bpf-firewall.c -+++ b/src/core/bpf-firewall.c -@@ -646,14 +646,13 @@ int bpf_firewall_load_custom(Unit *u) { - - static int attach_custom_bpf_progs(Unit *u, const char *path, int attach_type, Set **set, Set **set_installed) { - BPFProgram *prog; -- Iterator i; - int r; - - assert(u); - - set_clear(*set_installed); - -- SET_FOREACH(prog, *set, i) { -+ SET_FOREACH(prog, *set) { - r = bpf_program_cgroup_attach(prog, attach_type, path, BPF_F_ALLOW_MULTI); - if (r < 0) - return log_unit_error_errno(u, r, "Attaching custom egress BPF program to cgroup %s failed: %m", path); -@@ -900,11 +899,11 @@ void emit_bpf_firewall_warning(Unit *u) { - if (!warned) { - bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container(); - -- log_unit_full(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason, -- "unit configures an IP firewall, but %s.\n" -- "(This warning is only shown for the first unit using IP firewalling.)", -- getuid() != 0 ? "not running as root" : -- "the local system does not support BPF/cgroup firewalling"); -+ log_unit_full_errno(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason, -+ "unit configures an IP firewall, but %s.\n" -+ "(This warning is only shown for the first unit using IP firewalling.)", -+ getuid() != 0 ? "not running as root" : -+ "the local system does not support BPF/cgroup firewalling"); - warned = true; - } - } -diff --git a/src/core/cgroup.c b/src/core/cgroup.c -index 031b28a..8b97d15 100644 ---- a/src/core/cgroup.c -+++ b/src/core/cgroup.c -@@ -78,8 +78,8 @@ static int set_attribute_and_warn(Unit *u, const char *controller, const char *a - - r = cg_set_attribute(controller, u->cgroup_path, attribute, value); - if (r < 0) -- log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m", -- strna(attribute), isempty(u->cgroup_path) ? "/" : u->cgroup_path, (int) strcspn(value, NEWLINE), value); -+ log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m", -+ strna(attribute), isempty(u->cgroup_path) ? "/" : u->cgroup_path, (int) strcspn(value, NEWLINE), value); - - return r; - } -@@ -724,7 +724,7 @@ static usec_t cgroup_cpu_adjust_period_and_log(Unit *u, usec_t period, usec_t qu - - if (new_period != period) { - char v[FORMAT_TIMESPAN_MAX]; -- log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING, 0, -+ log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING, - "Clamping CPU interval for cpu.max: period is now %s", - format_timespan(v, sizeof(v), new_period, 1)); - u->warned_clamping_cpu_quota_period = true; -@@ -986,8 +986,8 @@ static int cgroup_apply_devices(Unit *u) { - else - r = cg_set_attribute("devices", path, "devices.allow", "a"); - if (r < 0) -- log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r, -- "Failed to reset devices.allow/devices.deny: %m"); -+ log_unit_full_errno(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r, -+ "Failed to reset devices.allow/devices.deny: %m"); - } - - bool allow_list_static = policy == CGROUP_DEVICE_POLICY_CLOSED || -@@ -1351,8 +1351,8 @@ static void cgroup_context_apply( - else - r = 0; - if (r < 0) -- log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r, -- "Failed to write to tasks limit sysctls: %m"); -+ log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, -+ "Failed to write to tasks limit sysctls: %m"); - } - - /* The attribute itself is not available on the host root cgroup, and in the container case we want to -@@ -1469,7 +1469,7 @@ CGroupMask unit_get_own_mask(Unit *u) { - if (!c) - return 0; - -- return (unit_get_cgroup_mask(u) | unit_get_bpf_mask(u) | unit_get_delegate_mask(u)) & ~unit_get_ancestor_disable_mask(u); -+ return unit_get_cgroup_mask(u) | unit_get_bpf_mask(u) | unit_get_delegate_mask(u); - } - - CGroupMask unit_get_delegate_mask(Unit *u) { -@@ -1495,6 +1495,14 @@ CGroupMask unit_get_delegate_mask(Unit *u) { - return CGROUP_MASK_EXTEND_JOINED(c->delegate_controllers); - } - -+static CGroupMask unit_get_subtree_mask(Unit *u) { -+ -+ /* Returns the mask of this subtree, meaning of the group -+ * itself and its children. */ -+ -+ return unit_get_own_mask(u) | unit_get_members_mask(u); -+} -+ - CGroupMask unit_get_members_mask(Unit *u) { - assert(u); - -@@ -1508,9 +1516,8 @@ CGroupMask unit_get_members_mask(Unit *u) { - if (u->type == UNIT_SLICE) { - void *v; - Unit *member; -- Iterator i; - -- HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) -+ HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE]) - if (UNIT_DEREF(member->slice) == u) - u->cgroup_members_mask |= unit_get_subtree_mask(member); /* note that this calls ourselves again, for the children */ - } -@@ -1532,7 +1539,7 @@ CGroupMask unit_get_siblings_mask(Unit *u) { - return unit_get_subtree_mask(u); /* we are the top-level slice */ - } - --CGroupMask unit_get_disable_mask(Unit *u) { -+static CGroupMask unit_get_disable_mask(Unit *u) { - CGroupContext *c; - - c = unit_get_cgroup_context(u); -@@ -1557,14 +1564,6 @@ CGroupMask unit_get_ancestor_disable_mask(Unit *u) { - return mask; - } - --CGroupMask unit_get_subtree_mask(Unit *u) { -- -- /* Returns the mask of this subtree, meaning of the group -- * itself and its children. */ -- -- return unit_get_own_mask(u) | unit_get_members_mask(u); --} -- - CGroupMask unit_get_target_mask(Unit *u) { - CGroupMask mask; - -@@ -1629,7 +1628,10 @@ const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask) { - } - - static const char *migrate_callback(CGroupMask mask, void *userdata) { -- return unit_get_realized_cgroup_path(userdata, mask); -+ /* If not realized at all, migrate to root (""). -+ * It may happen if we're upgrading from older version that didn't clean up. -+ */ -+ return strempty(unit_get_realized_cgroup_path(userdata, mask)); - } - - char *unit_default_cgroup_path(const Unit *u) { -@@ -1820,13 +1822,14 @@ int unit_pick_cgroup_path(Unit *u) { - return 0; - } - --static int unit_create_cgroup( -+static int unit_update_cgroup( - Unit *u, - CGroupMask target_mask, - CGroupMask enable_mask, - ManagerState state) { - -- bool created; -+ bool created, is_root_slice; -+ CGroupMask migrate_mask = 0; - int r; - - assert(u); -@@ -1849,7 +1852,9 @@ static int unit_create_cgroup( - (void) unit_watch_cgroup(u); - (void) unit_watch_cgroup_memory(u); - -- /* Preserve enabled controllers in delegated units, adjust others. */ -+ -+ /* For v2 we preserve enabled controllers in delegated units, adjust others, -+ * for v1 we figure out which controller hierarchies need migration. */ - if (created || !u->cgroup_realized || !unit_cgroup_delegate(u)) { - CGroupMask result_mask = 0; - -@@ -1858,39 +1863,32 @@ static int unit_create_cgroup( - if (r < 0) - log_unit_warning_errno(u, r, "Failed to enable/disable controllers on cgroup %s, ignoring: %m", u->cgroup_path); - -- /* If we just turned off a controller, this might release the controller for our parent too, let's -- * enqueue the parent for re-realization in that case again. */ -- if (UNIT_ISSET(u->slice)) { -- CGroupMask turned_off; -- -- turned_off = (u->cgroup_realized ? u->cgroup_enabled_mask & ~result_mask : 0); -- if (turned_off != 0) { -- Unit *parent; -- -- /* Force the parent to propagate the enable mask to the kernel again, by invalidating -- * the controller we just turned off. */ -- -- for (parent = UNIT_DEREF(u->slice); parent; parent = UNIT_DEREF(parent->slice)) -- unit_invalidate_cgroup(parent, turned_off); -- } -- } -- - /* Remember what's actually enabled now */ - u->cgroup_enabled_mask = result_mask; -+ -+ migrate_mask = u->cgroup_realized_mask ^ target_mask; - } - - /* Keep track that this is now realized */ - u->cgroup_realized = true; - u->cgroup_realized_mask = target_mask; - -- if (u->type != UNIT_SLICE && !unit_cgroup_delegate(u)) { -+ /* Migrate processes in controller hierarchies both downwards (enabling) and upwards (disabling). -+ * -+ * Unnecessary controller cgroups are trimmed (after emptied by upward migration). -+ * We perform migration also with whole slices for cases when users don't care about leave -+ * granularity. Since delegated_mask is subset of target mask, we won't trim slice subtree containing -+ * delegated units. -+ */ -+ if (cg_all_unified() == 0) { -+ r = cg_migrate_v1_controllers(u->manager->cgroup_supported, migrate_mask, u->cgroup_path, migrate_callback, u); -+ if (r < 0) -+ log_unit_warning_errno(u, r, "Failed to migrate controller cgroups from %s, ignoring: %m", u->cgroup_path); - -- /* Then, possibly move things over, but not if -- * subgroups may contain processes, which is the case -- * for slice and delegation units. */ -- r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u); -+ is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE); -+ r = cg_trim_v1_controllers(u->manager->cgroup_supported, ~target_mask, u->cgroup_path, !is_root_slice); - if (r < 0) -- log_unit_warning_errno(u, r, "Failed to migrate cgroup from to %s, ignoring: %m", u->cgroup_path); -+ log_unit_warning_errno(u, r, "Failed to delete controller cgroups %s, ignoring: %m", u->cgroup_path); - } - - /* Set attributes */ -@@ -1941,7 +1939,6 @@ static int unit_attach_pid_to_cgroup_via_bus(Unit *u, pid_t pid, const char *suf - int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) { - CGroupMask delegated_mask; - const char *p; -- Iterator i; - void *pidp; - int r, q; - -@@ -1971,7 +1968,7 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) { - delegated_mask = unit_get_delegate_mask(u); - - r = 0; -- SET_FOREACH(pidp, pids, i) { -+ SET_FOREACH(pidp, pids) { - pid_t pid = PTR_TO_PID(pidp); - CGroupController c; - -@@ -2106,13 +2103,13 @@ static bool unit_has_mask_enables_realized( - ((u->cgroup_enabled_mask | enable_mask) & CGROUP_MASK_V2) == (u->cgroup_enabled_mask & CGROUP_MASK_V2); - } - --void unit_add_to_cgroup_realize_queue(Unit *u) { -+static void unit_add_to_cgroup_realize_queue(Unit *u) { - assert(u); - - if (u->in_cgroup_realize_queue) - return; - -- LIST_PREPEND(cgroup_realize_queue, u->manager->cgroup_realize_queue, u); -+ LIST_APPEND(cgroup_realize_queue, u->manager->cgroup_realize_queue, u); - u->in_cgroup_realize_queue = true; - } - -@@ -2153,13 +2150,12 @@ static int unit_realize_cgroup_now_enable(Unit *u, ManagerState state) { - new_target_mask = u->cgroup_realized_mask | target_mask; - new_enable_mask = u->cgroup_enabled_mask | enable_mask; - -- return unit_create_cgroup(u, new_target_mask, new_enable_mask, state); -+ return unit_update_cgroup(u, new_target_mask, new_enable_mask, state); - } - - /* Controllers can only be disabled depth-first, from the leaves of the - * hierarchy upwards to the unit in question. */ - static int unit_realize_cgroup_now_disable(Unit *u, ManagerState state) { -- Iterator i; - Unit *m; - void *v; - -@@ -2168,7 +2164,7 @@ static int unit_realize_cgroup_now_disable(Unit *u, ManagerState state) { - if (u->type != UNIT_SLICE) - return 0; - -- HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE], i) { -+ HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE]) { - CGroupMask target_mask, enable_mask, new_target_mask, new_enable_mask; - int r; - -@@ -2178,7 +2174,7 @@ static int unit_realize_cgroup_now_disable(Unit *u, ManagerState state) { - /* The cgroup for this unit might not actually be fully - * realised yet, in which case it isn't holding any controllers - * open anyway. */ -- if (!m->cgroup_path) -+ if (!m->cgroup_realized) - continue; - - /* We must disable those below us first in order to release the -@@ -2197,7 +2193,7 @@ static int unit_realize_cgroup_now_disable(Unit *u, ManagerState state) { - new_target_mask = m->cgroup_realized_mask & target_mask; - new_enable_mask = m->cgroup_enabled_mask & enable_mask; - -- r = unit_create_cgroup(m, new_target_mask, new_enable_mask, state); -+ r = unit_update_cgroup(m, new_target_mask, new_enable_mask, state); - if (r < 0) - return r; - } -@@ -2276,7 +2272,7 @@ static int unit_realize_cgroup_now(Unit *u, ManagerState state) { - } - - /* Now actually deal with the cgroup we were trying to realise and set attributes */ -- r = unit_create_cgroup(u, target_mask, enable_mask, state); -+ r = unit_update_cgroup(u, target_mask, enable_mask, state); - if (r < 0) - return r; - -@@ -2314,29 +2310,33 @@ unsigned manager_dispatch_cgroup_realize_queue(Manager *m) { - return n; - } - --static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) { -- Unit *slice; -+void unit_add_family_to_cgroup_realize_queue(Unit *u) { -+ assert(u); -+ assert(u->type == UNIT_SLICE); - -- /* This adds the siblings of the specified unit and the siblings of all parent units to the cgroup -- * queue. (But neither the specified unit itself nor the parents.) -+ /* Family of a unit for is defined as (immediate) children of the unit and immediate children of all -+ * its ancestors. -+ * -+ * Ideally we would enqueue ancestor path only (bottom up). However, on cgroup-v1 scheduling becomes -+ * very weird if two units that own processes reside in the same slice, but one is realized in the -+ * "cpu" hierarchy and one is not (for example because one has CPUWeight= set and the other does -+ * not), because that means individual processes need to be scheduled against whole cgroups. Let's -+ * avoid this asymmetry by always ensuring that siblings of a unit are always realized in their v1 -+ * controller hierarchies too (if unit requires the controller to be realized). - * -- * Propagation of realization "side-ways" (i.e. towards siblings) is relevant on cgroup-v1 where -- * scheduling becomes very weird if two units that own processes reside in the same slice, but one is -- * realized in the "cpu" hierarchy and one is not (for example because one has CPUWeight= set and the -- * other does not), because that means individual processes need to be scheduled against whole -- * cgroups. Let's avoid this asymmetry by always ensuring that units below a slice that are realized -- * at all are always realized in *all* their hierarchies, and it is sufficient for a unit's sibling -- * to be realized for the unit itself to be realized too. */ -- -- while ((slice = UNIT_DEREF(u->slice))) { -- Iterator i; -+ * The function must invalidate cgroup_members_mask of all ancestors in order to calculate up to date -+ * masks. */ -+ -+ do { - Unit *m; - void *v; - -- HASHMAP_FOREACH_KEY(v, m, slice->dependencies[UNIT_BEFORE], i) { -+ /* Children of u likely changed when we're called */ -+ u->cgroup_members_mask_valid = false; - -+ HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE]) { - /* Skip units that have a dependency on the slice but aren't actually in it. */ -- if (UNIT_DEREF(m->slice) != slice) -+ if (UNIT_DEREF(m->slice) != u) - continue; - - /* No point in doing cgroup application for units without active processes. */ -@@ -2358,8 +2358,9 @@ static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) { - unit_add_to_cgroup_realize_queue(m); - } - -- u = slice; -- } -+ /* Parent comes after children */ -+ unit_add_to_cgroup_realize_queue(u); -+ } while ((u = UNIT_DEREF(u->slice))); - } - - int unit_realize_cgroup(Unit *u) { -@@ -2368,19 +2369,17 @@ int unit_realize_cgroup(Unit *u) { - if (!UNIT_HAS_CGROUP_CONTEXT(u)) - return 0; - -- /* So, here's the deal: when realizing the cgroups for this -- * unit, we need to first create all parents, but there's more -- * actually: for the weight-based controllers we also need to -- * make sure that all our siblings (i.e. units that are in the -- * same slice as we are) have cgroups, too. Otherwise, things -- * would become very uneven as each of their processes would -- * get as much resources as all our group together. This call -- * will synchronously create the parent cgroups, but will -- * defer work on the siblings to the next event loop -- * iteration. */ -+ /* So, here's the deal: when realizing the cgroups for this unit, we need to first create all -+ * parents, but there's more actually: for the weight-based controllers we also need to make sure -+ * that all our siblings (i.e. units that are in the same slice as we are) have cgroups, too. On the -+ * other hand, when a controller is removed from realized set, it may become unnecessary in siblings -+ * and ancestors and they should be (de)realized too. -+ * -+ * This call will defer work on the siblings and derealized ancestors to the next event loop -+ * iteration and synchronously creates the parent cgroups (unit_realize_cgroup_now). */ - -- /* Add all sibling slices to the cgroup queue. */ -- unit_add_siblings_to_cgroup_realize_queue(u); -+ if (UNIT_ISSET(u->slice)) -+ unit_add_family_to_cgroup_realize_queue(UNIT_DEREF(u->slice)); - - /* And realize this one now (and apply the values) */ - return unit_realize_cgroup_now(u, manager_state(u->manager)); -@@ -2436,7 +2435,7 @@ void unit_prune_cgroup(Unit *u) { - * the containing slice is stopped. So even if we failed now, this unit shouldn't assume - * that the cgroup is still realized the next time it is started. Do not return early - * on error, continue cleanup. */ -- log_unit_full(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path); -+ log_unit_full_errno(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path); - - if (is_root_slice) - return; -@@ -3524,10 +3523,9 @@ void unit_invalidate_cgroup_bpf(Unit *u) { - * list of our children includes our own. */ - if (u->type == UNIT_SLICE) { - Unit *member; -- Iterator i; - void *v; - -- HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) -+ HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE]) - if (UNIT_DEREF(member->slice) == u) - unit_invalidate_cgroup_bpf(member); - } -@@ -3549,12 +3547,11 @@ bool unit_cgroup_delegate(Unit *u) { - } - - void manager_invalidate_startup_units(Manager *m) { -- Iterator i; - Unit *u; - - assert(m); - -- SET_FOREACH(u, m->startup_units, i) -+ SET_FOREACH(u, m->startup_units) - unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO); - } - -@@ -3605,6 +3602,9 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action) { - assert(u); - assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW)); - -+ if (!cg_freezer_supported()) -+ return 0; -+ - if (!u->cgroup_realized) - return -EBUSY; - -diff --git a/src/core/cgroup.h b/src/core/cgroup.h -index 52d028e..9ac5c8b 100644 ---- a/src/core/cgroup.h -+++ b/src/core/cgroup.h -@@ -203,8 +203,6 @@ CGroupMask unit_get_own_mask(Unit *u); - CGroupMask unit_get_delegate_mask(Unit *u); - CGroupMask unit_get_members_mask(Unit *u); - CGroupMask unit_get_siblings_mask(Unit *u); --CGroupMask unit_get_subtree_mask(Unit *u); --CGroupMask unit_get_disable_mask(Unit *u); - CGroupMask unit_get_ancestor_disable_mask(Unit *u); - - CGroupMask unit_get_target_mask(Unit *u); -@@ -212,7 +210,7 @@ CGroupMask unit_get_enable_mask(Unit *u); - - void unit_invalidate_cgroup_members_masks(Unit *u); - --void unit_add_to_cgroup_realize_queue(Unit *u); -+void unit_add_family_to_cgroup_realize_queue(Unit *u); - - const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask); - char *unit_default_cgroup_path(const Unit *u); -diff --git a/src/core/core-varlink.c b/src/core/core-varlink.c -index eca27f4..4bb262b 100644 ---- a/src/core/core-varlink.c -+++ b/src/core/core-varlink.c -@@ -79,10 +79,9 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var - else if (p.user_name) - r = dynamic_user_lookup_name(m, p.user_name, &found_uid); - else { -- Iterator i; - DynamicUser *d; - -- HASHMAP_FOREACH(d, m->dynamic_users, i) { -+ HASHMAP_FOREACH(d, m->dynamic_users) { - r = dynamic_user_current(d, &uid); - if (r == -EAGAIN) /* not realized yet? */ - continue; -@@ -136,6 +135,7 @@ static int build_group_json(const char *group_name, gid_t gid, JsonVariant **ret - return json_build(ret, JSON_BUILD_OBJECT( - JSON_BUILD_PAIR("record", JSON_BUILD_OBJECT( - JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(group_name)), -+ JSON_BUILD_PAIR("description", JSON_BUILD_STRING("Dynamic Group")), - JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(gid)), - JSON_BUILD_PAIR("service", JSON_BUILD_STRING("io.systemd.DynamicUser")), - JSON_BUILD_PAIR("disposition", JSON_BUILD_STRING("dynamic")))))); -@@ -188,9 +188,8 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va - r = dynamic_user_lookup_name(m, p.group_name, (uid_t*) &found_gid); - else { - DynamicUser *d; -- Iterator i; - -- HASHMAP_FOREACH(d, m->dynamic_users, i) { -+ HASHMAP_FOREACH(d, m->dynamic_users) { - uid_t uid; - - r = dynamic_user_current(d, &uid); -@@ -290,7 +289,7 @@ int manager_varlink_init(Manager *m) { - return log_error_errno(r, "Failed to register varlink methods: %m"); - - if (!MANAGER_IS_TEST_RUN(m)) { -- (void) mkdir_p("/run/systemd/userdb", 0755); -+ (void) mkdir_p_label("/run/systemd/userdb", 0755); - - r = varlink_server_listen_address(s, "/run/systemd/userdb/io.systemd.DynamicUser", 0666); - if (r < 0) -diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c -index 50f7ada..dfcc2ee 100644 ---- a/src/core/dbus-execute.c -+++ b/src/core/dbus-execute.c -@@ -47,6 +47,8 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInp - static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode); - static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode); - static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode); -+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_proc, protect_proc, ProtectProc); -+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_proc_subset, proc_subset, ProcSubset); - static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_home, protect_home, ProtectHome); - static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system, protect_system, ProtectSystem); - static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality, personality, unsigned long); -@@ -358,7 +360,6 @@ static int property_get_syscall_filter( - int r; - - #if HAVE_SECCOMP -- Iterator i; - void *id, *val; - #endif - -@@ -375,7 +376,7 @@ static int property_get_syscall_filter( - return r; - - #if HAVE_SECCOMP -- HASHMAP_FOREACH_KEY(val, id, c->syscall_filter, i) { -+ HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) { - _cleanup_free_ char *name = NULL; - const char *e = NULL; - char *s; -@@ -386,7 +387,7 @@ static int property_get_syscall_filter( - continue; - - if (num >= 0) { -- e = errno_to_name(num); -+ e = seccomp_errno_or_action_to_string(num); - if (e) { - s = strjoin(name, ":", e); - if (!s) -@@ -414,6 +415,58 @@ static int property_get_syscall_filter( - return sd_bus_message_close_container(reply); - } - -+static int property_get_syscall_log( -+ sd_bus *bus, -+ const char *path, -+ const char *interface, -+ const char *property, -+ sd_bus_message *reply, -+ void *userdata, -+ sd_bus_error *error) { -+ -+ ExecContext *c = userdata; -+ _cleanup_strv_free_ char **l = NULL; -+ int r; -+ -+#if HAVE_SECCOMP -+ void *id, *val; -+#endif -+ -+ assert(bus); -+ assert(reply); -+ assert(c); -+ -+ r = sd_bus_message_open_container(reply, 'r', "bas"); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_append(reply, "b", c->syscall_log_allow_list); -+ if (r < 0) -+ return r; -+ -+#if HAVE_SECCOMP -+ HASHMAP_FOREACH_KEY(val, id, c->syscall_log) { -+ char *name = NULL; -+ -+ name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1); -+ if (!name) -+ continue; -+ -+ r = strv_consume(&l, name); -+ if (r < 0) -+ return r; -+ } -+#endif -+ -+ strv_sort(l); -+ -+ r = sd_bus_message_append_strv(reply, l); -+ if (r < 0) -+ return r; -+ -+ return sd_bus_message_close_container(reply); -+} -+ - static int property_get_syscall_archs( - sd_bus *bus, - const char *path, -@@ -428,7 +481,6 @@ static int property_get_syscall_archs( - int r; - - #if HAVE_SECCOMP -- Iterator i; - void *id; - #endif - -@@ -437,7 +489,7 @@ static int property_get_syscall_archs( - assert(c); - - #if HAVE_SECCOMP -- SET_FOREACH(id, c->syscall_archs, i) { -+ SET_FOREACH(id, c->syscall_archs) { - const char *name; - - name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1); -@@ -524,7 +576,6 @@ static int property_get_address_families( - - ExecContext *c = userdata; - _cleanup_strv_free_ char **l = NULL; -- Iterator i; - void *af; - int r; - -@@ -540,7 +591,7 @@ static int property_get_address_families( - if (r < 0) - return r; - -- SET_FOREACH(af, c->address_families, i) { -+ SET_FOREACH(af, c->address_families) { - const char *name; - - name = af_to_name(PTR_TO_INT(af)); -@@ -746,6 +797,81 @@ static int property_get_log_extra_fields( - return sd_bus_message_close_container(reply); - } - -+static int property_get_set_credential( -+ sd_bus *bus, -+ const char *path, -+ const char *interface, -+ const char *property, -+ sd_bus_message *reply, -+ void *userdata, -+ sd_bus_error *error) { -+ -+ ExecContext *c = userdata; -+ ExecSetCredential *sc; -+ int r; -+ -+ assert(bus); -+ assert(c); -+ assert(property); -+ assert(reply); -+ -+ r = sd_bus_message_open_container(reply, 'a', "(say)"); -+ if (r < 0) -+ return r; -+ -+ HASHMAP_FOREACH(sc, c->set_credentials) { -+ -+ r = sd_bus_message_open_container(reply, 'r', "say"); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_append(reply, "s", sc->id); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_append_array(reply, 'y', sc->data, sc->size); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_close_container(reply); -+ if (r < 0) -+ return r; -+ } -+ -+ return sd_bus_message_close_container(reply); -+} -+ -+static int property_get_load_credential( -+ sd_bus *bus, -+ const char *path, -+ const char *interface, -+ const char *property, -+ sd_bus_message *reply, -+ void *userdata, -+ sd_bus_error *error) { -+ -+ ExecContext *c = userdata; -+ char **i, **j; -+ int r; -+ -+ assert(bus); -+ assert(c); -+ assert(property); -+ assert(reply); -+ -+ r = sd_bus_message_open_container(reply, 'a', "(ss)"); -+ if (r < 0) -+ return r; -+ -+ STRV_FOREACH_PAIR(i, j, c->load_credentials) { -+ r = sd_bus_message_append(reply, "(ss)", *i, *j); -+ if (r < 0) -+ return r; -+ } -+ -+ return sd_bus_message_close_container(reply); -+} -+ - static int property_get_root_hash( - sd_bus *bus, - const char *path, -@@ -784,6 +910,94 @@ static int property_get_root_hash_sig( - return sd_bus_message_append_array(reply, 'y', c->root_hash_sig, c->root_hash_sig_size); - } - -+static int property_get_root_image_options( -+ sd_bus *bus, -+ const char *path, -+ const char *interface, -+ const char *property, -+ sd_bus_message *reply, -+ void *userdata, -+ sd_bus_error *error) { -+ -+ ExecContext *c = userdata; -+ MountOptions *m; -+ int r; -+ -+ assert(bus); -+ assert(c); -+ assert(property); -+ assert(reply); -+ -+ r = sd_bus_message_open_container(reply, 'a', "(ss)"); -+ if (r < 0) -+ return r; -+ -+ LIST_FOREACH(mount_options, m, c->root_image_options) { -+ r = sd_bus_message_append(reply, "(ss)", -+ partition_designator_to_string(m->partition_designator), -+ m->options); -+ if (r < 0) -+ return r; -+ } -+ -+ return sd_bus_message_close_container(reply); -+} -+ -+static int property_get_mount_images( -+ sd_bus *bus, -+ const char *path, -+ const char *interface, -+ const char *property, -+ sd_bus_message *reply, -+ void *userdata, -+ sd_bus_error *error) { -+ -+ ExecContext *c = userdata; -+ int r; -+ -+ assert(bus); -+ assert(c); -+ assert(property); -+ assert(reply); -+ -+ r = sd_bus_message_open_container(reply, 'a', "(ssba(ss))"); -+ if (r < 0) -+ return r; -+ -+ for (size_t i = 0; i < c->n_mount_images; i++) { -+ MountOptions *m; -+ -+ r = sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "ssba(ss)"); -+ if (r < 0) -+ return r; -+ r = sd_bus_message_append( -+ reply, "ssb", -+ c->mount_images[i].source, -+ c->mount_images[i].destination, -+ c->mount_images[i].ignore_enoent); -+ if (r < 0) -+ return r; -+ r = sd_bus_message_open_container(reply, 'a', "(ss)"); -+ if (r < 0) -+ return r; -+ LIST_FOREACH(mount_options, m, c->mount_images[i].mount_options) { -+ r = sd_bus_message_append(reply, "(ss)", -+ partition_designator_to_string(m->partition_designator), -+ m->options); -+ if (r < 0) -+ return r; -+ } -+ r = sd_bus_message_close_container(reply); -+ if (r < 0) -+ return r; -+ r = sd_bus_message_close_container(reply); -+ if (r < 0) -+ return r; -+ } -+ -+ return sd_bus_message_close_container(reply); -+} -+ - const sd_bus_vtable bus_exec_vtable[] = { - SD_BUS_VTABLE_START(0), - SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST), -@@ -826,11 +1040,13 @@ const sd_bus_vtable bus_exec_vtable[] = { - SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST), -+ SD_BUS_PROPERTY("RootImageOptions", "a(ss)", property_get_root_image_options, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RootHash", "ay", property_get_root_hash, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RootHashPath", "s", NULL, offsetof(ExecContext, root_hash_path), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RootHashSignature", "ay", property_get_root_hash_sig, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RootHashSignaturePath", "s", NULL, offsetof(ExecContext, root_hash_sig_path), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RootVerity", "s", NULL, offsetof(ExecContext, root_verity), SD_BUS_VTABLE_PROPERTY_CONST), -+ SD_BUS_PROPERTY("MountImages", "a(ssba(ss))", property_get_mount_images, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST), -@@ -873,6 +1089,8 @@ const sd_bus_vtable bus_exec_vtable[] = { - SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST), -+ SD_BUS_PROPERTY("SetCredential", "a(say)", property_get_set_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST), -+ SD_BUS_PROPERTY("LoadCredential", "a(ss)", property_get_load_credential, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST), -@@ -902,6 +1120,7 @@ const sd_bus_vtable bus_exec_vtable[] = { - SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST), -+ SD_BUS_PROPERTY("SystemCallLog", "(bas)", property_get_syscall_log, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST), -@@ -926,6 +1145,8 @@ const sd_bus_vtable bus_exec_vtable[] = { - SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST), -+ SD_BUS_PROPERTY("ProtectProc", "s", property_get_protect_proc, offsetof(ExecContext, protect_proc), SD_BUS_VTABLE_PROPERTY_CONST), -+ SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset, offsetof(ExecContext, proc_subset), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST), - -@@ -1256,7 +1477,7 @@ static const char* mount_propagation_flags_to_string_with_check(unsigned long n) - static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT); - static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid); - #if HAVE_SECCOMP --static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, errno_is_valid); -+static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, seccomp_errno_or_action_is_valid); - #endif - static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string); - static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string); -@@ -1264,6 +1485,8 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_fr - static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, protect_system_from_string); - static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, protect_home_from_string); - static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string); -+static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_proc, ProtectProc, protect_proc_from_string); -+static BUS_DEFINE_SET_TRANSIENT_PARSE(proc_subset, ProcSubset, proc_subset_from_string); - static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string); - static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality); - static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check); -@@ -1271,6 +1494,74 @@ static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint6 - static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flags_to_string); - static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check); - -+/* ret_format_str is an accumulator, so if it has any pre-existing content, new options will be appended to it */ -+static int read_mount_options(sd_bus_message *message, sd_bus_error *error, MountOptions **ret_options, char **ret_format_str, const char *separator) { -+ _cleanup_(mount_options_free_allp) MountOptions *options = NULL; -+ _cleanup_free_ char *format_str = NULL; -+ const char *mount_options, *partition; -+ int r; -+ -+ assert(message); -+ assert(ret_options); -+ assert(ret_format_str); -+ assert(separator); -+ -+ r = sd_bus_message_enter_container(message, 'a', "(ss)"); -+ if (r < 0) -+ return r; -+ -+ while ((r = sd_bus_message_read(message, "(ss)", &partition, &mount_options)) > 0) { -+ _cleanup_free_ char *previous = NULL, *escaped = NULL; -+ _cleanup_free_ MountOptions *o = NULL; -+ PartitionDesignator partition_designator; -+ -+ if (chars_intersect(mount_options, WHITESPACE)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, -+ "Invalid mount options string, contains whitespace character(s): %s", mount_options); -+ -+ partition_designator = partition_designator_from_string(partition); -+ if (partition_designator < 0) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid partition name %s", partition); -+ -+ /* Need to store them in the unit with the escapes, so that they can be parsed again */ -+ escaped = shell_escape(mount_options, ":"); -+ if (!escaped) -+ return -ENOMEM; -+ -+ previous = TAKE_PTR(format_str); -+ format_str = strjoin(previous, previous ? separator : "", partition, ":", escaped); -+ if (!format_str) -+ return -ENOMEM; -+ -+ o = new(MountOptions, 1); -+ if (!o) -+ return -ENOMEM; -+ *o = (MountOptions) { -+ .partition_designator = partition_designator, -+ .options = strdup(mount_options), -+ }; -+ if (!o->options) -+ return -ENOMEM; -+ LIST_APPEND(mount_options, options, TAKE_PTR(o)); -+ } -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_exit_container(message); -+ if (r < 0) -+ return r; -+ -+ if (!LIST_IS_EMPTY(options)) { -+ char *final = strjoin(*ret_format_str, !isempty(*ret_format_str) ? separator : "", format_str); -+ if (!final) -+ return -ENOMEM; -+ free_and_replace(*ret_format_str, final); -+ LIST_JOIN(mount_options, *ret_options, options); -+ } -+ -+ return 0; -+} -+ - int bus_exec_context_set_transient_property( - Unit *u, - ExecContext *c, -@@ -1301,6 +1592,31 @@ int bus_exec_context_set_transient_property( - if (streq(name, "RootImage")) - return bus_set_transient_path(u, name, &c->root_image, message, flags, error); - -+ if (streq(name, "RootImageOptions")) { -+ _cleanup_(mount_options_free_allp) MountOptions *options = NULL; -+ _cleanup_free_ char *format_str = NULL; -+ -+ r = read_mount_options(message, error, &options, &format_str, " "); -+ if (r < 0) -+ return r; -+ -+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { -+ if (LIST_IS_EMPTY(options)) { -+ c->root_image_options = mount_options_free_all(c->root_image_options); -+ unit_write_settingf(u, flags, name, "%s=", name); -+ } else { -+ LIST_JOIN(mount_options, c->root_image_options, options); -+ unit_write_settingf( -+ u, flags|UNIT_ESCAPE_SPECIFIERS, name, -+ "%s=%s", -+ name, -+ format_str); -+ } -+ } -+ -+ return 1; -+ } -+ - if (streq(name, "RootHash")) { - const void *roothash_decoded; - size_t roothash_decoded_size; -@@ -1523,6 +1839,12 @@ int bus_exec_context_set_transient_property( - if (streq(name, "KeyringMode")) - return bus_set_transient_keyring_mode(u, name, &c->keyring_mode, message, flags, error); - -+ if (streq(name, "ProtectProc")) -+ return bus_set_transient_protect_proc(u, name, &c->protect_proc, message, flags, error); -+ -+ if (streq(name, "ProcSubset")) -+ return bus_set_transient_proc_subset(u, name, &c->proc_subset, message, flags, error); -+ - if (streq(name, "RuntimeDirectoryPreserve")) - return bus_set_transient_preserve_mode(u, name, &c->runtime_directory_preserve_mode, message, flags, error); - -@@ -1599,6 +1921,146 @@ int bus_exec_context_set_transient_property( - - return 1; - -+ } else if (streq(name, "SetCredential")) { -+ bool isempty = true; -+ -+ r = sd_bus_message_enter_container(message, 'a', "(say)"); -+ if (r < 0) -+ return r; -+ -+ for (;;) { -+ const char *id; -+ const void *p; -+ size_t sz; -+ -+ r = sd_bus_message_enter_container(message, 'r', "say"); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; -+ -+ r = sd_bus_message_read(message, "s", &id); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_read_array(message, 'y', &p, &sz); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_exit_container(message); -+ if (r < 0) -+ return r; -+ -+ if (!credential_name_valid(id)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Credential ID is invalid: %s", id); -+ -+ isempty = false; -+ -+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { -+ _cleanup_free_ char *a = NULL, *b = NULL; -+ _cleanup_free_ void *copy = NULL; -+ ExecSetCredential *old; -+ -+ copy = memdup(p, sz); -+ if (!copy) -+ return -ENOMEM; -+ -+ old = hashmap_get(c->set_credentials, id); -+ if (old) { -+ free_and_replace(old->data, copy); -+ old->size = sz; -+ } else { -+ _cleanup_(exec_set_credential_freep) ExecSetCredential *sc = NULL; -+ -+ sc = new0(ExecSetCredential, 1); -+ if (!sc) -+ return -ENOMEM; -+ -+ sc->id = strdup(id); -+ if (!sc->id) -+ return -ENOMEM; -+ -+ sc->data = TAKE_PTR(copy); -+ sc->size = sz; -+ -+ r = hashmap_ensure_allocated(&c->set_credentials, &exec_set_credential_hash_ops); -+ if (r < 0) -+ return r; -+ -+ r = hashmap_put(c->set_credentials, sc->id, sc); -+ if (r < 0) -+ return r; -+ -+ TAKE_PTR(sc); -+ } -+ -+ a = specifier_escape(id); -+ if (!a) -+ return -ENOMEM; -+ -+ b = cescape_length(p, sz); -+ if (!b) -+ return -ENOMEM; -+ -+ (void) unit_write_settingf(u, flags, name, "%s=%s:%s", name, a, b); -+ } -+ } -+ -+ r = sd_bus_message_exit_container(message); -+ if (r < 0) -+ return r; -+ -+ if (!UNIT_WRITE_FLAGS_NOOP(flags) && isempty) { -+ c->set_credentials = hashmap_free(c->set_credentials); -+ (void) unit_write_settingf(u, flags, name, "%s=", name); -+ } -+ -+ return 1; -+ -+ } else if (streq(name, "LoadCredential")) { -+ bool isempty = true; -+ -+ r = sd_bus_message_enter_container(message, 'a', "(ss)"); -+ if (r < 0) -+ return r; -+ -+ for (;;) { -+ const char *id, *source; -+ -+ r = sd_bus_message_read(message, "(ss)", &id, &source); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; -+ -+ if (!credential_name_valid(id)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Credential ID is invalid: %s", id); -+ -+ if (!(path_is_absolute(source) ? path_is_normalized(source) : credential_name_valid(source))) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Credential source is invalid: %s", source); -+ -+ isempty = false; -+ -+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { -+ r = strv_extend_strv(&c->load_credentials, STRV_MAKE(id, source), /* filter_duplicates = */ false); -+ if (r < 0) -+ return r; -+ -+ (void) unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s:%s", name, id, source); -+ } -+ } -+ -+ r = sd_bus_message_exit_container(message); -+ if (r < 0) -+ return r; -+ -+ if (!UNIT_WRITE_FLAGS_NOOP(flags) && isempty) { -+ c->load_credentials = strv_free(c->load_credentials); -+ (void) unit_write_settingf(u, flags, name, "%s=", name); -+ } -+ -+ return 1; -+ - } else if (streq(name, "SyslogLevel")) { - int32_t level; - -@@ -1821,6 +2283,76 @@ int bus_exec_context_set_transient_property( - - return 1; - -+ } else if (streq(name, "SystemCallLog")) { -+ int allow_list; -+ _cleanup_strv_free_ char **l = NULL; -+ -+ r = sd_bus_message_enter_container(message, 'r', "bas"); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_read(message, "b", &allow_list); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_read_strv(message, &l); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_exit_container(message); -+ if (r < 0) -+ return r; -+ -+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { -+ _cleanup_free_ char *joined = NULL; -+ SeccompParseFlags invert_flag = allow_list ? 0 : SECCOMP_PARSE_INVERT; -+ char **s; -+ -+ if (strv_isempty(l)) { -+ c->syscall_log_allow_list = false; -+ c->syscall_log = hashmap_free(c->syscall_log); -+ -+ unit_write_settingf(u, flags, name, "SystemCallLog="); -+ return 1; -+ } -+ -+ if (!c->syscall_log) { -+ c->syscall_log = hashmap_new(NULL); -+ if (!c->syscall_log) -+ return log_oom(); -+ -+ c->syscall_log_allow_list = allow_list; -+ } -+ -+ STRV_FOREACH(s, l) { -+ _cleanup_free_ char *n = NULL; -+ int e; -+ -+ r = parse_syscall_and_errno(*s, &n, &e); -+ if (r < 0) -+ return r; -+ -+ r = seccomp_parse_syscall_filter(n, -+ 0, /* errno not used */ -+ c->syscall_log, -+ SECCOMP_PARSE_LOG | SECCOMP_PARSE_PERMISSIVE | -+ invert_flag | -+ (c->syscall_log_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0), -+ u->id, -+ NULL, 0); -+ if (r < 0) -+ return r; -+ } -+ -+ joined = strv_join(l, " "); -+ if (!joined) -+ return -ENOMEM; -+ -+ unit_write_settingf(u, flags, name, "SystemCallLog=%s%s", allow_list ? "" : "~", joined); -+ } -+ -+ return 1; -+ - } else if (streq(name, "SystemCallArchitectures")) { - _cleanup_strv_free_ char **l = NULL; - -@@ -2808,6 +3340,105 @@ int bus_exec_context_set_transient_property( - return 1; - } - -+ } else if (streq(name, "MountImages")) { -+ _cleanup_free_ char *format_str = NULL; -+ MountImage *mount_images = NULL; -+ size_t n_mount_images = 0; -+ char *source, *destination; -+ int permissive; -+ -+ r = sd_bus_message_enter_container(message, 'a', "(ssba(ss))"); -+ if (r < 0) -+ return r; -+ -+ for (;;) { -+ _cleanup_(mount_options_free_allp) MountOptions *options = NULL; -+ _cleanup_free_ char *source_escaped = NULL, *destination_escaped = NULL; -+ char *tuple; -+ -+ r = sd_bus_message_enter_container(message, 'r', "ssba(ss)"); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_read(message, "ssb", &source, &destination, &permissive); -+ if (r <= 0) -+ break; -+ -+ if (!path_is_absolute(source)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source); -+ if (!path_is_normalized(source)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not normalized.", source); -+ if (!path_is_absolute(destination)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination); -+ if (!path_is_normalized(destination)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not normalized.", destination); -+ -+ /* Need to store them in the unit with the escapes, so that they can be parsed again */ -+ source_escaped = shell_escape(source, ":"); -+ if (!source_escaped) -+ return -ENOMEM; -+ destination_escaped = shell_escape(destination, ":"); -+ if (!destination_escaped) -+ return -ENOMEM; -+ -+ tuple = strjoin(format_str, -+ format_str ? " " : "", -+ permissive ? "-" : "", -+ source_escaped, -+ ":", -+ destination_escaped); -+ if (!tuple) -+ return -ENOMEM; -+ free_and_replace(format_str, tuple); -+ -+ r = read_mount_options(message, error, &options, &format_str, ":"); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_exit_container(message); -+ if (r < 0) -+ return r; -+ -+ r = mount_image_add(&mount_images, &n_mount_images, -+ &(MountImage) { -+ .source = source, -+ .destination = destination, -+ .mount_options = options, -+ .ignore_enoent = permissive, -+ }); -+ if (r < 0) -+ return r; -+ } -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_exit_container(message); -+ if (r < 0) -+ return r; -+ -+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) { -+ if (n_mount_images == 0) { -+ c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images); -+ -+ unit_write_settingf(u, flags, name, "%s=", name); -+ } else { -+ for (size_t i = 0; i < n_mount_images; ++i) { -+ r = mount_image_add(&c->mount_images, &c->n_mount_images, &mount_images[i]); -+ if (r < 0) -+ return r; -+ } -+ -+ unit_write_settingf(u, flags|UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, -+ name, -+ "%s=%s", -+ name, -+ format_str); -+ } -+ } -+ -+ mount_images = mount_image_free_many(mount_images, &n_mount_images); -+ -+ return 1; - } - - return 0; -diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c -index 33e4128..06443a4 100644 ---- a/src/core/dbus-job.c -+++ b/src/core/dbus-job.c -@@ -164,14 +164,13 @@ static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - unsigned k = 0; -- Iterator i; - Job *j; - - l = new0(char*, hashmap_size(m->jobs)+1); - if (!l) - return -ENOMEM; - -- HASHMAP_FOREACH(j, m->jobs, i) { -+ HASHMAP_FOREACH(j, m->jobs) { - l[k] = job_dbus_path(j); - if (!l[k]) - return -ENOMEM; -@@ -340,7 +339,7 @@ static int bus_job_allocate_bus_track(Job *j) { - } - - int bus_job_coldplug_bus_track(Job *j) { -- int r = 0; -+ int r; - _cleanup_strv_free_ char **deserialized_clients = NULL; - - assert(j); -diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c -index 07e139c..0ac87b5 100644 ---- a/src/core/dbus-manager.c -+++ b/src/core/dbus-manager.c -@@ -1058,7 +1058,6 @@ static int list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_e - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; - const char *k; -- Iterator i; - Unit *u; - int r; - -@@ -1079,7 +1078,7 @@ static int list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_e - if (r < 0) - return r; - -- HASHMAP_FOREACH_KEY(u, k, m->units, i) { -+ HASHMAP_FOREACH_KEY(u, k, m->units) { - if (k != u->id) - continue; - -@@ -1139,7 +1138,6 @@ static int method_list_units_by_patterns(sd_bus_message *message, void *userdata - static int method_list_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; -- Iterator i; - Job *j; - int r; - -@@ -1160,7 +1158,7 @@ static int method_list_jobs(sd_bus_message *message, void *userdata, sd_bus_erro - if (r < 0) - return r; - -- HASHMAP_FOREACH(j, m->jobs, i) { -+ HASHMAP_FOREACH(j, m->jobs) { - _cleanup_free_ char *unit_path = NULL, *job_path = NULL; - - job_path = job_dbus_path(j); -@@ -1759,7 +1757,6 @@ static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_ - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; - DynamicUser *d; -- Iterator i; - int r; - - assert(message); -@@ -1778,7 +1775,7 @@ static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_ - if (r < 0) - return r; - -- HASHMAP_FOREACH(d, m->dynamic_users, i) { -+ HASHMAP_FOREACH(d, m->dynamic_users) { - uid_t uid; - - r = dynamic_user_current(d, &uid); -@@ -1804,7 +1801,6 @@ static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, - Manager *m = userdata; - UnitFileList *item; - Hashmap *h; -- Iterator i; - int r; - - assert(message); -@@ -1832,7 +1828,7 @@ static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, - if (r < 0) - goto fail; - -- HASHMAP_FOREACH(item, h, i) { -+ HASHMAP_FOREACH(item, h) { - - r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state)); - if (r < 0) -@@ -2083,7 +2079,7 @@ static int method_enable_unit_files_generic( - UnitFileChange *changes = NULL; - size_t n_changes = 0; - UnitFileFlags flags; -- int runtime, force, r; -+ int r; - - assert(message); - assert(m); -@@ -2092,11 +2088,23 @@ static int method_enable_unit_files_generic( - if (r < 0) - return r; - -- r = sd_bus_message_read(message, "bb", &runtime, &force); -- if (r < 0) -- return r; -+ if (sd_bus_message_is_method_call(message, NULL, "EnableUnitFilesWithFlags")) { -+ uint64_t raw_flags; - -- flags = unit_file_bools_to_flags(runtime, force); -+ r = sd_bus_message_read(message, "t", &raw_flags); -+ if (r < 0) -+ return r; -+ if ((raw_flags & ~_UNIT_FILE_FLAGS_MASK_PUBLIC) != 0) -+ return -EINVAL; -+ flags = raw_flags; -+ } else { -+ int runtime, force; -+ -+ r = sd_bus_message_read(message, "bb", &runtime, &force); -+ if (r < 0) -+ return r; -+ flags = unit_file_bools_to_flags(runtime, force); -+ } - - r = bus_verify_manage_unit_files_async(m, message, error); - if (r < 0) -@@ -2111,6 +2119,10 @@ static int method_enable_unit_files_generic( - return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes, error); - } - -+static int method_enable_unit_files_with_flags(sd_bus_message *message, void *userdata, sd_bus_error *error) { -+ return method_enable_unit_files_generic(message, userdata, unit_file_enable, true, error); -+} -+ - static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { - return method_enable_unit_files_generic(message, userdata, unit_file_enable, true, error); - } -@@ -2188,8 +2200,9 @@ static int method_disable_unit_files_generic( - - _cleanup_strv_free_ char **l = NULL; - UnitFileChange *changes = NULL; -+ UnitFileFlags flags; - size_t n_changes = 0; -- int r, runtime; -+ int r; - - assert(message); - assert(m); -@@ -2198,9 +2211,24 @@ static int method_disable_unit_files_generic( - if (r < 0) - return r; - -- r = sd_bus_message_read(message, "b", &runtime); -- if (r < 0) -- return r; -+ if (sd_bus_message_is_method_call(message, NULL, "DisableUnitFilesWithFlags")) { -+ uint64_t raw_flags; -+ -+ r = sd_bus_message_read(message, "t", &raw_flags); -+ if (r < 0) -+ return r; -+ if ((raw_flags & ~_UNIT_FILE_FLAGS_MASK_PUBLIC) != 0 || -+ FLAGS_SET(raw_flags, UNIT_FILE_FORCE)) -+ return -EINVAL; -+ flags = raw_flags; -+ } else { -+ int runtime; -+ -+ r = sd_bus_message_read(message, "b", &runtime); -+ if (r < 0) -+ return r; -+ flags = unit_file_bools_to_flags(runtime, false); -+ } - - r = bus_verify_manage_unit_files_async(m, message, error); - if (r < 0) -@@ -2208,13 +2236,17 @@ static int method_disable_unit_files_generic( - if (r == 0) - return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ - -- r = call(m->unit_file_scope, runtime ? UNIT_FILE_RUNTIME : 0, NULL, l, &changes, &n_changes); -+ r = call(m->unit_file_scope, flags, NULL, l, &changes, &n_changes); - if (r < 0) - return install_error(error, r, changes, n_changes); - - return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); - } - -+static int method_disable_unit_files_with_flags(sd_bus_message *message, void *userdata, sd_bus_error *error) { -+ return method_disable_unit_files_generic(message, userdata, unit_file_disable, error); -+} -+ - static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { - return method_disable_unit_files_generic(message, userdata, unit_file_disable, error); - } -@@ -2984,6 +3016,23 @@ const sd_bus_vtable bus_manager_vtable[] = { - SD_BUS_PARAM(changes), - method_disable_unit_files, - SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD_WITH_NAMES("EnableUnitFilesWithFlags", -+ "ast", -+ SD_BUS_PARAM(files) -+ SD_BUS_PARAM(flags), -+ "ba(sss)", -+ SD_BUS_PARAM(carries_install_info) -+ SD_BUS_PARAM(changes), -+ method_enable_unit_files_with_flags, -+ SD_BUS_VTABLE_UNPRIVILEGED), -+ SD_BUS_METHOD_WITH_NAMES("DisableUnitFilesWithFlags", -+ "ast", -+ SD_BUS_PARAM(files) -+ SD_BUS_PARAM(flags), -+ "a(sss)", -+ SD_BUS_PARAM(changes), -+ method_disable_unit_files_with_flags, -+ SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD_WITH_NAMES("ReenableUnitFiles", - "asbb", - SD_BUS_PARAM(files) -diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c -index bab12cc..a4fa44d 100644 ---- a/src/core/dbus-mount.c -+++ b/src/core/dbus-mount.c -@@ -149,7 +149,6 @@ int bus_mount_set_property( - int bus_mount_commit_properties(Unit *u) { - assert(u); - -- unit_invalidate_cgroup_members_masks(u); - unit_realize_cgroup(u); - - return 0; -diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c -index aecfda6..d752cd5 100644 ---- a/src/core/dbus-scope.c -+++ b/src/core/dbus-scope.c -@@ -190,7 +190,6 @@ int bus_scope_set_property( - int bus_scope_commit_properties(Unit *u) { - assert(u); - -- unit_invalidate_cgroup_members_masks(u); - unit_realize_cgroup(u); - - return 0; -diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c -index 3cc453d..73052fa 100644 ---- a/src/core/dbus-service.c -+++ b/src/core/dbus-service.c -@@ -42,7 +42,6 @@ static int property_get_exit_status_set( - - const ExitStatusSet *status_set = userdata; - unsigned n; -- Iterator i; - int r; - - assert(bus); -@@ -57,7 +56,7 @@ static int property_get_exit_status_set( - if (r < 0) - return r; - -- BITMAP_FOREACH(n, &status_set->status, i) { -+ BITMAP_FOREACH(n, &status_set->status) { - assert(n < 256); - - r = sd_bus_message_append_basic(reply, 'i', &n); -@@ -73,7 +72,7 @@ static int property_get_exit_status_set( - if (r < 0) - return r; - -- BITMAP_FOREACH(n, &status_set->signal, i) { -+ BITMAP_FOREACH(n, &status_set->signal) { - const char *str; - - str = signal_to_string(n); -@@ -457,7 +456,6 @@ int bus_service_set_property( - int bus_service_commit_properties(Unit *u) { - assert(u); - -- unit_invalidate_cgroup_members_masks(u); - unit_realize_cgroup(u); - - return 0; -diff --git a/src/core/dbus-slice.c b/src/core/dbus-slice.c -index effd5fa..28a6a4f 100644 ---- a/src/core/dbus-slice.c -+++ b/src/core/dbus-slice.c -@@ -28,7 +28,6 @@ int bus_slice_set_property( - int bus_slice_commit_properties(Unit *u) { - assert(u); - -- unit_invalidate_cgroup_members_masks(u); - unit_realize_cgroup(u); - - return 0; -diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c -index f01489e..07d030a 100644 ---- a/src/core/dbus-socket.c -+++ b/src/core/dbus-socket.c -@@ -86,6 +86,7 @@ const sd_bus_vtable bus_socket_vtable[] = { - SD_BUS_PROPERTY("SocketMode", "u", bus_property_get_mode, offsetof(Socket, socket_mode), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Socket, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Accept", "b", bus_property_get_bool, offsetof(Socket, accept), SD_BUS_VTABLE_PROPERTY_CONST), -+ SD_BUS_PROPERTY("FlushPending", "b", bus_property_get_bool, offsetof(Socket, flush_pending), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Writable", "b", bus_property_get_bool, offsetof(Socket, writable), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("KeepAlive", "b", bus_property_get_bool, offsetof(Socket, keep_alive), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("KeepAliveTimeUSec", "t", bus_property_get_usec, offsetof(Socket, keep_alive_time), SD_BUS_VTABLE_PROPERTY_CONST), -@@ -179,6 +180,9 @@ static int bus_socket_set_transient_property( - if (streq(name, "Accept")) - return bus_set_transient_bool(u, name, &s->accept, message, flags, error); - -+ if (streq(name, "FlushPending")) -+ return bus_set_transient_bool(u, name, &s->flush_pending, message, flags, error); -+ - if (streq(name, "Writable")) - return bus_set_transient_bool(u, name, &s->writable, message, flags, error); - -@@ -469,7 +473,6 @@ int bus_socket_set_property( - int bus_socket_commit_properties(Unit *u) { - assert(u); - -- unit_invalidate_cgroup_members_masks(u); - unit_realize_cgroup(u); - - return 0; -diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c -index cb4824b..d132c08 100644 ---- a/src/core/dbus-swap.c -+++ b/src/core/dbus-swap.c -@@ -70,7 +70,6 @@ int bus_swap_set_property( - int bus_swap_commit_properties(Unit *u) { - assert(u); - -- unit_invalidate_cgroup_members_masks(u); - unit_realize_cgroup(u); - - return 0; -diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c -index 9e9d3b1..d38c0f0 100644 ---- a/src/core/dbus-unit.c -+++ b/src/core/dbus-unit.c -@@ -103,7 +103,6 @@ static int property_get_names( - sd_bus_error *error) { - - Unit *u = userdata; -- Iterator i; - const char *t; - int r; - -@@ -119,7 +118,7 @@ static int property_get_names( - if (r < 0) - return r; - -- SET_FOREACH(t, u->aliases, i) { -+ SET_FOREACH(t, u->aliases) { - r = sd_bus_message_append(reply, "s", t); - if (r < 0) - return r; -@@ -157,7 +156,6 @@ static int property_get_dependencies( - sd_bus_error *error) { - - Hashmap **h = userdata; -- Iterator j; - Unit *u; - void *v; - int r; -@@ -170,7 +168,7 @@ static int property_get_dependencies( - if (r < 0) - return r; - -- HASHMAP_FOREACH_KEY(v, u, *h, j) { -+ HASHMAP_FOREACH_KEY(v, u, *h) { - r = sd_bus_message_append(reply, "s", u->id); - if (r < 0) - return r; -@@ -190,7 +188,6 @@ static int property_get_requires_mounts_for( - - Hashmap **h = userdata; - const char *p; -- Iterator j; - void *v; - int r; - -@@ -202,7 +199,7 @@ static int property_get_requires_mounts_for( - if (r < 0) - return r; - -- HASHMAP_FOREACH_KEY(v, p, *h, j) { -+ HASHMAP_FOREACH_KEY(v, p, *h) { - r = sd_bus_message_append(reply, "s", p); - if (r < 0) - return r; -@@ -1729,7 +1726,6 @@ int bus_unit_queue_job( - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_free_ char *job_path = NULL, *unit_path = NULL; - _cleanup_set_free_ Set *affected = NULL; -- Iterator i; - Job *j, *a; - int r; - -@@ -1808,7 +1804,7 @@ int bus_unit_queue_job( - if (r < 0) - return r; - -- SET_FOREACH(a, affected, i) { -+ SET_FOREACH(a, affected) { - - if (a->id == j->id) - continue; -@@ -1974,14 +1970,11 @@ static int bus_set_transient_conditions( - if (t < 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid condition type: %s", type_name); - -- if (t != CONDITION_NULL) { -- if (isempty(param)) -- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name); -+ if (isempty(param)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name); - -- if (condition_takes_path(t) && !path_is_absolute(param)) -- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param); -- } else -- param = NULL; -+ if (condition_takes_path(t) && !path_is_absolute(param)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param); - - if (!UNIT_WRITE_FLAGS_NOOP(flags)) { - Condition *c; -@@ -1992,14 +1985,9 @@ static int bus_set_transient_conditions( - - LIST_PREPEND(conditions, *list, c); - -- if (t != CONDITION_NULL) -- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, -- "%s=%s%s%s", type_name, -- trigger ? "|" : "", negate ? "!" : "", param); -- else -- unit_write_settingf(u, flags, name, -- "%s=%s%s", type_name, -- trigger ? "|" : "", yes_no(!negate)); -+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, -+ "%s=%s%s%s", type_name, -+ trigger ? "|" : "", negate ? "!" : "", param); - } - - empty = false; -diff --git a/src/core/dbus.c b/src/core/dbus.c -index 76bb91d..774ee56 100644 ---- a/src/core/dbus.c -+++ b/src/core/dbus.c -@@ -457,14 +457,13 @@ static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, cha - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - unsigned k = 0; -- Iterator i; - Unit *u; - - l = new0(char*, hashmap_size(m->units)+1); - if (!l) - return -ENOMEM; - -- HASHMAP_FOREACH(u, m->units, i) { -+ HASHMAP_FOREACH(u, m->units) { - l[k] = unit_dbus_path(u); - if (!l[k]) - return -ENOMEM; -@@ -767,7 +766,6 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void - } - - static int bus_setup_api(Manager *m, sd_bus *bus) { -- Iterator i; - char *name; - Unit *u; - int r; -@@ -787,7 +785,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) { - if (r < 0) - return r; - -- HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) { -+ HASHMAP_FOREACH_KEY(u, name, m->watch_bus) { - r = unit_install_bus_match(u, bus, name); - if (r < 0) - log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name); -@@ -976,7 +974,6 @@ int bus_init_private(Manager *m) { - } - - static void destroy_bus(Manager *m, sd_bus **bus) { -- Iterator i; - Unit *u; - Job *j; - -@@ -987,7 +984,7 @@ static void destroy_bus(Manager *m, sd_bus **bus) { - return; - - /* Make sure all bus slots watching names are released. */ -- HASHMAP_FOREACH(u, m->watch_bus, i) { -+ HASHMAP_FOREACH(u, m->watch_bus) { - if (u->match_bus_slot && sd_bus_slot_get_bus(u->match_bus_slot) == *bus) - u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); - if (u->get_name_owner_slot && sd_bus_slot_get_bus(u->get_name_owner_slot) == *bus) -@@ -998,11 +995,11 @@ static void destroy_bus(Manager *m, sd_bus **bus) { - if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus) - m->subscribed = sd_bus_track_unref(m->subscribed); - -- HASHMAP_FOREACH(j, m->jobs, i) -+ HASHMAP_FOREACH(j, m->jobs) - if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus) - j->bus_track = sd_bus_track_unref(j->bus_track); - -- HASHMAP_FOREACH(u, m->units, i) { -+ HASHMAP_FOREACH(u, m->units) { - if (u->bus_track && sd_bus_track_get_bus(u->bus_track) == *bus) - u->bus_track = sd_bus_track_unref(u->bus_track); - -@@ -1060,7 +1057,6 @@ void bus_done(Manager *m) { - } - - int bus_fdset_add_all(Manager *m, FDSet *fds) { -- Iterator i; - sd_bus *b; - int fd; - -@@ -1083,7 +1079,7 @@ int bus_fdset_add_all(Manager *m, FDSet *fds) { - } - } - -- SET_FOREACH(b, m->private_buses, i) { -+ SET_FOREACH(b, m->private_buses) { - fd = sd_bus_get_fd(b); - if (fd >= 0) { - fd = fdset_put_dup(fds, fd); -@@ -1105,12 +1101,11 @@ int bus_foreach_bus( - int (*send_message)(sd_bus *bus, void *userdata), - void *userdata) { - -- Iterator i; - sd_bus *b; - int r, ret = 0; - - /* Send to all direct buses, unconditionally */ -- SET_FOREACH(b, m->private_buses, i) { -+ SET_FOREACH(b, m->private_buses) { - - /* Don't bother with enqueuing these messages to clients that haven't started yet */ - if (sd_bus_is_ready(b) <= 0) -@@ -1149,7 +1144,7 @@ void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) { - } - - int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) { -- int r = 0; -+ int r; - - assert(m); - assert(t); -@@ -1191,13 +1186,12 @@ int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_er - - uint64_t manager_bus_n_queued_write(Manager *m) { - uint64_t c = 0; -- Iterator i; - sd_bus *b; - int r; - - /* Returns the total number of messages queued for writing on all our direct and API buses. */ - -- SET_FOREACH(b, m->private_buses, i) { -+ SET_FOREACH(b, m->private_buses) { - uint64_t k; - - r = sd_bus_get_n_queued_write(b, &k); -diff --git a/src/core/device.c b/src/core/device.c -index 50d5528..595b009 100644 ---- a/src/core/device.c -+++ b/src/core/device.c -@@ -441,10 +441,7 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) { - } - } - -- strv_free(d->wants_property); -- d->wants_property = TAKE_PTR(added); -- -- return 0; -+ return strv_free_and_replace(d->wants_property, added); - } - - static bool device_is_bound_by_mounts(Device *d, sd_device *dev) { -@@ -468,13 +465,12 @@ static bool device_is_bound_by_mounts(Device *d, sd_device *dev) { - - static void device_upgrade_mount_deps(Unit *u) { - Unit *other; -- Iterator i; - void *v; - int r; - - /* Let's upgrade Requires= to BindsTo= on us. (Used when SYSTEMD_MOUNT_DEVICE_BOUND is set) */ - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRED_BY], i) { -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRED_BY]) { - if (other->type != UNIT_MOUNT) - continue; - -@@ -736,6 +732,10 @@ static bool device_is_ready(sd_device *dev) { - if (device_is_renaming(dev) > 0) - return false; - -+ /* Is it really tagged as 'systemd' right now? */ -+ if (sd_device_has_current_tag(dev, "systemd") <= 0) -+ return false; -+ - if (sd_device_get_property_value(dev, "SYSTEMD_READY", &ready) < 0) - return true; - -@@ -915,20 +915,19 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void * - return 0; - } - -- if (action == DEVICE_ACTION_CHANGE) -+ if (!IN_SET(action, DEVICE_ACTION_ADD, DEVICE_ACTION_REMOVE, DEVICE_ACTION_MOVE)) - device_propagate_reload_by_sysfs(m, sysfs); - -- /* A change event can signal that a device is becoming ready, in particular if -- * the device is using the SYSTEMD_READY logic in udev -- * so we need to reach the else block of the following if, even for change events */ -+ /* A change event can signal that a device is becoming ready, in particular if the device is using -+ * the SYSTEMD_READY logic in udev so we need to reach the else block of the following if, even for -+ * change events */ - if (action == DEVICE_ACTION_REMOVE) { - r = swap_process_device_remove(m, dev); - if (r < 0) - log_device_warning_errno(dev, r, "Failed to process swap device remove event, ignoring: %m"); - -- /* If we get notified that a device was removed by -- * udev, then it's completely gone, hence unset all -- * found bits */ -+ /* If we get notified that a device was removed by udev, then it's completely gone, hence -+ * unset all found bits */ - device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP); - - } else if (device_is_ready(dev)) { -@@ -944,13 +943,10 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void * - /* The device is found now, set the udev found bit */ - device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); - -- } else { -- /* The device is nominally around, but not ready for -- * us. Hence unset the udev bit, but leave the rest -- * around. */ -- -+ } else -+ /* The device is nominally around, but not ready for us. Hence unset the udev bit, but leave -+ * the rest around. */ - device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV); -- } - - return 0; - } -diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c -index 58b3792..be386df 100644 ---- a/src/core/dynamic-user.c -+++ b/src/core/dynamic-user.c -@@ -611,7 +611,6 @@ static DynamicUser* dynamic_user_destroy(DynamicUser *d) { - - int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds) { - DynamicUser *d; -- Iterator i; - - assert(m); - assert(f); -@@ -619,7 +618,7 @@ int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds) { - - /* Dump the dynamic user database into the manager serialization, to deal with daemon reloads. */ - -- HASHMAP_FOREACH(d, m->dynamic_users, i) { -+ HASHMAP_FOREACH(d, m->dynamic_users) { - int copy0, copy1; - - copy0 = fdset_put_dup(fds, d->storage_socket[0]); -@@ -674,7 +673,6 @@ void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds) { - - void dynamic_user_vacuum(Manager *m, bool close_user) { - DynamicUser *d; -- Iterator i; - - assert(m); - -@@ -682,7 +680,7 @@ void dynamic_user_vacuum(Manager *m, bool close_user) { - * to which no reference exist. This is called after a daemon reload finished, in order to destroy users which - * might not be referenced anymore. */ - -- HASHMAP_FOREACH(d, m->dynamic_users, i) { -+ HASHMAP_FOREACH(d, m->dynamic_users) { - if (d->n_ref > 0) - continue; - -diff --git a/src/core/execute.c b/src/core/execute.c -index 2a4840a..be35093 100644 ---- a/src/core/execute.c -+++ b/src/core/execute.c -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -32,6 +33,7 @@ - - #include "sd-messages.h" - -+#include "acl-util.h" - #include "af-list.h" - #include "alloc-util.h" - #if HAVE_APPARMOR -@@ -41,8 +43,8 @@ - #include "barrier.h" - #include "cap-list.h" - #include "capability-util.h" --#include "chown-recursive.h" - #include "cgroup-setup.h" -+#include "chown-recursive.h" - #include "cpu-set-util.h" - #include "def.h" - #include "env-file.h" -@@ -51,6 +53,7 @@ - #include "execute.h" - #include "exit-status.h" - #include "fd-util.h" -+#include "fileio.h" - #include "format-util.h" - #include "fs-util.h" - #include "glob-util.h" -@@ -64,6 +67,7 @@ - #include "memory-util.h" - #include "missing_fs.h" - #include "mkdir.h" -+#include "mountpoint-util.h" - #include "namespace.h" - #include "parse-util.h" - #include "path-util.h" -@@ -85,6 +89,7 @@ - #include "strv.h" - #include "syslog-util.h" - #include "terminal-util.h" -+#include "tmpfile-util.h" - #include "umask-util.h" - #include "unit.h" - #include "user-util.h" -@@ -96,8 +101,6 @@ - #define SNDBUF_SIZE (8*1024*1024) - - static int shift_fds(int fds[], size_t n_fds) { -- int start, restart_from; -- - if (n_fds <= 0) - return 0; - -@@ -105,13 +108,10 @@ static int shift_fds(int fds[], size_t n_fds) { - - assert(fds); - -- start = 0; -- for (;;) { -- int i; -- -- restart_from = -1; -+ for (int start = 0;;) { -+ int restart_from = -1; - -- for (i = start; i < (int) n_fds; i++) { -+ for (int i = start; i < (int) n_fds; i++) { - int nfd; - - /* Already at right index? */ -@@ -141,7 +141,7 @@ static int shift_fds(int fds[], size_t n_fds) { - } - - static int flags_fds(const int fds[], size_t n_socket_fds, size_t n_storage_fds, bool nonblock) { -- size_t i, n_fds; -+ size_t n_fds; - int r; - - n_fds = n_socket_fds + n_storage_fds; -@@ -153,7 +153,7 @@ static int flags_fds(const int fds[], size_t n_socket_fds, size_t n_storage_fds, - /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags. - * O_NONBLOCK only applies to socket activation though. */ - -- for (i = 0; i < n_fds; i++) { -+ for (size_t i = 0; i < n_fds; i++) { - - if (i < n_socket_fds) { - r = fd_nonblock(fds[i], nonblock); -@@ -407,7 +407,7 @@ static int acquire_path(const char *path, int flags, mode_t mode) { - - if (connect(fd, &sa.sa, sa_len) < 0) - return errno == EINVAL ? -ENXIO : -errno; /* Propagate initial error if we get EINVAL, i.e. we have -- * indication that his wasn't an AF_UNIX socket after all */ -+ * indication that this wasn't an AF_UNIX socket after all */ - - if ((flags & O_ACCMODE) == O_RDONLY) - r = shutdown(fd, SHUT_WR); -@@ -1072,26 +1072,42 @@ static int enforce_groups(gid_t gid, const gid_t *supplementary_gids, int ngids) - return 0; - } - -+static int set_securebits(int bits, int mask) { -+ int current, applied; -+ current = prctl(PR_GET_SECUREBITS); -+ if (current < 0) -+ return -errno; -+ /* Clear all securebits defined in mask and set bits */ -+ applied = (current & ~mask) | bits; -+ if (current == applied) -+ return 0; -+ if (prctl(PR_SET_SECUREBITS, applied) < 0) -+ return -errno; -+ return 1; -+} -+ - static int enforce_user(const ExecContext *context, uid_t uid) { - assert(context); -+ int r; - - if (!uid_is_valid(uid)) - return 0; - - /* Sets (but doesn't look up) the uid and make sure we keep the -- * capabilities while doing so. */ -+ * capabilities while doing so. For setting secure bits the capability CAP_SETPCAP is -+ * required, so we also need keep-caps in this case. -+ */ - -- if (context->capability_ambient_set != 0) { -+ if (context->capability_ambient_set != 0 || context->secure_bits != 0) { - - /* First step: If we need to keep capabilities but - * drop privileges we need to make sure we keep our - * caps, while we drop privileges. */ - if (uid != 0) { -- int sb = context->secure_bits | 1<syscall_filter); - } - -+static bool context_has_syscall_logs(const ExecContext *c) { -+ assert(c); -+ -+ return c->syscall_log_allow_list || -+ !hashmap_isempty(c->syscall_log); -+} -+ - static bool context_has_no_new_privileges(const ExecContext *c) { - assert(c); - -@@ -1412,11 +1435,20 @@ static bool context_has_no_new_privileges(const ExecContext *c) { - c->protect_kernel_logs || - c->private_devices || - context_has_syscall_filters(c) || -+ context_has_syscall_logs(c) || - !set_isempty(c->syscall_archs) || - c->lock_personality || - c->protect_hostname; - } - -+static bool exec_context_has_credentials(const ExecContext *context) { -+ -+ assert(context); -+ -+ return !hashmap_isempty(context->set_credentials) || -+ context->load_credentials; -+} -+ - #if HAVE_SECCOMP - - static bool skip_seccomp_unavailable(const Unit* u, const char* msg) { -@@ -1441,7 +1473,7 @@ static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_ - if (skip_seccomp_unavailable(u, "SystemCallFilter=")) - return 0; - -- negative_action = c->syscall_errno == 0 ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno); -+ negative_action = c->syscall_errno == SECCOMP_ERROR_NUMBER_KILL ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno); - - if (c->syscall_allow_list) { - default_action = negative_action; -@@ -1460,6 +1492,39 @@ static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_ - return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action, false); - } - -+static int apply_syscall_log(const Unit* u, const ExecContext *c) { -+#ifdef SCMP_ACT_LOG -+ uint32_t default_action, action; -+#endif -+ -+ assert(u); -+ assert(c); -+ -+ if (!context_has_syscall_logs(c)) -+ return 0; -+ -+#ifdef SCMP_ACT_LOG -+ if (skip_seccomp_unavailable(u, "SystemCallLog=")) -+ return 0; -+ -+ if (c->syscall_log_allow_list) { -+ /* Log nothing but the ones listed */ -+ default_action = SCMP_ACT_ALLOW; -+ action = SCMP_ACT_LOG; -+ } else { -+ /* Log everything but the ones listed */ -+ default_action = SCMP_ACT_LOG; -+ action = SCMP_ACT_ALLOW; -+ } -+ -+ return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_log, action, false); -+#else -+ /* old libseccomp */ -+ log_unit_debug(u, "SECCOMP feature SCMP_ACT_LOG not available, skipping SystemCallLog="); -+ return 0; -+#endif -+} -+ - static int apply_syscall_archs(const Unit *u, const ExecContext *c) { - assert(u); - assert(c); -@@ -1716,7 +1781,6 @@ static int build_environment( - char ***ret) { - - _cleanup_strv_free_ char **our_env = NULL; -- ExecDirectoryType t; - size_t n_env = 0; - char *x; - -@@ -1725,7 +1789,7 @@ static int build_environment( - assert(p); - assert(ret); - --#define N_ENV_VARS 15 -+#define N_ENV_VARS 16 - our_env = new0(char*, N_ENV_VARS + _EXEC_DIRECTORY_TYPE_MAX); - if (!our_env) - return -ENOMEM; -@@ -1844,7 +1908,7 @@ static int build_environment( - our_env[n_env++] = x; - } - -- for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { -+ for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { - _cleanup_free_ char *pre = NULL, *joined = NULL; - const char *n; - -@@ -1873,6 +1937,14 @@ static int build_environment( - our_env[n_env++] = x; - } - -+ if (exec_context_has_credentials(c) && p->prefix[EXEC_DIRECTORY_RUNTIME]) { -+ x = strjoin("CREDENTIALS_DIRECTORY=", p->prefix[EXEC_DIRECTORY_RUNTIME], "/credentials/", u->id); -+ if (!x) -+ return -ENOMEM; -+ -+ our_env[n_env++] = x; -+ } -+ - our_env[n_env++] = NULL; - assert(n_env <= N_ENV_VARS + _EXEC_DIRECTORY_TYPE_MAX); - #undef N_ENV_VARS -@@ -1932,6 +2004,9 @@ static bool exec_needs_mount_namespace( - if (context->n_temporary_filesystems > 0) - return true; - -+ if (context->n_mount_images > 0) -+ return true; -+ - if (!IN_SET(context->mount_flags, 0, MS_SHARED)) - return true; - -@@ -1945,16 +2020,16 @@ static bool exec_needs_mount_namespace( - context->protect_kernel_tunables || - context->protect_kernel_modules || - context->protect_kernel_logs || -- context->protect_control_groups) -+ context->protect_control_groups || -+ context->protect_proc != PROTECT_PROC_DEFAULT || -+ context->proc_subset != PROC_SUBSET_ALL) - return true; - - if (context->root_directory) { -- ExecDirectoryType t; -- - if (context->mount_apivfs) - return true; - -- for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { -+ for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { - if (!params->prefix[t]) - continue; - -@@ -2373,6 +2448,428 @@ fail: - return r; - } - -+static int write_credential( -+ int dfd, -+ const char *id, -+ const void *data, -+ size_t size, -+ uid_t uid, -+ bool ownership_ok) { -+ -+ _cleanup_(unlink_and_freep) char *tmp = NULL; -+ _cleanup_close_ int fd = -1; -+ int r; -+ -+ r = tempfn_random_child("", "cred", &tmp); -+ if (r < 0) -+ return r; -+ -+ fd = openat(dfd, tmp, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL|O_NOFOLLOW|O_NOCTTY, 0600); -+ if (fd < 0) { -+ tmp = mfree(tmp); -+ return -errno; -+ } -+ -+ r = loop_write(fd, data, size, /* do_pool = */ false); -+ if (r < 0) -+ return r; -+ -+ if (fchmod(fd, 0400) < 0) /* Take away "w" bit */ -+ return -errno; -+ -+ if (uid_is_valid(uid) && uid != getuid()) { -+ r = fd_add_uid_acl_permission(fd, uid, ACL_READ); -+ if (r < 0) { -+ if (!ERRNO_IS_NOT_SUPPORTED(r) && !ERRNO_IS_PRIVILEGE(r)) -+ return r; -+ -+ if (!ownership_ok) /* Ideally we use ACLs, since we can neatly express what we want -+ * to express: that the user gets read access and nothing -+ * else. But if the backing fs can't support that (e.g. ramfs) -+ * then we can use file ownership instead. But that's only safe if -+ * we can then re-mount the whole thing read-only, so that the -+ * user can no longer chmod() the file to gain write access. */ -+ return r; -+ -+ if (fchown(fd, uid, (gid_t) -1) < 0) -+ return -errno; -+ } -+ } -+ -+ if (renameat(dfd, tmp, dfd, id) < 0) -+ return -errno; -+ -+ tmp = mfree(tmp); -+ return 0; -+} -+ -+#define CREDENTIALS_BYTES_MAX (1024LU * 1024LU) /* Refuse to pass more than 1M, after all this is unswappable memory */ -+ -+static int acquire_credentials( -+ const ExecContext *context, -+ const ExecParameters *params, -+ const char *p, -+ uid_t uid, -+ bool ownership_ok) { -+ -+ uint64_t left = CREDENTIALS_BYTES_MAX; -+ _cleanup_close_ int dfd = -1; -+ ExecSetCredential *sc; -+ char **id, **fn; -+ int r; -+ -+ assert(context); -+ assert(p); -+ -+ dfd = open(p, O_DIRECTORY|O_CLOEXEC); -+ if (dfd < 0) -+ return -errno; -+ -+ /* First we use the literally specified credentials. Note that they might be overridden again below, -+ * and thus act as a "default" if the same credential is specified multiple times */ -+ HASHMAP_FOREACH(sc, context->set_credentials) { -+ size_t add; -+ -+ add = strlen(sc->id) + sc->size; -+ if (add > left) -+ return -E2BIG; -+ -+ r = write_credential(dfd, sc->id, sc->data, sc->size, uid, ownership_ok); -+ if (r < 0) -+ return r; -+ -+ left -= add; -+ } -+ -+ /* Then, load credential off disk (or acquire via AF_UNIX socket) */ -+ STRV_FOREACH_PAIR(id, fn, context->load_credentials) { -+ ReadFullFileFlags flags = READ_FULL_FILE_SECURE; -+ _cleanup_(erase_and_freep) char *data = NULL; -+ _cleanup_free_ char *j = NULL; -+ const char *source; -+ size_t size, add; -+ -+ if (path_is_absolute(*fn)) { -+ /* If this is an absolute path, read the data directly from it, and support AF_UNIX sockets */ -+ source = *fn; -+ flags |= READ_FULL_FILE_CONNECT_SOCKET; -+ } else if (params->received_credentials) { -+ /* If this is a relative path, take it relative to the credentials we received -+ * ourselves. We don't support the AF_UNIX stuff in this mode, since we are operating -+ * on a credential store, i.e. this is guaranteed to be regular files. */ -+ j = path_join(params->received_credentials, *fn); -+ if (!j) -+ return -ENOMEM; -+ -+ source = j; -+ } else -+ source = NULL; -+ -+ if (source) -+ r = read_full_file_full(AT_FDCWD, source, flags, &data, &size); -+ else -+ r = -ENOENT; -+ if (r == -ENOENT && -+ faccessat(dfd, *id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) /* If the source file doesn't exist, but we already acquired the key otherwise, then don't fail */ -+ continue; -+ if (r < 0) -+ return r; -+ -+ add = strlen(*id) + size; -+ if (add > left) -+ return -E2BIG; -+ -+ r = write_credential(dfd, *id, data, size, uid, ownership_ok); -+ if (r < 0) -+ return r; -+ -+ left -= add; -+ } -+ -+ if (fchmod(dfd, 0500) < 0) /* Now take away the "w" bit */ -+ return -errno; -+ -+ /* After we created all keys with the right perms, also make sure the credential store as a whole is -+ * accessible */ -+ -+ if (uid_is_valid(uid) && uid != getuid()) { -+ r = fd_add_uid_acl_permission(dfd, uid, ACL_READ | ACL_EXECUTE); -+ if (r < 0) { -+ if (!ERRNO_IS_NOT_SUPPORTED(r) && !ERRNO_IS_PRIVILEGE(r)) -+ return r; -+ -+ if (!ownership_ok) -+ return r; -+ -+ if (fchown(dfd, uid, (gid_t) -1) < 0) -+ return -errno; -+ } -+ } -+ -+ return 0; -+} -+ -+static int setup_credentials_internal( -+ const ExecContext *context, -+ const ExecParameters *params, -+ const char *final, /* This is where the credential store shall eventually end up at */ -+ const char *workspace, /* This is where we can prepare it before moving it to the final place */ -+ bool reuse_workspace, /* Whether to reuse any existing workspace mount if it already is a mount */ -+ bool must_mount, /* Whether to require that we mount something, it's not OK to use the plain directory fall back */ -+ uid_t uid) { -+ -+ int r, workspace_mounted; /* negative if we don't know yet whether we have/can mount something; true -+ * if we mounted something; false if we definitely can't mount anything */ -+ bool final_mounted; -+ const char *where; -+ -+ assert(context); -+ assert(final); -+ assert(workspace); -+ -+ if (reuse_workspace) { -+ r = path_is_mount_point(workspace, NULL, 0); -+ if (r < 0) -+ return r; -+ if (r > 0) -+ workspace_mounted = true; /* If this is already a mount, and we are supposed to reuse it, let's keep this in mind */ -+ else -+ workspace_mounted = -1; /* We need to figure out if we can mount something to the workspace */ -+ } else -+ workspace_mounted = -1; /* ditto */ -+ -+ r = path_is_mount_point(final, NULL, 0); -+ if (r < 0) -+ return r; -+ if (r > 0) { -+ /* If the final place already has something mounted, we use that. If the workspace also has -+ * something mounted we assume it's actually the same mount (but with MS_RDONLY -+ * different). */ -+ final_mounted = true; -+ -+ if (workspace_mounted < 0) { -+ /* If the final place is mounted, but the workspace we isn't, then let's bind mount -+ * the final version to the workspace, and make it writable, so that we can make -+ * changes */ -+ -+ if (mount(final, workspace, NULL, MS_BIND|MS_REC, NULL) < 0) -+ return -errno; -+ -+ if (mount(NULL, workspace, NULL, MS_BIND|MS_REMOUNT|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0) -+ return -errno; -+ -+ workspace_mounted = true; -+ } -+ } else -+ final_mounted = false; -+ -+ if (workspace_mounted < 0) { -+ /* Nothing is mounted on the workspace yet, let's try to mount something now */ -+ for (int try = 0;; try++) { -+ -+ if (try == 0) { -+ /* Try "ramfs" first, since it's not swap backed */ -+ if (mount("ramfs", workspace, "ramfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, "mode=0700") >= 0) { -+ workspace_mounted = true; -+ break; -+ } -+ -+ } else if (try == 1) { -+ _cleanup_free_ char *opts = NULL; -+ -+ if (asprintf(&opts, "mode=0700,nr_inodes=1024,size=%lu", CREDENTIALS_BYTES_MAX) < 0) -+ return -ENOMEM; -+ -+ /* Fall back to "tmpfs" otherwise */ -+ if (mount("tmpfs", workspace, "tmpfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, opts) >= 0) { -+ workspace_mounted = true; -+ break; -+ } -+ -+ } else { -+ /* If that didn't work, try to make a bind mount from the final to the workspace, so that we can make it writable there. */ -+ if (mount(final, workspace, NULL, MS_BIND|MS_REC, NULL) < 0) { -+ if (!ERRNO_IS_PRIVILEGE(errno)) /* Propagate anything that isn't a permission problem */ -+ return -errno; -+ -+ if (must_mount) /* If we it's not OK to use the plain directory -+ * fallback, propagate all errors too */ -+ return -errno; -+ -+ /* If we lack privileges to bind mount stuff, then let's gracefully -+ * proceed for compat with container envs, and just use the final dir -+ * as is. */ -+ -+ workspace_mounted = false; -+ break; -+ } -+ -+ /* Make the new bind mount writable (i.e. drop MS_RDONLY) */ -+ if (mount(NULL, workspace, NULL, MS_BIND|MS_REMOUNT|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0) -+ return -errno; -+ -+ workspace_mounted = true; -+ break; -+ } -+ } -+ } -+ -+ assert(!must_mount || workspace_mounted > 0); -+ where = workspace_mounted ? workspace : final; -+ -+ r = acquire_credentials(context, params, where, uid, workspace_mounted); -+ if (r < 0) -+ return r; -+ -+ if (workspace_mounted) { -+ /* Make workspace read-only now, so that any bind mount we make from it defaults to read-only too */ -+ if (mount(NULL, workspace, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0) -+ return -errno; -+ -+ /* And mount it to the final place, read-only */ -+ if (final_mounted) { -+ if (umount2(workspace, MNT_DETACH|UMOUNT_NOFOLLOW) < 0) -+ return -errno; -+ } else { -+ if (mount(workspace, final, NULL, MS_MOVE, NULL) < 0) -+ return -errno; -+ } -+ } else { -+ _cleanup_free_ char *parent = NULL; -+ -+ /* If we do not have our own mount put used the plain directory fallback, then we need to -+ * open access to the top-level credential directory and the per-service directory now */ -+ -+ parent = dirname_malloc(final); -+ if (!parent) -+ return -ENOMEM; -+ if (chmod(parent, 0755) < 0) -+ return -errno; -+ } -+ -+ return 0; -+} -+ -+static int setup_credentials( -+ const ExecContext *context, -+ const ExecParameters *params, -+ const char *unit, -+ uid_t uid) { -+ -+ _cleanup_free_ char *p = NULL, *q = NULL; -+ const char *i; -+ int r; -+ -+ assert(context); -+ assert(params); -+ -+ if (!exec_context_has_credentials(context)) -+ return 0; -+ -+ if (!params->prefix[EXEC_DIRECTORY_RUNTIME]) -+ return -EINVAL; -+ -+ /* This where we'll place stuff when we are done; this main credentials directory is world-readable, -+ * and the subdir we mount over with a read-only file system readable by the service's user */ -+ q = path_join(params->prefix[EXEC_DIRECTORY_RUNTIME], "credentials"); -+ if (!q) -+ return -ENOMEM; -+ -+ r = mkdir_label(q, 0755); /* top-level dir: world readable/searchable */ -+ if (r < 0 && r != -EEXIST) -+ return r; -+ -+ p = path_join(q, unit); -+ if (!p) -+ return -ENOMEM; -+ -+ r = mkdir_label(p, 0700); /* per-unit dir: private to user */ -+ if (r < 0 && r != -EEXIST) -+ return r; -+ -+ r = safe_fork("(sd-mkdcreds)", FORK_DEATHSIG|FORK_WAIT|FORK_NEW_MOUNTNS, NULL); -+ if (r < 0) { -+ _cleanup_free_ char *t = NULL, *u = NULL; -+ -+ /* If this is not a privilege or support issue then propagate the error */ -+ if (!ERRNO_IS_NOT_SUPPORTED(r) && !ERRNO_IS_PRIVILEGE(r)) -+ return r; -+ -+ /* Temporary workspace, that remains inaccessible all the time. We prepare stuff there before moving -+ * it into place, so that users can't access half-initialized credential stores. */ -+ t = path_join(params->prefix[EXEC_DIRECTORY_RUNTIME], "systemd/temporary-credentials"); -+ if (!t) -+ return -ENOMEM; -+ -+ /* We can't set up a mount namespace. In that case operate on a fixed, inaccessible per-unit -+ * directory outside of /run/credentials/ first, and then move it over to /run/credentials/ -+ * after it is fully set up */ -+ u = path_join(t, unit); -+ if (!u) -+ return -ENOMEM; -+ -+ FOREACH_STRING(i, t, u) { -+ r = mkdir_label(i, 0700); -+ if (r < 0 && r != -EEXIST) -+ return r; -+ } -+ -+ r = setup_credentials_internal( -+ context, -+ params, -+ p, /* final mount point */ -+ u, /* temporary workspace to overmount */ -+ true, /* reuse the workspace if it is already a mount */ -+ false, /* it's OK to fall back to a plain directory if we can't mount anything */ -+ uid); -+ -+ (void) rmdir(u); /* remove the workspace again if we can. */ -+ -+ if (r < 0) -+ return r; -+ -+ } else if (r == 0) { -+ -+ /* We managed to set up a mount namespace, and are now in a child. That's great. In this case -+ * we can use the same directory for all cases, after turning off propagation. Question -+ * though is: where do we turn off propagation exactly, and where do we place the workspace -+ * directory? We need some place that is guaranteed to be a mount point in the host, and -+ * which is guaranteed to have a subdir we can mount over. /run/ is not suitable for this, -+ * since we ultimately want to move the resulting file system there, i.e. we need propagation -+ * for /run/ eventually. We could use our own /run/systemd/bind mount on itself, but that -+ * would be visible in the host mount table all the time, which we want to avoid. Hence, what -+ * we do here instead we use /dev/ and /dev/shm/ for our purposes. We know for sure that -+ * /dev/ is a mount point and we now for sure that /dev/shm/ exists. Hence we can turn off -+ * propagation on the former, and then overmount the latter. -+ * -+ * Yes it's nasty playing games with /dev/ and /dev/shm/ like this, since it does not exist -+ * for this purpose, but there are few other candidates that work equally well for us, and -+ * given that the we do this in a privately namespaced short-lived single-threaded process -+ * that no one else sees this should be OK to do.*/ -+ -+ if (mount(NULL, "/dev", NULL, MS_SLAVE|MS_REC, NULL) < 0) /* Turn off propagation from our namespace to host */ -+ goto child_fail; -+ -+ r = setup_credentials_internal( -+ context, -+ params, -+ p, /* final mount point */ -+ "/dev/shm", /* temporary workspace to overmount */ -+ false, /* do not reuse /dev/shm if it is already a mount, under no circumstances */ -+ true, /* insist that something is mounted, do not allow fallback to plain directory */ -+ uid); -+ if (r < 0) -+ goto child_fail; -+ -+ _exit(EXIT_SUCCESS); -+ -+ child_fail: -+ _exit(EXIT_FAILURE); -+ } -+ -+ return 0; -+} -+ - #if ENABLE_SMACK - static int setup_smack( - const ExecContext *context, -@@ -2415,8 +2912,7 @@ static int compile_bind_mounts( - - _cleanup_strv_free_ char **empty_directories = NULL; - BindMount *bind_mounts; -- size_t n, h = 0, i; -- ExecDirectoryType t; -+ size_t n, h = 0; - int r; - - assert(context); -@@ -2426,7 +2922,7 @@ static int compile_bind_mounts( - assert(ret_empty_directories); - - n = context->n_bind_mounts; -- for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { -+ for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { - if (!params->prefix[t]) - continue; - -@@ -2444,7 +2940,7 @@ static int compile_bind_mounts( - if (!bind_mounts) - return -ENOMEM; - -- for (i = 0; i < context->n_bind_mounts; i++) { -+ for (size_t i = 0; i < context->n_bind_mounts; i++) { - BindMount *item = context->bind_mounts + i; - char *s, *d; - -@@ -2470,7 +2966,7 @@ static int compile_bind_mounts( - }; - } - -- for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { -+ for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { - char **suffix; - - if (!params->prefix[t]) -@@ -2555,8 +3051,6 @@ static bool insist_on_sandboxing( - const BindMount *bind_mounts, - size_t n_bind_mounts) { - -- size_t i; -- - assert(context); - assert(n_bind_mounts == 0 || bind_mounts); - -@@ -2570,12 +3064,15 @@ static bool insist_on_sandboxing( - if (root_dir || root_image) - return true; - -+ if (context->n_mount_images > 0) -+ return true; -+ - if (context->dynamic_user) - return true; - - /* If there are any bind mounts set that don't map back onto themselves, fs namespacing becomes - * essential. */ -- for (i = 0; i < n_bind_mounts; i++) -+ for (size_t i = 0; i < n_bind_mounts; i++) - if (!path_equal(bind_mounts[i].source, bind_mounts[i].destination)) - return true; - -@@ -2596,6 +3093,7 @@ static int apply_mount_namespace( - _cleanup_strv_free_ char **empty_directories = NULL; - const char *tmp_dir = NULL, *var_tmp_dir = NULL; - const char *root_dir = NULL, *root_image = NULL; -+ _cleanup_free_ char *creds_path = NULL; - NamespaceInfo ns_info; - bool needs_sandboxing; - BindMount *bind_mounts = NULL; -@@ -2644,6 +3142,10 @@ static int apply_mount_namespace( - .protect_hostname = context->protect_hostname, - .mount_apivfs = context->mount_apivfs, - .private_mounts = context->private_mounts, -+ .protect_home = context->protect_home, -+ .protect_system = context->protect_system, -+ .protect_proc = context->protect_proc, -+ .proc_subset = context->proc_subset, - }; - } else if (!context->dynamic_user && root_dir) - /* -@@ -2660,7 +3162,15 @@ static int apply_mount_namespace( - if (context->mount_flags == MS_SHARED) - log_unit_debug(u, "shared mount propagation hidden by other fs namespacing unit settings: ignoring"); - -- r = setup_namespace(root_dir, root_image, -+ if (exec_context_has_credentials(context) && params->prefix[EXEC_DIRECTORY_RUNTIME]) { -+ creds_path = path_join(params->prefix[EXEC_DIRECTORY_RUNTIME], "credentials", u->id); -+ if (!creds_path) { -+ r = -ENOMEM; -+ goto finalize; -+ } -+ } -+ -+ r = setup_namespace(root_dir, root_image, context->root_image_options, - &ns_info, context->read_write_paths, - needs_sandboxing ? context->read_only_paths : NULL, - needs_sandboxing ? context->inaccessible_paths : NULL, -@@ -2669,11 +3179,12 @@ static int apply_mount_namespace( - n_bind_mounts, - context->temporary_filesystems, - context->n_temporary_filesystems, -+ context->mount_images, -+ context->n_mount_images, - tmp_dir, - var_tmp_dir, -+ creds_path, - context->log_namespace, -- needs_sandboxing ? context->protect_home : PROTECT_HOME_NO, -- needs_sandboxing ? context->protect_system : PROTECT_SYSTEM_NO, - context->mount_flags, - context->root_hash, context->root_hash_size, context->root_hash_path, - context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path, -@@ -2702,6 +3213,7 @@ static int apply_mount_namespace( - } - } - -+finalize: - bind_mount_free_many(bind_mounts, n_bind_mounts); - return r; - } -@@ -2753,13 +3265,12 @@ static int apply_root_directory( - assert(context); - assert(exit_status); - -- if (params->flags & EXEC_APPLY_CHROOT) { -+ if (params->flags & EXEC_APPLY_CHROOT) - if (!needs_mount_ns && context->root_directory) - if (chroot(context->root_directory) < 0) { - *exit_status = EXIT_CHROOT; - return -errno; - } -- } - - return 0; - } -@@ -2984,7 +3495,6 @@ static int acquire_home(const ExecContext *c, uid_t uid, const char** home, char - - static int compile_suggested_paths(const ExecContext *c, const ExecParameters *p, char ***ret) { - _cleanup_strv_free_ char ** list = NULL; -- ExecDirectoryType t; - int r; - - assert(c); -@@ -2997,7 +3507,7 @@ static int compile_suggested_paths(const ExecContext *c, const ExecParameters *p - * dynamic UID allocation, in order to save us from doing costly recursive chown()s of the special - * directories. */ - -- for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { -+ for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { - char **i; - - if (t == EXEC_DIRECTORY_CONFIGURATION) -@@ -3132,7 +3642,6 @@ static int exec_child( - uid_t uid = UID_INVALID; - gid_t gid = GID_INVALID; - size_t n_fds; -- ExecDirectoryType dt; - int secure_bits; - _cleanup_free_ gid_t *gids_after_pam = NULL; - int ngids_after_pam = 0; -@@ -3471,12 +3980,20 @@ static int exec_child( - } - } - -- for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { -+ for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { - r = setup_exec_directory(context, params, uid, gid, dt, exit_status); - if (r < 0) - return log_unit_error_errno(unit, r, "Failed to set up special execution directory in %s: %m", params->prefix[dt]); - } - -+ if (FLAGS_SET(params->flags, EXEC_WRITE_CREDENTIALS)) { -+ r = setup_credentials(context, params, unit->id, uid); -+ if (r < 0) { -+ *exit_status = EXIT_CREDENTIALS; -+ return log_unit_error_errno(unit, r, "Failed to set up credentials: %m"); -+ } -+ } -+ - r = build_environment( - unit, - context, -@@ -3779,8 +4296,16 @@ static int exec_child( - } - } - -- /* This is done before enforce_user, but ambient set -- * does not survive over setresuid() if keep_caps is not set. */ -+ /* Ambient capabilities are cleared during setresuid() (in enforce_user()) even with -+ * keep-caps set. -+ * To be able to raise the ambient capabilities after setresuid() they have to be -+ * added to the inherited set and keep caps has to be set (done in enforce_user()). -+ * After setresuid() the ambient capabilities can be raised as they are present in -+ * the permitted and inhertiable set. However it is possible that someone wants to -+ * set ambient capabilities without changing the user, so we also set the ambient -+ * capabilities here. -+ * The requested ambient capabilities are raised in the inheritable set if the -+ * second argument is true. */ - if (!needs_ambient_hack) { - r = capability_ambient_set_apply(context->capability_ambient_set, true); - if (r < 0) { -@@ -3806,21 +4331,12 @@ static int exec_child( - if (!needs_ambient_hack && - context->capability_ambient_set != 0) { - -- /* Fix the ambient capabilities after user change. */ -+ /* Raise the ambient capabilities after user change. */ - r = capability_ambient_set_apply(context->capability_ambient_set, false); - if (r < 0) { - *exit_status = EXIT_CAPABILITIES; - return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (after UID change): %m"); - } -- -- /* If we were asked to change user and ambient capabilities -- * were requested, we had to add keep-caps to the securebits -- * so that we would maintain the inherited capability set -- * through the setresuid(). Make sure that the bit is added -- * also to the context secure_bits so that we don't try to -- * drop the bit away next. */ -- -- secure_bits |= 1<path, -@@ -4164,8 +4705,6 @@ int exec_spawn(Unit *unit, - } - - void exec_context_init(ExecContext *c) { -- ExecDirectoryType i; -- - assert(c); - - c->umask = 0022; -@@ -4176,20 +4715,20 @@ void exec_context_init(ExecContext *c) { - c->ignore_sigpipe = true; - c->timer_slack_nsec = NSEC_INFINITY; - c->personality = PERSONALITY_INVALID; -- for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) -- c->directories[i].mode = 0755; -+ for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) -+ c->directories[t].mode = 0755; - c->timeout_clean_usec = USEC_INFINITY; - c->capability_bounding_set = CAP_ALL; - assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL); - c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL; - c->log_level_max = -1; -+#if HAVE_SECCOMP -+ c->syscall_errno = SECCOMP_ERROR_NUMBER_KILL; -+#endif - numa_policy_reset(&c->numa_policy); - } - - void exec_context_done(ExecContext *c) { -- ExecDirectoryType i; -- size_t l; -- - assert(c); - - c->environment = strv_free(c->environment); -@@ -4199,7 +4738,7 @@ void exec_context_done(ExecContext *c) { - - rlimit_free_all(c->rlimit); - -- for (l = 0; l < 3; l++) { -+ for (size_t l = 0; l < 3; l++) { - c->stdio_fdname[l] = mfree(c->stdio_fdname[l]); - c->stdio_file[l] = mfree(c->stdio_file[l]); - } -@@ -4207,6 +4746,7 @@ void exec_context_done(ExecContext *c) { - c->working_directory = mfree(c->working_directory); - c->root_directory = mfree(c->root_directory); - c->root_image = mfree(c->root_image); -+ c->root_image_options = mount_options_free_all(c->root_image_options); - c->root_hash = mfree(c->root_hash); - c->root_hash_size = 0; - c->root_hash_path = mfree(c->root_hash_path); -@@ -4233,6 +4773,7 @@ void exec_context_done(ExecContext *c) { - temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems); - c->temporary_filesystems = NULL; - c->n_temporary_filesystems = 0; -+ c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images); - - cpu_set_reset(&c->cpu_set); - numa_policy_reset(&c->numa_policy); -@@ -4246,8 +4787,8 @@ void exec_context_done(ExecContext *c) { - c->syscall_archs = set_free(c->syscall_archs); - c->address_families = set_free(c->address_families); - -- for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) -- c->directories[i].paths = strv_free(c->directories[i].paths); -+ for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) -+ c->directories[t].paths = strv_free(c->directories[t].paths); - - c->log_level_max = -1; - -@@ -4262,6 +4803,9 @@ void exec_context_done(ExecContext *c) { - c->network_namespace_path = mfree(c->network_namespace_path); - - c->log_namespace = mfree(c->log_namespace); -+ -+ c->load_credentials = strv_free(c->load_credentials); -+ c->set_credentials = hashmap_free(c->set_credentials); - } - - int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_prefix) { -@@ -4290,6 +4834,26 @@ int exec_context_destroy_runtime_directory(const ExecContext *c, const char *run - return 0; - } - -+int exec_context_destroy_credentials(const ExecContext *c, const char *runtime_prefix, const char *unit) { -+ _cleanup_free_ char *p = NULL; -+ -+ assert(c); -+ -+ if (!runtime_prefix || !unit) -+ return 0; -+ -+ p = path_join(runtime_prefix, "credentials", unit); -+ if (!p) -+ return -ENOMEM; -+ -+ /* This is either a tmpfs/ramfs of its own, or a plain directory. Either way, let's first try to -+ * unmount it, and afterwards remove the mount point */ -+ (void) umount2(p, MNT_DETACH|UMOUNT_NOFOLLOW); -+ (void) rm_rf(p, REMOVE_ROOT|REMOVE_CHMOD); -+ -+ return 0; -+} -+ - static void exec_command_done(ExecCommand *c) { - assert(c); - -@@ -4317,23 +4881,17 @@ ExecCommand* exec_command_free_list(ExecCommand *c) { - } - - void exec_command_free_array(ExecCommand **c, size_t n) { -- size_t i; -- -- for (i = 0; i < n; i++) -+ for (size_t i = 0; i < n; i++) - c[i] = exec_command_free_list(c[i]); - } - - void exec_command_reset_status_array(ExecCommand *c, size_t n) { -- size_t i; -- -- for (i = 0; i < n; i++) -+ for (size_t i = 0; i < n; i++) - exec_status_reset(&c[i].exec_status); - } - - void exec_command_reset_status_list_array(ExecCommand **c, size_t n) { -- size_t i; -- -- for (i = 0; i < n; i++) { -+ for (size_t i = 0; i < n; i++) { - ExecCommand *z; - - LIST_FOREACH(command, z, c[i]) -@@ -4385,7 +4943,7 @@ static int exec_context_named_iofds( - const ExecParameters *p, - int named_iofds[static 3]) { - -- size_t i, targets; -+ size_t targets; - const char* stdio_fdname[3]; - size_t n_fds; - -@@ -4397,12 +4955,12 @@ static int exec_context_named_iofds( - (c->std_output == EXEC_OUTPUT_NAMED_FD) + - (c->std_error == EXEC_OUTPUT_NAMED_FD); - -- for (i = 0; i < 3; i++) -+ for (size_t i = 0; i < 3; i++) - stdio_fdname[i] = exec_context_fdname(c, i); - - n_fds = p->n_storage_fds + p->n_socket_fds; - -- for (i = 0; i < n_fds && targets > 0; i++) -+ for (size_t i = 0; i < n_fds && targets > 0; i++) - if (named_iofds[STDIN_FILENO] < 0 && - c->std_input == EXEC_INPUT_NAMED_FD && - stdio_fdname[STDIN_FILENO] && -@@ -4440,7 +4998,6 @@ static int exec_context_load_environment(const Unit *unit, const ExecContext *c, - STRV_FOREACH(i, c->environment_files) { - char *fn; - int k; -- unsigned n; - bool ignore = false; - char **p; - _cleanup_globfree_ glob_t pglob = {}; -@@ -4473,7 +5030,7 @@ static int exec_context_load_environment(const Unit *unit, const ExecContext *c, - /* When we don't match anything, -ENOENT should be returned */ - assert(pglob.gl_pathc > 0); - -- for (n = 0; n < pglob.gl_pathc; n++) { -+ for (unsigned n = 0; n < pglob.gl_pathc; n++) { - k = load_env_file(NULL, pglob.gl_pathv[n], &p); - if (k < 0) { - if (ignore) -@@ -4560,8 +5117,6 @@ static void strv_fprintf(FILE *f, char **l) { - - void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - char **e, **d, buf_clean[FORMAT_TIMESPAN_MAX]; -- ExecDirectoryType dt; -- unsigned i; - int r; - - assert(c); -@@ -4591,7 +5146,9 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - "%sRestrictRealtime: %s\n" - "%sRestrictSUIDSGID: %s\n" - "%sKeyringMode: %s\n" -- "%sProtectHostname: %s\n", -+ "%sProtectHostname: %s\n" -+ "%sProtectProc: %s\n" -+ "%sProcSubset: %s\n", - prefix, c->umask, - prefix, c->working_directory ? c->working_directory : "/", - prefix, c->root_directory ? c->root_directory : "/", -@@ -4613,11 +5170,25 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - prefix, yes_no(c->restrict_realtime), - prefix, yes_no(c->restrict_suid_sgid), - prefix, exec_keyring_mode_to_string(c->keyring_mode), -- prefix, yes_no(c->protect_hostname)); -+ prefix, yes_no(c->protect_hostname), -+ prefix, protect_proc_to_string(c->protect_proc), -+ prefix, proc_subset_to_string(c->proc_subset)); - - if (c->root_image) - fprintf(f, "%sRootImage: %s\n", prefix, c->root_image); - -+ if (c->root_image_options) { -+ MountOptions *o; -+ -+ fprintf(f, "%sRootImageOptions:", prefix); -+ LIST_FOREACH(mount_options, o, c->root_image_options) -+ if (!isempty(o->options)) -+ fprintf(f, " %s:%s", -+ partition_designator_to_string(o->partition_designator), -+ o->options); -+ fprintf(f, "\n"); -+ } -+ - if (c->root_hash) { - _cleanup_free_ char *encoded = NULL; - encoded = hexmem(c->root_hash, c->root_hash_size); -@@ -4656,7 +5227,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - - fprintf(f, "%sRuntimeDirectoryPreserve: %s\n", prefix, exec_preserve_mode_to_string(c->runtime_directory_preserve_mode)); - -- for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { -+ for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { - fprintf(f, "%s%sMode: %04o\n", prefix, exec_directory_type_to_string(dt), c->directories[dt].mode); - - STRV_FOREACH(d, c->directories[dt].paths) -@@ -4682,7 +5253,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - "%sCoredumpFilter: 0x%"PRIx64"\n", - prefix, c->coredump_filter); - -- for (i = 0; i < RLIM_NLIMITS; i++) -+ for (unsigned i = 0; i < RLIM_NLIMITS; i++) - if (c->rlimit[i]) { - fprintf(f, "%sLimit%s: " RLIM_FMT "\n", - prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max); -@@ -4810,16 +5381,12 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - if (c->log_ratelimit_burst > 0) - fprintf(f, "%sLogRateLimitBurst: %u\n", prefix, c->log_ratelimit_burst); - -- if (c->n_log_extra_fields > 0) { -- size_t j; -- -- for (j = 0; j < c->n_log_extra_fields; j++) { -- fprintf(f, "%sLogExtraFields: ", prefix); -- fwrite(c->log_extra_fields[j].iov_base, -- 1, c->log_extra_fields[j].iov_len, -- f); -- fputc('\n', f); -- } -+ for (size_t j = 0; j < c->n_log_extra_fields; j++) { -+ fprintf(f, "%sLogExtraFields: ", prefix); -+ fwrite(c->log_extra_fields[j].iov_base, -+ 1, c->log_extra_fields[j].iov_len, -+ f); -+ fputc('\n', f); - } - - if (c->log_namespace) -@@ -4883,24 +5450,22 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - fputs("\n", f); - } - -- if (c->n_bind_mounts > 0) -- for (i = 0; i < c->n_bind_mounts; i++) -- fprintf(f, "%s%s: %s%s:%s:%s\n", prefix, -- c->bind_mounts[i].read_only ? "BindReadOnlyPaths" : "BindPaths", -- c->bind_mounts[i].ignore_enoent ? "-": "", -- c->bind_mounts[i].source, -- c->bind_mounts[i].destination, -- c->bind_mounts[i].recursive ? "rbind" : "norbind"); -+ for (size_t i = 0; i < c->n_bind_mounts; i++) -+ fprintf(f, "%s%s: %s%s:%s:%s\n", prefix, -+ c->bind_mounts[i].read_only ? "BindReadOnlyPaths" : "BindPaths", -+ c->bind_mounts[i].ignore_enoent ? "-": "", -+ c->bind_mounts[i].source, -+ c->bind_mounts[i].destination, -+ c->bind_mounts[i].recursive ? "rbind" : "norbind"); - -- if (c->n_temporary_filesystems > 0) -- for (i = 0; i < c->n_temporary_filesystems; i++) { -- TemporaryFileSystem *t = c->temporary_filesystems + i; -+ for (size_t i = 0; i < c->n_temporary_filesystems; i++) { -+ const TemporaryFileSystem *t = c->temporary_filesystems + i; - -- fprintf(f, "%sTemporaryFileSystem: %s%s%s\n", prefix, -- t->path, -- isempty(t->options) ? "" : ":", -- strempty(t->options)); -- } -+ fprintf(f, "%sTemporaryFileSystem: %s%s%s\n", prefix, -+ t->path, -+ isempty(t->options) ? "" : ":", -+ strempty(t->options)); -+ } - - if (c->utmp_id) - fprintf(f, -@@ -4933,7 +5498,6 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - - if (c->syscall_filter) { - #if HAVE_SECCOMP -- Iterator j; - void *id, *val; - bool first = true; - #endif -@@ -4946,7 +5510,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - fputc('~', f); - - #if HAVE_SECCOMP -- HASHMAP_FOREACH_KEY(val, id, c->syscall_filter, j) { -+ HASHMAP_FOREACH_KEY(val, id, c->syscall_filter) { - _cleanup_free_ char *name = NULL; - const char *errno_name = NULL; - int num = PTR_TO_INT(val); -@@ -4960,7 +5524,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - fputs(strna(name), f); - - if (num >= 0) { -- errno_name = errno_to_name(num); -+ errno_name = seccomp_errno_or_action_to_string(num); - if (errno_name) - fprintf(f, ":%s", errno_name); - else -@@ -4974,7 +5538,6 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - - if (c->syscall_archs) { - #if HAVE_SECCOMP -- Iterator j; - void *id; - #endif - -@@ -4983,7 +5546,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - prefix); - - #if HAVE_SECCOMP -- SET_FOREACH(id, c->syscall_archs, j) -+ SET_FOREACH(id, c->syscall_archs) - fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1))); - #endif - fputc('\n', f); -@@ -5004,15 +5567,35 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { - prefix, c->network_namespace_path); - - if (c->syscall_errno > 0) { -+#if HAVE_SECCOMP - const char *errno_name; -+#endif - - fprintf(f, "%sSystemCallErrorNumber: ", prefix); - -- errno_name = errno_to_name(c->syscall_errno); -+#if HAVE_SECCOMP -+ errno_name = seccomp_errno_or_action_to_string(c->syscall_errno); - if (errno_name) -- fprintf(f, "%s\n", errno_name); -+ fputs(errno_name, f); - else -- fprintf(f, "%d\n", c->syscall_errno); -+ fprintf(f, "%d", c->syscall_errno); -+#endif -+ fputc('\n', f); -+ } -+ -+ for (size_t i = 0; i < c->n_mount_images; i++) { -+ MountOptions *o; -+ -+ fprintf(f, "%sMountImages: %s%s:%s%s", prefix, -+ c->mount_images[i].ignore_enoent ? "-": "", -+ c->mount_images[i].source, -+ c->mount_images[i].destination, -+ LIST_IS_EMPTY(c->mount_images[i].mount_options) ? "": ":"); -+ LIST_FOREACH(mount_options, o, c->mount_images[i].mount_options) -+ fprintf(f, "%s:%s", -+ partition_designator_to_string(o->partition_designator), -+ o->options); -+ fprintf(f, "\n"); - } - } - -@@ -5047,11 +5630,9 @@ int exec_context_get_effective_ioprio(const ExecContext *c) { - } - - void exec_context_free_log_extra_fields(ExecContext *c) { -- size_t l; -- - assert(c); - -- for (l = 0; l < c->n_log_extra_fields; l++) -+ for (size_t l = 0; l < c->n_log_extra_fields; l++) - free(c->log_extra_fields[l].iov_base); - c->log_extra_fields = mfree(c->log_extra_fields); - c->n_log_extra_fields = 0; -@@ -5088,14 +5669,13 @@ int exec_context_get_clean_directories( - char ***ret) { - - _cleanup_strv_free_ char **l = NULL; -- ExecDirectoryType t; - int r; - - assert(c); - assert(prefix); - assert(ret); - -- for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { -+ for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { - char **i; - - if (!FLAGS_SET(mask, 1U << t)) -@@ -5534,13 +6114,12 @@ ExecRuntime *exec_runtime_unref(ExecRuntime *rt, bool destroy) { - - int exec_runtime_serialize(const Manager *m, FILE *f, FDSet *fds) { - ExecRuntime *rt; -- Iterator i; - - assert(m); - assert(f); - assert(fds); - -- HASHMAP_FOREACH(rt, m->exec_runtime_by_id, i) { -+ HASHMAP_FOREACH(rt, m->exec_runtime_by_id) { - fprintf(f, "exec-runtime=%s", rt->id); - - if (rt->tmp_dir) -@@ -5715,8 +6294,13 @@ int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) { - - n = strcspn(v, " "); - buf = strndupa(v, n); -- if (safe_atoi(buf, &fdpair[0]) < 0 || !fdset_contains(fds, fdpair[0])) -- return log_debug("Unable to process exec-runtime netns fd specification."); -+ -+ r = safe_atoi(buf, &fdpair[0]); -+ if (r < 0) -+ return log_debug_errno(r, "Unable to parse exec-runtime specification netns-socket-0=%s: %m", buf); -+ if (!fdset_contains(fds, fdpair[0])) -+ return log_debug_errno(SYNTHETIC_ERRNO(EBADF), -+ "exec-runtime specification netns-socket-0= refers to unknown fd %d: %m", fdpair[0]); - fdpair[0] = fdset_remove(fds, fdpair[0]); - if (v[n] != ' ') - goto finalize; -@@ -5729,8 +6313,12 @@ int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) { - - n = strcspn(v, " "); - buf = strndupa(v, n); -- if (safe_atoi(buf, &fdpair[1]) < 0 || !fdset_contains(fds, fdpair[1])) -- return log_debug("Unable to process exec-runtime netns fd specification."); -+ r = safe_atoi(buf, &fdpair[1]); -+ if (r < 0) -+ return log_debug_errno(r, "Unable to parse exec-runtime specification netns-socket-1=%s: %m", buf); -+ if (!fdset_contains(fds, fdpair[0])) -+ return log_debug_errno(SYNTHETIC_ERRNO(EBADF), -+ "exec-runtime specification netns-socket-1= refers to unknown fd %d: %m", fdpair[1]); - fdpair[1] = fdset_remove(fds, fdpair[1]); - } - -@@ -5743,13 +6331,12 @@ finalize: - - void exec_runtime_vacuum(Manager *m) { - ExecRuntime *rt; -- Iterator i; - - assert(m); - - /* Free unreferenced ExecRuntime objects. This is used after manager deserialization process. */ - -- HASHMAP_FOREACH(rt, m->exec_runtime_by_id, i) { -+ HASHMAP_FOREACH(rt, m->exec_runtime_by_id) { - if (rt->n_ref > 0) - continue; - -@@ -5767,6 +6354,17 @@ void exec_params_clear(ExecParameters *p) { - p->exec_fd = safe_close(p->exec_fd); - } - -+ExecSetCredential *exec_set_credential_free(ExecSetCredential *sc) { -+ if (!sc) -+ return NULL; -+ -+ free(sc->id); -+ free(sc->data); -+ return mfree(sc); -+} -+ -+DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(exec_set_credential_hash_ops, char, string_hash_func, string_compare_func, ExecSetCredential, exec_set_credential_free); -+ - static const char* const exec_input_table[_EXEC_INPUT_MAX] = { - [EXEC_INPUT_NULL] = "null", - [EXEC_INPUT_TTY] = "tty", -diff --git a/src/core/execute.h b/src/core/execute.h -index fc7bc5c..02a2c8d 100644 ---- a/src/core/execute.h -+++ b/src/core/execute.h -@@ -145,6 +145,13 @@ typedef enum ExecCleanMask { - _EXEC_CLEAN_MASK_INVALID = -1, - } ExecCleanMask; - -+/* A credential configured with SetCredential= */ -+typedef struct ExecSetCredential { -+ char *id; -+ void *data; -+ size_t size; -+} ExecSetCredential; -+ - /* Encodes configuration parameters applied to invoked commands. Does not carry runtime data, but only configuration - * changes sourced from unit files and suchlike. ExecContext objects are usually embedded into Unit objects, and do not - * change after being loaded. */ -@@ -158,6 +165,7 @@ struct ExecContext { - char *working_directory, *root_directory, *root_image, *root_verity, *root_hash_path, *root_hash_sig_path; - void *root_hash, *root_hash_sig; - size_t root_hash_size, root_hash_sig_size; -+ LIST_HEAD(MountOptions, root_image_options); - bool working_directory_missing_ok:1; - bool working_directory_home:1; - -@@ -238,6 +246,8 @@ struct ExecContext { - size_t n_bind_mounts; - TemporaryFileSystem *temporary_filesystems; - size_t n_temporary_filesystems; -+ MountImage *mount_images; -+ size_t n_mount_images; - - uint64_t capability_bounding_set; - uint64_t capability_ambient_set; -@@ -257,6 +267,9 @@ struct ExecContext { - - char *log_namespace; - -+ ProtectProc protect_proc; /* hidepid= */ -+ ProcSubset proc_subset; /* subset= */ -+ - bool private_tmp; - bool private_network; - bool private_devices; -@@ -289,6 +302,9 @@ struct ExecContext { - int syscall_errno; - bool syscall_allow_list:1; - -+ Hashmap *syscall_log; -+ bool syscall_log_allow_list:1; /* Log listed system calls */ -+ - bool address_families_allow_list:1; - Set *address_families; - -@@ -297,6 +313,9 @@ struct ExecContext { - ExecDirectory directories[_EXEC_DIRECTORY_TYPE_MAX]; - ExecPreserveMode runtime_directory_preserve_mode; - usec_t timeout_clean_usec; -+ -+ Hashmap *set_credentials; /* output id → ExecSetCredential */ -+ char **load_credentials; /* pairs of output id, path/input id */ - }; - - static inline bool exec_context_restrict_namespaces_set(const ExecContext *c) { -@@ -315,11 +334,12 @@ typedef enum ExecFlags { - EXEC_CGROUP_DELEGATE = 1 << 6, - EXEC_IS_CONTROL = 1 << 7, - EXEC_CONTROL_CGROUP = 1 << 8, /* Place the process not in the indicated cgroup but in a subcgroup '/.control', but only EXEC_CGROUP_DELEGATE and EXEC_IS_CONTROL is set, too */ -+ EXEC_WRITE_CREDENTIALS = 1 << 9, /* Set up the credential store logic */ - - /* The following are not used by execute.c, but by consumers internally */ -- EXEC_PASS_FDS = 1 << 9, -- EXEC_SETENV_RESULT = 1 << 10, -- EXEC_SET_WATCHDOG = 1 << 11, -+ EXEC_PASS_FDS = 1 << 10, -+ EXEC_SETENV_RESULT = 1 << 11, -+ EXEC_SET_WATCHDOG = 1 << 12, - } ExecFlags; - - /* Parameters for a specific invocation of a command. This structure is put together right before a command is -@@ -339,6 +359,7 @@ struct ExecParameters { - const char *cgroup_path; - - char **prefix; -+ const char *received_credentials; - - const char *confirm_spawn; - -@@ -380,6 +401,7 @@ void exec_context_done(ExecContext *c); - void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix); - - int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_root); -+int exec_context_destroy_credentials(const ExecContext *c, const char *runtime_root, const char *unit); - - const char* exec_context_fdname(const ExecContext *c, int fd_index); - -@@ -412,6 +434,11 @@ void exec_params_clear(ExecParameters *p); - - bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c); - -+ExecSetCredential *exec_set_credential_free(ExecSetCredential *sc); -+DEFINE_TRIVIAL_CLEANUP_FUNC(ExecSetCredential*, exec_set_credential_free); -+ -+extern const struct hash_ops exec_set_credential_hash_ops; -+ - const char* exec_output_to_string(ExecOutput i) _const_; - ExecOutput exec_output_from_string(const char *s) _pure_; - -diff --git a/src/core/job.c b/src/core/job.c -index d97cb64..063f3f7 100644 ---- a/src/core/job.c -+++ b/src/core/job.c -@@ -458,7 +458,6 @@ int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) { - } - - static bool job_is_runnable(Job *j) { -- Iterator i; - Unit *other; - void *v; - -@@ -482,7 +481,7 @@ static bool job_is_runnable(Job *j) { - if (j->type == JOB_NOP) - return true; - -- HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) -+ HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER]) - if (other->job && job_compare(j, other->job, UNIT_AFTER) > 0) { - log_unit_debug(j->unit, - "starting held back, waiting for: %s", -@@ -490,7 +489,7 @@ static bool job_is_runnable(Job *j) { - return false; - } - -- HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) -+ HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE]) - if (other->job && job_compare(j, other->job, UNIT_BEFORE) > 0) { - log_unit_debug(j->unit, - "stopping held back, waiting for: %s", -@@ -957,12 +956,11 @@ static void job_emit_done_status_message(Unit *u, uint32_t job_id, JobType t, Jo - - static void job_fail_dependencies(Unit *u, UnitDependency d) { - Unit *other; -- Iterator i; - void *v; - - assert(u); - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[d], i) { -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[d]) { - Job *j = other->job; - - if (!j) -@@ -978,7 +976,6 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr - Unit *u; - Unit *other; - JobType t; -- Iterator i; - void *v; - - assert(j); -@@ -1072,12 +1069,12 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr - - finish: - /* Try to start the next jobs that can be started */ -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_AFTER], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_AFTER]) - if (other->job) { - job_add_to_run_queue(other->job); - job_add_to_gc_queue(other->job); - } -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BEFORE], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BEFORE]) - if (other->job) { - job_add_to_run_queue(other->job); - job_add_to_gc_queue(other->job); -@@ -1427,7 +1424,6 @@ int job_get_timeout(Job *j, usec_t *timeout) { - - bool job_may_gc(Job *j) { - Unit *other; -- Iterator i; - void *v; - - assert(j); -@@ -1457,11 +1453,11 @@ bool job_may_gc(Job *j) { - return false; - - /* The logic is inverse to job_is_runnable, we cannot GC as long as we block any job. */ -- HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) -+ HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE]) - if (other->job && job_compare(j, other->job, UNIT_BEFORE) < 0) - return false; - -- HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) -+ HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER]) - if (other->job && job_compare(j, other->job, UNIT_AFTER) < 0) - return false; - -@@ -1508,7 +1504,6 @@ int job_get_before(Job *j, Job*** ret) { - _cleanup_free_ Job** list = NULL; - size_t n = 0, n_allocated = 0; - Unit *other = NULL; -- Iterator i; - void *v; - - /* Returns a list of all pending jobs that need to finish before this job may be started. */ -@@ -1521,7 +1516,7 @@ int job_get_before(Job *j, Job*** ret) { - return 0; - } - -- HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) { -+ HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER]) { - if (!other->job) - continue; - if (job_compare(j, other->job, UNIT_AFTER) <= 0) -@@ -1532,7 +1527,7 @@ int job_get_before(Job *j, Job*** ret) { - list[n++] = other->job; - } - -- HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) { -+ HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE]) { - if (!other->job) - continue; - if (job_compare(j, other->job, UNIT_BEFORE) <= 0) -@@ -1555,14 +1550,13 @@ int job_get_after(Job *j, Job*** ret) { - size_t n = 0, n_allocated = 0; - Unit *other = NULL; - void *v; -- Iterator i; - - assert(j); - assert(ret); - - /* Returns a list of all pending jobs that are waiting for this job to finish. */ - -- HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) { -+ HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE]) { - if (!other->job) - continue; - -@@ -1577,7 +1571,7 @@ int job_get_after(Job *j, Job*** ret) { - list[n++] = other->job; - } - -- HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) { -+ HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER]) { - if (!other->job) - continue; - -diff --git a/src/core/killall.c b/src/core/killall.c -index 075c705..0272fdb 100644 ---- a/src/core/killall.c -+++ b/src/core/killall.c -@@ -79,10 +79,9 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) { - - static void log_children_no_yet_killed(Set *pids) { - _cleanup_free_ char *lst_child = NULL; -- Iterator i; - void *p; - -- SET_FOREACH(p, pids, i) { -+ SET_FOREACH(p, pids) { - _cleanup_free_ char *s = NULL; - - if (get_process_comm(PTR_TO_PID(p), &s) < 0) -@@ -121,7 +120,6 @@ static int wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) { - struct timespec ts; - int k; - void *p; -- Iterator i; - - /* First, let the kernel inform us about killed - * children. Most processes will probably be our -@@ -145,7 +143,7 @@ static int wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) { - - /* Now explicitly check who might be remaining, who - * might not be our child. */ -- SET_FOREACH(p, pids, i) { -+ SET_FOREACH(p, pids) { - - /* kill(pid, 0) sends no signal, but it tells - * us whether the process still exists. */ -diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 -index 12ae78e..c60d565 100644 ---- a/src/core/load-fragment-gperf.gperf.m4 -+++ b/src/core/load-fragment-gperf.gperf.m4 -@@ -23,9 +23,11 @@ m4_define(`EXEC_CONTEXT_CONFIG_ITEMS', - `$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context) - $1.RootDirectory, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_directory) - $1.RootImage, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_image) -+$1.RootImageOptions, config_parse_root_image_options, 0, offsetof($1, exec_context) - $1.RootHash, config_parse_exec_root_hash, 0, offsetof($1, exec_context) - $1.RootHashSignature, config_parse_exec_root_hash_sig, 0, offsetof($1, exec_context) - $1.RootVerity, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_verity) -+$1.MountImages, config_parse_mount_images, 0, offsetof($1, exec_context) - $1.User, config_parse_user_group_compat, 0, offsetof($1, exec_context.user) - $1.Group, config_parse_user_group_compat, 0, offsetof($1, exec_context.group) - $1.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof($1, exec_context.supplementary_groups) -@@ -71,10 +73,13 @@ $1.AmbientCapabilities, config_parse_capability_set, 0, - $1.TimerSlackNSec, config_parse_nsec, 0, offsetof($1, exec_context.timer_slack_nsec) - $1.NoNewPrivileges, config_parse_bool, 0, offsetof($1, exec_context.no_new_privileges) - $1.KeyringMode, config_parse_exec_keyring_mode, 0, offsetof($1, exec_context.keyring_mode) -+$1.ProtectProc, config_parse_protect_proc, 0, offsetof($1, exec_context.protect_proc) -+$1.ProcSubset, config_parse_proc_subset, 0, offsetof($1, exec_context.proc_subset) - m4_ifdef(`HAVE_SECCOMP', - `$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context) - $1.SystemCallArchitectures, config_parse_syscall_archs, 0, offsetof($1, exec_context.syscall_archs) - $1.SystemCallErrorNumber, config_parse_syscall_errno, 0, offsetof($1, exec_context) -+$1.SystemCallLog, config_parse_syscall_log, 0, offsetof($1, exec_context) - $1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute) - $1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context) - $1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime) -@@ -84,6 +89,7 @@ $1.LockPersonality, config_parse_bool, 0, - `$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 - $1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 - $1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 -+$1.SystemCallLog, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 - $1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 - $1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 - $1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 -@@ -143,6 +149,8 @@ $1.LogsDirectoryMode, config_parse_mode, 0, - $1.LogsDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].paths) - $1.ConfigurationDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].mode) - $1.ConfigurationDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].paths) -+$1.SetCredential, config_parse_set_credential, 0, offsetof($1, exec_context) -+$1.LoadCredential, config_parse_load_credential, 0, offsetof($1, exec_context) - $1.TimeoutCleanSec, config_parse_sec, 0, offsetof($1, exec_context.timeout_clean_usec) - $1.ProtectHostname, config_parse_bool, 0, offsetof($1, exec_context.protect_hostname) - m4_ifdef(`HAVE_PAM', -@@ -263,53 +271,58 @@ Unit.SuccessAction, config_parse_emergency_action, 0, - Unit.FailureActionExitStatus, config_parse_exit_status, 0, offsetof(Unit, failure_action_exit_status) - Unit.SuccessActionExitStatus, config_parse_exit_status, 0, offsetof(Unit, success_action_exit_status) - Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg) --m4_dnl Also add any conditions to condition_definitions[] in src/analyze/analyze-condition.c. - 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) - Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, conditions) - Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, conditions) - Unit.ConditionPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, conditions) -+Unit.ConditionPathIsEncrypted, config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED, offsetof(Unit, conditions) - Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, conditions) - Unit.ConditionFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, conditions) - Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, conditions) - Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions) - Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions) --Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions) --Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions) - Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions) - Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions) -+Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions) -+Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions) -+Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions) - Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions) - Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, conditions) --Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions) - Unit.ConditionACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, conditions) -+Unit.ConditionMemory, config_parse_unit_condition_string, CONDITION_MEMORY, offsetof(Unit, conditions) -+Unit.ConditionCPUs, config_parse_unit_condition_string, CONDITION_CPUS, offsetof(Unit, conditions) -+Unit.ConditionEnvironment, config_parse_unit_condition_string, CONDITION_ENVIRONMENT, offsetof(Unit, conditions) - Unit.ConditionUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, conditions) - Unit.ConditionGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, conditions) --Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions) --Unit.ConditionNull, config_parse_unit_condition_null, 0, offsetof(Unit, conditions) -+Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions) - Unit.AssertPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, asserts) - Unit.AssertPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, asserts) - Unit.AssertPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, asserts) - Unit.AssertPathIsSymbolicLink, config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, asserts) - Unit.AssertPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, asserts) - Unit.AssertPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, asserts) -+Unit.AssertPathIsEncrypted, config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED, offsetof(Unit, asserts) - Unit.AssertDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, asserts) - Unit.AssertFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, asserts) - Unit.AssertFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, asserts) - Unit.AssertNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, asserts) - Unit.AssertFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, asserts) --Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts) --Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts) - Unit.AssertArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, asserts) - Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts) -+Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts) -+Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts) -+Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts) - Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts) - Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, asserts) --Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts) - Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts) -+Unit.AssertMemory, config_parse_unit_condition_string, CONDITION_MEMORY, offsetof(Unit, asserts) -+Unit.AssertCPUs, config_parse_unit_condition_string, CONDITION_CPUS, offsetof(Unit, asserts) -+Unit.AssertEnvironment, config_parse_unit_condition_string, CONDITION_ENVIRONMENT, offsetof(Unit, asserts) - Unit.AssertUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, asserts) - Unit.AssertGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, asserts) --Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts) --Unit.AssertNull, config_parse_unit_condition_null, 0, offsetof(Unit, asserts) -+Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts) - Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode) - m4_dnl - Service.PIDFile, config_parse_pid_file, 0, offsetof(Service, pid_file) -@@ -380,6 +393,7 @@ Socket.SocketGroup, config_parse_user_group_compat, 0, - Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode) - Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode) - Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept) -+Socket.FlushPending, config_parse_bool, 0, offsetof(Socket, flush_pending) - Socket.Writable, config_parse_bool, 0, offsetof(Socket, writable) - Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections) - Socket.MaxConnectionsPerSource, config_parse_unsigned, 0, offsetof(Socket, max_connections_per_source) -diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c -index 3036aa8..8630ef0 100644 ---- a/src/core/load-fragment.c -+++ b/src/core/load-fragment.c -@@ -60,6 +60,7 @@ - #include "unit-name.h" - #include "unit-printf.h" - #include "user-util.h" -+#include "utf8.h" - #include "web-util.h" - - static int parse_socket_protocol(const char *s) { -@@ -118,6 +119,8 @@ DEFINE_CONFIG_PARSE(config_parse_exec_secure_bits, secure_bits_from_string, "Fai - DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode"); - DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy"); - DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode"); -+DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_proc, protect_proc, ProtectProc, "Failed to parse /proc/ protection mode"); -+DEFINE_CONFIG_PARSE_ENUM(config_parse_proc_subset, proc_subset, ProcSubset, "Failed to parse /proc/ subset mode"); - DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode"); - DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode"); - DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier"); -@@ -151,39 +154,35 @@ int config_parse_unit_deps( - - UnitDependency d = ltype; - Unit *u = userdata; -- const char *p; - - assert(filename); - assert(lvalue); - assert(rvalue); - -- p = rvalue; -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - int r; - - r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE); - if (r == 0) -- break; -+ return 0; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); -- break; -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); -+ return 0; - } - - r = unit_name_printf(u, word, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); - continue; - } - - r = unit_add_dependency_by_name(u, d, k, true, UNIT_DEPENDENCY_FILE); - if (r < 0) -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); - } -- -- return 0; - } - - int config_parse_obsolete_unit_deps( -@@ -227,7 +226,7 @@ int config_parse_unit_string_printf( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -257,7 +256,7 @@ int config_parse_unit_strv_printf( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -288,7 +287,7 @@ int config_parse_unit_path_printf( - - /* Let's not bother with anything that is too long */ - if (strlen(rvalue) >= PATH_MAX) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, fatal ? LOG_ERR : LOG_WARNING, filename, line, 0, - "%s value too long%s.", - lvalue, fatal ? "" : ", ignoring"); - return fatal ? -ENAMETOOLONG : 0; -@@ -296,7 +295,7 @@ int config_parse_unit_path_printf( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, fatal ? LOG_ERR : LOG_WARNING, filename, line, r, - "Failed to resolve unit specifiers in '%s'%s: %m", - rvalue, fatal ? "" : ", ignoring"); - return fatal ? -ENOEXEC : 0; -@@ -320,7 +319,6 @@ int config_parse_unit_path_strv_printf( - char ***x = data; - const Unit *u = userdata; - int r; -- const char *p; - - assert(filename); - assert(lvalue); -@@ -332,7 +330,7 @@ int config_parse_unit_path_strv_printf( - return 0; - } - -- for (p = rvalue;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); -@@ -348,7 +346,7 @@ int config_parse_unit_path_strv_printf( - - r = unit_full_printf(u, word, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to resolve unit specifiers in '%s', ignoring: %m", word); - return 0; - } -@@ -429,7 +427,7 @@ int config_parse_socket_listen( - - r = unit_full_printf(UNIT(s), rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -451,13 +449,13 @@ int config_parse_socket_listen( - - r = unit_full_printf(UNIT(s), rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - - r = socket_address_parse_netlink(&p->address, k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k); - return 0; - } - -@@ -468,7 +466,7 @@ int config_parse_socket_listen( - - r = unit_full_printf(UNIT(s), rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -481,7 +479,7 @@ int config_parse_socket_listen( - r = socket_address_parse_and_warn(&p->address, k); - if (r < 0) { - if (r != -EAFNOSUPPORT) -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k); - return 0; - } - -@@ -495,7 +493,7 @@ int config_parse_socket_listen( - } - - if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Address family not supported, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Address family not supported, ignoring: %s", rvalue); - return 0; - } - -@@ -543,9 +541,9 @@ int config_parse_exec_nice( - r = parse_nice(rvalue, &priority); - if (r < 0) { - if (r == -ERANGE) -- log_syntax(unit, LOG_ERR, filename, line, r, "Nice priority out of range, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Nice priority out of range, ignoring: %s", rvalue); - else -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse nice priority '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -583,9 +581,9 @@ int config_parse_exec_oom_score_adjust( - r = parse_oom_score_adjust(rvalue, &oa); - if (r < 0) { - if (r == -ERANGE) -- log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue); - else -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse the OOM score adjust value '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -759,7 +757,7 @@ int config_parse_exec( - - r = unit_full_printf(u, f, &path); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r, - "Failed to resolve unit specifiers in '%s'%s: %m", - f, ignore ? ", ignoring" : ""); - return ignore ? 0 : -ENOEXEC; -@@ -767,19 +765,19 @@ int config_parse_exec( - - if (isempty(path)) { - /* First word is either "-" or "@" with no command. */ -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0, - "Empty path in command line%s: '%s'", - ignore ? ", ignoring" : "", rvalue); - return ignore ? 0 : -ENOEXEC; - } - if (!string_is_safe(path)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0, - "Executable name contains special characters%s: %s", - ignore ? ", ignoring" : "", path); - return ignore ? 0 : -ENOEXEC; - } - if (endswith(path, "/")) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0, - "Executable path specifies a directory%s: %s", - ignore ? ", ignoring" : "", path); - return ignore ? 0 : -ENOEXEC; -@@ -790,7 +788,7 @@ int config_parse_exec( - bool found = false; - - if (!filename_is_valid(path)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0, - "Neither a valid executable name nor an absolute path%s: %s", - ignore ? ", ignoring" : "", path); - return ignore ? 0 : -ENOEXEC; -@@ -812,7 +810,7 @@ int config_parse_exec( - } - - if (!found) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0, - "Executable \"%s\" not found in path \"%s\"%s", - path, DEFAULT_PATH, ignore ? ", ignoring" : ""); - return ignore ? 0 : -ENOEXEC; -@@ -873,7 +871,7 @@ int config_parse_exec( - - r = unit_full_printf(u, word, &resolved); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r, - "Failed to resolve unit specifiers in %s%s: %m", - word, ignore ? ", ignoring" : ""); - return ignore ? 0 : -ENOEXEC; -@@ -887,7 +885,7 @@ int config_parse_exec( - } - - if (!n || !n[0]) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, 0, - "Empty executable name or zeroeth argument%s: %s", - ignore ? ", ignoring" : "", rvalue); - return ignore ? 0 : -ENOEXEC; -@@ -937,7 +935,7 @@ int config_parse_socket_bindtodevice( - } - - if (!ifname_valid(rvalue)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid interface name, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid interface name, ignoring: %s", rvalue); - return 0; - } - -@@ -975,14 +973,16 @@ int config_parse_exec_input( - _cleanup_free_ char *resolved = NULL; - - r = unit_full_printf(u, n, &resolved); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", n); -+ return 0; -+ } - - if (isempty(resolved)) - resolved = mfree(resolved); - else if (!fdname_is_valid(resolved)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name: %s", resolved); -- return -ENOEXEC; -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid file descriptor name, ignoring: %s", resolved); -+ return 0; - } - - free_and_replace(c->stdio_fdname[STDIN_FILENO], resolved); -@@ -993,12 +993,14 @@ int config_parse_exec_input( - _cleanup_free_ char *resolved = NULL; - - r = unit_full_printf(u, n, &resolved); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", n); -+ return 0; -+ } - - r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue); - if (r < 0) -- return -ENOEXEC; -+ return 0; - - free_and_replace(c->stdio_file[STDIN_FILENO], resolved); - -@@ -1007,7 +1009,7 @@ int config_parse_exec_input( - } else { - ei = exec_input_from_string(rvalue); - if (ei < 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse input specifier, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse input specifier, ignoring: %s", rvalue); - return 0; - } - } -@@ -1048,18 +1050,26 @@ int config_parse_exec_input_text( - } - - r = cunescape(rvalue, 0, &unescaped); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode C escaped text '%s': %m", rvalue); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to decode C escaped text '%s', ignoring: %m", rvalue); -+ return 0; -+ } - - r = unit_full_printf(u, unescaped, &resolved); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", unescaped); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to resolve unit specifiers in '%s', ignoring: %m", unescaped); -+ return 0; -+ } - - sz = strlen(resolved); - if (c->stdin_data_size + sz + 1 < c->stdin_data_size || /* check for overflow */ - c->stdin_data_size + sz + 1 > EXEC_STDIN_DATA_MAX) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Standard input data too large (%zu), maximum of %zu permitted, ignoring.", c->stdin_data_size + sz, (size_t) EXEC_STDIN_DATA_MAX); -- return -E2BIG; -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Standard input data too large (%zu), maximum of %zu permitted, ignoring.", -+ c->stdin_data_size + sz, (size_t) EXEC_STDIN_DATA_MAX); -+ return 0; - } - - p = realloc(c->stdin_data, c->stdin_data_size + sz + 1); -@@ -1105,15 +1115,20 @@ int config_parse_exec_input_data( - } - - r = unbase64mem(rvalue, (size_t) -1, &p, &sz); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode base64 data, ignoring: %s", rvalue); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to decode base64 data, ignoring: %s", rvalue); -+ return 0; -+ } - - assert(sz > 0); - - if (c->stdin_data_size + sz < c->stdin_data_size || /* check for overflow */ - c->stdin_data_size + sz > EXEC_STDIN_DATA_MAX) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Standard input data too large (%zu), maximum of %zu permitted, ignoring.", c->stdin_data_size + sz, (size_t) EXEC_STDIN_DATA_MAX); -- return -E2BIG; -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Standard input data too large (%zu), maximum of %zu permitted, ignoring.", -+ c->stdin_data_size + sz, (size_t) EXEC_STDIN_DATA_MAX); -+ return 0; - } - - q = realloc(c->stdin_data, c->stdin_data_size + sz); -@@ -1157,14 +1172,16 @@ int config_parse_exec_output( - n = startswith(rvalue, "fd:"); - if (n) { - r = unit_full_printf(u, n, &resolved); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n); -+ return 0; -+ } - - if (isempty(resolved)) - resolved = mfree(resolved); - else if (!fdname_is_valid(resolved)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name: %s", resolved); -- return -ENOEXEC; -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid file descriptor name, ignoring: %s", resolved); -+ return 0; - } - - eo = EXEC_OUTPUT_NAMED_FD; -@@ -1180,30 +1197,34 @@ int config_parse_exec_output( - } else if ((n = startswith(rvalue, "file:"))) { - - r = unit_full_printf(u, n, &resolved); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n); -+ return 0; -+ } - - r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue); - if (r < 0) -- return -ENOEXEC; -+ return 0; - - eo = EXEC_OUTPUT_FILE; - - } else if ((n = startswith(rvalue, "append:"))) { - - r = unit_full_printf(u, n, &resolved); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n); -+ return 0; -+ } - - r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue); - if (r < 0) -- return -ENOEXEC; -+ return 0; - - eo = EXEC_OUTPUT_FILE_APPEND; - } else { - eo = exec_output_from_string(rvalue); - if (eo < 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output specifier, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse output specifier, ignoring: %s", rvalue); - return 0; - } - } -@@ -1262,7 +1283,7 @@ int config_parse_exec_io_class(const char *unit, - - x = ioprio_class_from_string(rvalue); - if (x < 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IO scheduling class, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse IO scheduling class, ignoring: %s", rvalue); - return 0; - } - -@@ -1299,7 +1320,7 @@ int config_parse_exec_io_priority(const char *unit, - - r = ioprio_parse_priority(rvalue, &i); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue); - return 0; - } - -@@ -1337,7 +1358,7 @@ int config_parse_exec_cpu_sched_policy(const char *unit, - - x = sched_policy_from_string(rvalue); - if (x < 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue); - return 0; - } - -@@ -1367,13 +1388,18 @@ int config_parse_numa_mask(const char *unit, - assert(rvalue); - assert(data); - -- r = parse_cpu_set_extend(rvalue, &p->nodes, true, unit, filename, line, lvalue); -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse NUMA node mask, ignoring: %s", rvalue); -- return 0; -+ if (streq(rvalue, "all")) { -+ r = numa_mask_add_all(&p->nodes); -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to create NUMA mask representing \"all\" NUMA nodes, ignoring: %m"); -+ } else { -+ r = parse_cpu_set_extend(rvalue, &p->nodes, true, unit, filename, line, lvalue); -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse NUMA node mask, ignoring: %s", rvalue); - } - -- return r; -+ return 0; - } - - int config_parse_exec_cpu_sched_prio(const char *unit, -@@ -1397,7 +1423,7 @@ int config_parse_exec_cpu_sched_prio(const char *unit, - - r = safe_atoi(rvalue, &i); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU scheduling priority, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse CPU scheduling priority, ignoring: %s", rvalue); - return 0; - } - -@@ -1406,7 +1432,7 @@ int config_parse_exec_cpu_sched_prio(const char *unit, - max = sched_get_priority_max(c->cpu_sched_policy); - - if (i < min || i > max) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "CPU scheduling priority is out of range, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "CPU scheduling priority is out of range, ignoring: %s", rvalue); - return 0; - } - -@@ -1416,6 +1442,86 @@ int config_parse_exec_cpu_sched_prio(const char *unit, - return 0; - } - -+int config_parse_root_image_options( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ -+ _cleanup_(mount_options_free_allp) MountOptions *options = NULL; -+ _cleanup_strv_free_ char **l = NULL; -+ char **first = NULL, **second = NULL; -+ ExecContext *c = data; -+ const Unit *u = userdata; -+ int r; -+ -+ assert(filename); -+ assert(lvalue); -+ assert(rvalue); -+ assert(data); -+ -+ if (isempty(rvalue)) { -+ c->root_image_options = mount_options_free_all(c->root_image_options); -+ return 0; -+ } -+ -+ r = strv_split_colon_pairs(&l, rvalue); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue); -+ return 0; -+ } -+ -+ STRV_FOREACH_PAIR(first, second, l) { -+ MountOptions *o = NULL; -+ _cleanup_free_ char *mount_options_resolved = NULL; -+ const char *mount_options = NULL, *partition = "root"; -+ PartitionDesignator partition_designator; -+ -+ /* Format is either 'root:foo' or 'foo' (root is implied) */ -+ if (!isempty(*second)) { -+ partition = *first; -+ mount_options = *second; -+ } else -+ mount_options = *first; -+ -+ partition_designator = partition_designator_from_string(partition); -+ if (partition_designator < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid partition name %s, ignoring", partition); -+ continue; -+ } -+ r = unit_full_printf(u, mount_options, &mount_options_resolved); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", mount_options); -+ continue; -+ } -+ -+ o = new(MountOptions, 1); -+ if (!o) -+ return log_oom(); -+ *o = (MountOptions) { -+ .partition_designator = partition_designator, -+ .options = TAKE_PTR(mount_options_resolved), -+ }; -+ LIST_APPEND(mount_options, options, TAKE_PTR(o)); -+ } -+ -+ /* empty spaces/separators only */ -+ if (LIST_IS_EMPTY(options)) -+ c->root_image_options = mount_options_free_all(c->root_image_options); -+ else -+ LIST_JOIN(mount_options, c->root_image_options, options); -+ -+ return 0; -+} -+ - int config_parse_exec_root_hash( - const char *unit, - const char *filename, -@@ -1462,10 +1568,14 @@ int config_parse_exec_root_hash( - - /* We have a roothash to decode, eg: RootHash=012345789abcdef */ - r = unhexmem(rvalue, strlen(rvalue), &roothash_decoded, &roothash_decoded_size); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode RootHash=, ignoring: %s", rvalue); -- if (roothash_decoded_size < sizeof(sd_id128_t)) -- return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "RootHash= is too short, ignoring: %s", rvalue); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to decode RootHash=, ignoring: %s", rvalue); -+ return 0; -+ } -+ if (roothash_decoded_size < sizeof(sd_id128_t)) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "RootHash= is too short, ignoring: %s", rvalue); -+ return 0; -+ } - - free_and_replace(c->root_hash, roothash_decoded); - c->root_hash_size = roothash_decoded_size; -@@ -1511,7 +1621,7 @@ int config_parse_exec_root_hash_sig( - - p = strdup(rvalue); - if (!p) -- return -ENOMEM; -+ return log_oom(); - - free_and_replace(c->root_hash_sig_path, p); - c->root_hash_sig = mfree(c->root_hash_sig); -@@ -1519,13 +1629,18 @@ int config_parse_exec_root_hash_sig( - return 0; - } - -- if (!(value = startswith(rvalue, "base64:"))) -- return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Failed to decode RootHashSignature=, not a path but doesn't start with 'base64:', ignoring: %s", rvalue); -+ if (!(value = startswith(rvalue, "base64:"))) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Failed to decode RootHashSignature=, not a path but doesn't start with 'base64:', ignoring: %s", rvalue); -+ return 0; -+ } - - /* We have a roothash signature to decode, eg: RootHashSignature=base64:012345789abcdef */ - r = unbase64mem(value, strlen(value), &roothash_sig_decoded, &roothash_sig_decoded_size); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode RootHashSignature=, ignoring: %s", rvalue); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to decode RootHashSignature=, ignoring: %s", rvalue); -+ return 0; -+ } - - free_and_replace(c->root_hash_sig, roothash_sig_decoded); - c->root_hash_sig_size = roothash_sig_decoded_size; -@@ -1600,7 +1715,7 @@ int config_parse_capability_set( - - r = capability_set_from_string(rvalue, &sum); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= specifier '%s', ignoring: %m", lvalue, rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= specifier '%s', ignoring: %m", lvalue, rvalue); - return 0; - } - -@@ -1655,7 +1770,7 @@ int config_parse_exec_selinux_context( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r, - "Failed to resolve unit specifiers in '%s'%s: %m", - rvalue, ignore ? ", ignoring" : ""); - return ignore ? 0 : -ENOEXEC; -@@ -1704,7 +1819,7 @@ int config_parse_exec_apparmor_profile( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r, - "Failed to resolve unit specifiers in '%s'%s: %m", - rvalue, ignore ? ", ignoring" : ""); - return ignore ? 0 : -ENOEXEC; -@@ -1753,7 +1868,7 @@ int config_parse_exec_smack_process_label( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r, - "Failed to resolve unit specifiers in '%s'%s: %m", - rvalue, ignore ? ", ignoring" : ""); - return ignore ? 0 : -ENOEXEC; -@@ -1798,20 +1913,20 @@ int config_parse_timer( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - - if (ltype == TIMER_CALENDAR) { - r = calendar_spec_from_string(k, &c); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse calendar specification, ignoring: %s", k); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse calendar specification, ignoring: %s", k); - return 0; - } - } else { - r = parse_sec(k, &usec); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse timer value, ignoring: %s", k); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse timer value, ignoring: %s", k); - return 0; - } - } -@@ -1854,29 +1969,29 @@ int config_parse_trigger_unit( - assert(data); - - if (!hashmap_isempty(u->dependencies[UNIT_TRIGGERS])) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Multiple units to trigger specified, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Multiple units to trigger specified, ignoring: %s", rvalue); - return 0; - } - - r = unit_name_printf(u, rvalue, &p); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); - return 0; - } - - type = unit_name_to_type(p); - if (type < 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Unit type not valid, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Unit type not valid, ignoring: %s", rvalue); - return 0; - } - if (unit_has_name(u, p)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Units cannot trigger themselves, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Units cannot trigger themselves, ignoring: %s", rvalue); - return 0; - } - - r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, true, UNIT_DEPENDENCY_FILE); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add trigger on %s, ignoring: %m", p); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to add trigger on %s, ignoring: %m", p); - return 0; - } - -@@ -1913,13 +2028,13 @@ int config_parse_path_spec(const char *unit, - - b = path_type_from_string(lvalue); - if (b < 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse path type, ignoring: %s", lvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse path type, ignoring: %s", lvalue); - return 0; - } - - r = unit_full_printf(UNIT(p), rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); - return 0; - } - -@@ -1966,19 +2081,19 @@ int config_parse_socket_service( - - r = unit_name_printf(UNIT(s), rvalue, &p); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue); -- return -ENOEXEC; -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); -+ return 0; - } - - if (!endswith(p, ".service")) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service: %s", rvalue); -- return -ENOEXEC; -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Unit must be of type service, ignoring: %s", rvalue); -+ return 0; - } - - r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s: %s", rvalue, bus_error_message(&error, r)); -- return -ENOEXEC; -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r)); -+ return 0; - } - - unit_ref_set(&s->service, UNIT(s), x); -@@ -2014,12 +2129,12 @@ int config_parse_fdname( - - r = unit_full_printf(UNIT(s), rvalue, &p); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - - if (!fdname_is_valid(p)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", p); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid file descriptor name, ignoring: %s", p); - return 0; - } - -@@ -2039,7 +2154,6 @@ int config_parse_service_sockets( - void *userdata) { - - Service *s = data; -- const char *p; - int r; - - assert(filename); -@@ -2047,41 +2161,38 @@ int config_parse_service_sockets( - assert(rvalue); - assert(data); - -- p = rvalue; -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, 0); - if (r == 0) -- break; -+ return 0; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage in sockets, ignoring: %s", rvalue); -- break; -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Trailing garbage in sockets, ignoring: %s", rvalue); -+ return 0; - } - - r = unit_name_printf(UNIT(s), word, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); - continue; - } - - if (!endswith(k, ".socket")) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type socket, ignoring: %s", k); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Unit must be of type socket, ignoring: %s", k); - continue; - } - - r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, true, UNIT_DEPENDENCY_FILE); - if (r < 0) -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); - - r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, true, UNIT_DEPENDENCY_FILE); - if (r < 0) -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); - } -- -- return 0; - } - - int config_parse_bus_name( -@@ -2107,12 +2218,12 @@ int config_parse_bus_name( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); - return 0; - } - - if (!sd_bus_service_name_is_valid(k)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name, ignoring: %s", k); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid bus name, ignoring: %s", k); - return 0; - } - -@@ -2147,7 +2258,7 @@ int config_parse_service_timeout( - * all other timeouts. */ - r = parse_sec_fix_0(rvalue, &usec); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue); - return 0; - } - -@@ -2189,7 +2300,7 @@ int config_parse_timeout_abort( - - r = parse_sec(rvalue, ret); - if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= setting, ignoring: %s", lvalue, rvalue); -+ return log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= setting, ignoring: %s", lvalue, rvalue); - - return 1; /* "set" */ - } -@@ -2243,10 +2354,8 @@ int config_parse_sec_fix_0( - * timeout. */ - - r = parse_sec_fix_0(rvalue, usec); -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue); -- return 0; -- } -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue); - - return 0; - } -@@ -2315,7 +2424,6 @@ int config_parse_user_group_strv_compat( - - char ***users = data; - const Unit *u = userdata; -- const char *p = rvalue; - int r; - - assert(filename); -@@ -2328,12 +2436,12 @@ int config_parse_user_group_strv_compat( - return 0; - } - -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, 0); - if (r == 0) -- break; -+ return 0; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -@@ -2358,8 +2466,6 @@ int config_parse_user_group_strv_compat( - - k = NULL; - } -- -- return 0; - } - - int config_parse_working_directory( -@@ -2405,7 +2511,7 @@ int config_parse_working_directory( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, missing_ok ? LOG_WARNING : LOG_ERR, filename, line, r, - "Failed to resolve unit specifiers in working directory path '%s'%s: %m", - rvalue, missing_ok ? ", ignoring" : ""); - return missing_ok ? 0 : -ENOEXEC; -@@ -2452,7 +2558,7 @@ int config_parse_unit_env_file(const char *unit, - - r = unit_full_printf(u, rvalue, &n); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -2483,7 +2589,6 @@ int config_parse_environ( - - const Unit *u = userdata; - char ***env = data; -- const char *p; - int r; - - assert(filename); -@@ -2497,7 +2602,7 @@ int config_parse_environ( - return 0; - } - -- for (p = rvalue;; ) { -+ for (const char *p = rvalue;; ) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE); -@@ -2514,7 +2619,7 @@ int config_parse_environ( - if (u) { - r = unit_full_printf(u, word, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to resolve unit specifiers in %s, ignoring: %m", word); - continue; - } -@@ -2522,7 +2627,7 @@ int config_parse_environ( - k = TAKE_PTR(word); - - if (!env_assignment_is_valid(k)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, LOG_WARNING, filename, line, 0, - "Invalid environment assignment, ignoring: %s", k); - continue; - } -@@ -2550,7 +2655,6 @@ int config_parse_pass_environ( - _cleanup_strv_free_ char **n = NULL; - size_t nlen = 0, nbufsize = 0; - char*** passenv = data; -- const char *p = rvalue; - const Unit *u = userdata; - int r; - -@@ -2565,7 +2669,7 @@ int config_parse_pass_environ( - return 0; - } - -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); -@@ -2574,7 +2678,7 @@ int config_parse_pass_environ( - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Trailing garbage in %s, ignoring: %s", lvalue, rvalue); - break; - } -@@ -2582,7 +2686,7 @@ int config_parse_pass_environ( - if (u) { - r = unit_full_printf(u, word, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to resolve specifiers in %s, ignoring: %m", word); - continue; - } -@@ -2590,7 +2694,7 @@ int config_parse_pass_environ( - k = TAKE_PTR(word); - - if (!env_name_is_valid(k)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, LOG_WARNING, filename, line, 0, - "Invalid environment name for %s, ignoring: %s", lvalue, k); - continue; - } -@@ -2626,7 +2730,6 @@ int config_parse_unset_environ( - _cleanup_strv_free_ char **n = NULL; - size_t nlen = 0, nbufsize = 0; - char*** unsetenv = data; -- const char *p = rvalue; - const Unit *u = userdata; - int r; - -@@ -2641,7 +2744,7 @@ int config_parse_unset_environ( - return 0; - } - -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE); -@@ -2650,7 +2753,7 @@ int config_parse_unset_environ( - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Trailing garbage in %s, ignoring: %s", lvalue, rvalue); - break; - } -@@ -2658,7 +2761,7 @@ int config_parse_unset_environ( - if (u) { - r = unit_full_printf(u, word, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to resolve unit specifiers in %s, ignoring: %m", word); - continue; - } -@@ -2666,7 +2769,7 @@ int config_parse_unset_environ( - k = TAKE_PTR(word); - - if (!env_assignment_is_valid(k) && !env_name_is_valid(k)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ log_syntax(unit, LOG_WARNING, filename, line, 0, - "Invalid environment name or assignment %s, ignoring: %s", lvalue, k); - continue; - } -@@ -2701,7 +2804,6 @@ int config_parse_log_extra_fields( - - ExecContext *c = data; - const Unit *u = userdata; -- const char *p = rvalue; - int r; - - assert(filename); -@@ -2714,7 +2816,7 @@ int config_parse_log_extra_fields( - return 0; - } - -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - struct iovec *t; - const char *eq; -@@ -2731,18 +2833,18 @@ int config_parse_log_extra_fields( - - r = unit_full_printf(u, word, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word); - continue; - } - - eq = strchr(k, '='); - if (!eq) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Log field lacks '=' character, ignoring: %s", k); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Log field lacks '=' character, ignoring: %s", k); - continue; - } - - if (!journal_field_valid(k, eq-k, false)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Log field name is invalid, ignoring: %s", k); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Log field name is invalid, ignoring: %s", k); - continue; - } - -@@ -2786,12 +2888,12 @@ int config_parse_log_namespace( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); - return 0; - } - - if (!log_namespace_name_valid(k)) { -- log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Specified log namespace name is not valid: %s", k); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Specified log namespace name is not valid, ignoring: %s", k); - return 0; - } - -@@ -2839,7 +2941,7 @@ int config_parse_unit_condition_path( - - r = unit_full_printf(u, rvalue, &p); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); - return 0; - } - -@@ -2895,7 +2997,7 @@ int config_parse_unit_condition_string( - - r = unit_full_printf(u, rvalue, &s); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } -@@ -2908,60 +3010,6 @@ int config_parse_unit_condition_string( - return 0; - } - --int config_parse_unit_condition_null( -- const char *unit, -- const char *filename, -- unsigned line, -- const char *section, -- unsigned section_line, -- const char *lvalue, -- int ltype, -- const char *rvalue, -- void *data, -- void *userdata) { -- -- Condition **list = data, *c; -- bool trigger, negate; -- int b; -- -- assert(filename); -- assert(lvalue); -- assert(rvalue); -- assert(data); -- -- log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is deprecated, please do not use.", lvalue); -- -- if (isempty(rvalue)) { -- /* Empty assignment resets the list */ -- *list = condition_free_list(*list); -- return 0; -- } -- -- trigger = rvalue[0] == '|'; -- if (trigger) -- rvalue++; -- -- negate = rvalue[0] == '!'; -- if (negate) -- rvalue++; -- -- b = parse_boolean(rvalue); -- if (b < 0) { -- log_syntax(unit, LOG_ERR, filename, line, b, "Failed to parse boolean value in condition, ignoring: %s", rvalue); -- return 0; -- } -- -- if (!b) -- negate = !negate; -- -- c = condition_new(CONDITION_NULL, NULL, trigger, negate); -- if (!c) -- return log_oom(); -- -- LIST_PREPEND(conditions, *list, c); -- return 0; --} -- - int config_parse_unit_requires_mounts_for( - const char *unit, - const char *filename, -@@ -2974,7 +3022,6 @@ int config_parse_unit_requires_mounts_for( - void *data, - void *userdata) { - -- const char *p = rvalue; - Unit *u = userdata; - int r; - -@@ -2983,7 +3030,7 @@ int config_parse_unit_requires_mounts_for( - assert(rvalue); - assert(data); - -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *resolved = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); -@@ -2999,7 +3046,7 @@ int config_parse_unit_requires_mounts_for( - - r = unit_full_printf(u, word, &resolved); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); - continue; - } - -@@ -3009,7 +3056,7 @@ int config_parse_unit_requires_mounts_for( - - r = unit_require_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount '%s', ignoring: %m", resolved); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to add required mount '%s', ignoring: %m", resolved); - continue; - } - } -@@ -3051,7 +3098,7 @@ int config_parse_documentation(const char *unit, - if (documentation_url_is_valid(*a)) - *(b++) = *a; - else { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid URL, ignoring: %s", *a); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid URL, ignoring: %s", *a); - free(*a); - } - } -@@ -3077,7 +3124,6 @@ int config_parse_syscall_filter( - ExecContext *c = data; - _unused_ const Unit *u = userdata; - bool invert = false; -- const char *p; - int r; - - assert(filename); -@@ -3120,8 +3166,7 @@ int config_parse_syscall_filter( - } - } - -- p = rvalue; -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *name = NULL; - int num; - -@@ -3152,7 +3197,7 @@ int config_parse_syscall_filter( - } - } - --int config_parse_syscall_archs( -+int config_parse_syscall_log( - const char *unit, - const char *filename, - unsigned line, -@@ -3164,33 +3209,112 @@ int config_parse_syscall_archs( - void *data, - void *userdata) { - -- const char *p = rvalue; -- Set **archs = data; -+ ExecContext *c = data; -+ _unused_ const Unit *u = userdata; -+ bool invert = false; -+ const char *p; - int r; - -+ assert(filename); -+ assert(lvalue); -+ assert(rvalue); -+ assert(u); -+ - if (isempty(rvalue)) { -- *archs = set_free(*archs); -+ /* Empty assignment resets the list */ -+ c->syscall_log = hashmap_free(c->syscall_log); -+ c->syscall_log_allow_list = false; - return 0; - } - -+ if (rvalue[0] == '~') { -+ invert = true; -+ rvalue++; -+ } -+ -+ if (!c->syscall_log) { -+ c->syscall_log = hashmap_new(NULL); -+ if (!c->syscall_log) -+ return log_oom(); -+ -+ if (invert) -+ /* Log everything but the ones listed */ -+ c->syscall_log_allow_list = false; -+ else -+ /* Log nothing but the ones listed */ -+ c->syscall_log_allow_list = true; -+ } -+ -+ p = rvalue; - for (;;) { -- _cleanup_free_ char *word = NULL; -- uint32_t a; -+ _cleanup_free_ char *word = NULL, *name = NULL; -+ int num; - -- r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); -+ r = extract_first_word(&p, &word, NULL, 0); - if (r == 0) - return 0; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_WARNING, filename, line, r, -- "Invalid syntax, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); -+ return 0; -+ } -+ -+ r = parse_syscall_and_errno(word, &name, &num); -+ if (r < 0 || num >= 0) { /* errno code not allowed */ -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse syscall, ignoring: %s", word); -+ continue; -+ } -+ -+ r = seccomp_parse_syscall_filter( -+ name, 0, c->syscall_log, -+ SECCOMP_PARSE_LOG|SECCOMP_PARSE_PERMISSIVE| -+ (invert ? SECCOMP_PARSE_INVERT : 0)| -+ (c->syscall_log_allow_list ? SECCOMP_PARSE_ALLOW_LIST : 0), -+ unit, filename, line); -+ if (r < 0) -+ return r; -+ } -+} -+ -+int config_parse_syscall_archs( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ -+ Set **archs = data; -+ int r; -+ -+ if (isempty(rvalue)) { -+ *archs = set_free(*archs); -+ return 0; -+ } -+ -+ for (const char *p = rvalue;;) { -+ _cleanup_free_ char *word = NULL; -+ uint32_t a; -+ -+ r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); -+ if (r == 0) -+ return 0; -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Invalid syntax, ignoring: %s", rvalue); - return 0; - } - - r = seccomp_arch_from_string(word, &a); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse system call architecture \"%s\", ignoring: %m", word); - continue; - } -@@ -3220,15 +3344,15 @@ int config_parse_syscall_errno( - assert(lvalue); - assert(rvalue); - -- if (isempty(rvalue)) { -+ if (isempty(rvalue) || streq(rvalue, "kill")) { - /* Empty assignment resets to KILL */ -- c->syscall_errno = 0; -+ c->syscall_errno = SECCOMP_ERROR_NUMBER_KILL; - return 0; - } - - e = parse_errno(rvalue); - if (e <= 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse error number, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse error number, ignoring: %s", rvalue); - return 0; - } - -@@ -3250,7 +3374,6 @@ int config_parse_address_families( - - ExecContext *c = data; - bool invert = false; -- const char *p; - int r; - - assert(filename); -@@ -3277,7 +3400,7 @@ int config_parse_address_families( - c->address_families_allow_list = !invert; - } - -- for (p = rvalue;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL; - int af; - -@@ -3294,7 +3417,7 @@ int config_parse_address_families( - - af = af_from_name(word); - if (af < 0) { -- log_syntax(unit, LOG_ERR, filename, line, af, -+ log_syntax(unit, LOG_WARNING, filename, line, af, - "Failed to parse address family, ignoring: %s", word); - continue; - } -@@ -3352,7 +3475,7 @@ int config_parse_restrict_namespaces( - /* Not a boolean argument, in this case it's a list of namespace types. */ - r = namespace_flags_from_string(rvalue, &flags); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse namespace type string, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse namespace type string, ignoring: %s", rvalue); - return 0; - } - -@@ -3391,19 +3514,19 @@ int config_parse_unit_slice( - - r = unit_name_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); - return 0; - } - - r = manager_load_unit(u->manager, k, NULL, &error, &slice); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load slice unit %s, ignoring: %s", k, bus_error_message(&error, r)); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to load slice unit %s, ignoring: %s", k, bus_error_message(&error, r)); - return 0; - } - - r = unit_set_slice(u, slice); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to assign slice %s to unit %s, ignoring: %m", slice->id, u->id); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to assign slice %s to unit %s, ignoring: %m", slice->id, u->id); - return 0; - } - -@@ -3436,7 +3559,7 @@ int config_parse_cpu_quota( - - r = parse_permille_unbounded(rvalue); - if (r <= 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU quota '%s', ignoring.", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid CPU quota '%s', ignoring.", rvalue); - return 0; - } - -@@ -3509,7 +3632,7 @@ int config_parse_memory_limit( - if (r < 0) { - r = parse_size(rvalue, 1024, &bytes); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid memory limit '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid memory limit '%s', ignoring: %m", rvalue); - return 0; - } - } else -@@ -3517,7 +3640,7 @@ int config_parse_memory_limit( - - if (bytes >= UINT64_MAX || - (bytes <= 0 && !STR_IN_SET(lvalue, "MemorySwapMax", "MemoryLow", "MemoryMin", "DefaultMemoryLow", "DefaultMemoryMin"))) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue); - return 0; - } - } -@@ -3581,12 +3704,12 @@ int config_parse_tasks_max( - else { - r = safe_atou64(rvalue, &v); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid maximum tasks value '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid maximum tasks value '%s', ignoring: %m", rvalue); - return 0; - } - - if (v <= 0 || v >= UINT64_MAX) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue); - return 0; - } - -@@ -3616,7 +3739,7 @@ int config_parse_delegate( - assert(t != _UNIT_TYPE_INVALID); - - if (!unit_vtable[t]->can_delegate) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Delegate= setting not supported for this unit type, ignoring."); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Delegate= setting not supported for this unit type, ignoring."); - return 0; - } - -@@ -3633,10 +3756,9 @@ int config_parse_delegate( - - r = parse_boolean(rvalue); - if (r < 0) { -- const char *p = rvalue; - CGroupMask mask = 0; - -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL; - CGroupController cc; - -@@ -3646,13 +3768,13 @@ int config_parse_delegate( - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); - return 0; - } - - cc = cgroup_controller_from_string(word); - if (cc < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid controller name '%s', ignoring", word); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid controller name '%s', ignoring", word); - continue; - } - -@@ -3725,13 +3847,13 @@ int config_parse_device_allow( - return 0; - - if (!valid_device_node_path(resolved)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s', ignoring.", resolved); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid device node path '%s', ignoring.", resolved); - return 0; - } - } - - if (!isempty(p) && !in_charset(p, "rwm")) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device rights '%s', ignoring.", p); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid device rights '%s', ignoring.", p); - return 0; - } - -@@ -3795,7 +3917,7 @@ int config_parse_io_device_weight( - - r = cg_weight_parse(p, &u); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid, ignoring: %m", p); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "IO weight '%s' invalid, ignoring: %m", p); - return 0; - } - -@@ -3867,8 +3989,9 @@ int config_parse_io_device_latency( - if (r < 0) - return 0; - -- if (parse_sec(p, &usec) < 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", p); -+ r = parse_sec(p, &usec); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse timer value, ignoring: %s", p); - return 0; - } - -@@ -3946,7 +4069,7 @@ int config_parse_io_limit( - else { - r = parse_size(p, 1000, &num); - if (r < 0 || num <= 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid IO limit '%s', ignoring.", p); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid IO limit '%s', ignoring.", p); - return 0; - } - } -@@ -4034,7 +4157,7 @@ int config_parse_blockio_device_weight( - - r = cg_blkio_weight_parse(p, &u); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid block IO weight '%s', ignoring: %m", p); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid block IO weight '%s', ignoring: %m", p); - return 0; - } - -@@ -4112,7 +4235,7 @@ int config_parse_blockio_bandwidth( - - r = parse_size(p, 1000, &bytes); - if (r < 0 || bytes <= 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid Block IO Bandwidth '%s', ignoring.", p); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid Block IO Bandwidth '%s', ignoring.", p); - return 0; - } - -@@ -4164,7 +4287,7 @@ int config_parse_job_mode_isolate( - - r = parse_boolean(rvalue); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse boolean, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse boolean, ignoring: %s", rvalue); - return 0; - } - -@@ -4188,7 +4311,6 @@ int config_parse_exec_directories( - - char***rt = data; - const Unit *u = userdata; -- const char *p; - int r; - - assert(filename); -@@ -4202,7 +4324,7 @@ int config_parse_exec_directories( - return 0; - } - -- for (p = rvalue;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); -@@ -4240,7 +4362,92 @@ int config_parse_exec_directories( - } - } - --int config_parse_set_status( -+int config_parse_set_credential( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ -+ _cleanup_free_ char *word = NULL, *k = NULL, *unescaped = NULL; -+ ExecContext *context = data; -+ ExecSetCredential *old; -+ Unit *u = userdata; -+ const char *p; -+ int r, l; -+ -+ assert(filename); -+ assert(lvalue); -+ assert(rvalue); -+ assert(context); -+ -+ if (isempty(rvalue)) { -+ /* Empty assignment resets the list */ -+ context->set_credentials = hashmap_free(context->set_credentials); -+ return 0; -+ } -+ -+ p = rvalue; -+ r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r <= 0 || !p) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); -+ return 0; -+ } -+ -+ r = unit_full_printf(u, word, &k); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word); -+ return 0; -+ } -+ if (!credential_name_valid(k)) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Credential name \"%s\" not valid, ignoring.", k); -+ return 0; -+ } -+ -+ /* We support escape codes here, so that users can insert trailing \n if they like */ -+ l = cunescape(p, UNESCAPE_ACCEPT_NUL, &unescaped); -+ if (l < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, l, "Can't unescape \"%s\", ignoring: %m", p); -+ return 0; -+ } -+ -+ old = hashmap_get(context->set_credentials, k); -+ if (old) { -+ free_and_replace(old->data, unescaped); -+ old->size = l; -+ } else { -+ _cleanup_(exec_set_credential_freep) ExecSetCredential *sc = NULL; -+ -+ sc = new0(ExecSetCredential, 1); -+ if (!sc) -+ return log_oom(); -+ -+ sc->id = TAKE_PTR(k); -+ sc->data = TAKE_PTR(unescaped); -+ sc->size = l; -+ -+ r = hashmap_ensure_allocated(&context->set_credentials, &exec_set_credential_hash_ops); -+ if (r < 0) -+ return r; -+ -+ r = hashmap_put(context->set_credentials, sc->id, sc); -+ if (r < 0) -+ return log_oom(); -+ -+ TAKE_PTR(sc); -+ } -+ -+ return 0; -+} -+ -+int config_parse_load_credential( - const char *unit, - const char *filename, - unsigned line, -@@ -4252,15 +4459,77 @@ int config_parse_set_status( - void *data, - void *userdata) { - -- size_t l; -- const char *word, *state; -+ _cleanup_free_ char *word = NULL, *k = NULL, *q = NULL; -+ ExecContext *context = data; -+ Unit *u = userdata; -+ const char *p; - int r; -+ -+ assert(filename); -+ assert(lvalue); -+ assert(rvalue); -+ assert(context); -+ -+ if (isempty(rvalue)) { -+ /* Empty assignment resets the list */ -+ context->load_credentials = strv_free(context->load_credentials); -+ return 0; -+ } -+ -+ p = rvalue; -+ r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r <= 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); -+ return 0; -+ } -+ -+ r = unit_full_printf(u, word, &k); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word); -+ return 0; -+ } -+ if (!credential_name_valid(k)) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Credential name \"%s\" not valid, ignoring.", k); -+ return 0; -+ } -+ r = unit_full_printf(u, p, &q); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", p); -+ return 0; -+ } -+ if (path_is_absolute(q) ? !path_is_normalized(q) : !credential_name_valid(q)) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Credential source \"%s\" not valid, ignoring.", q); -+ return 0; -+ } -+ -+ r = strv_consume_pair(&context->load_credentials, TAKE_PTR(k), TAKE_PTR(q)); -+ if (r < 0) -+ return log_oom(); -+ -+ return 0; -+} -+ -+int config_parse_set_status( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ - ExitStatusSet *status_set = data; -+ int r; - - assert(filename); - assert(lvalue); - assert(rvalue); -- assert(data); -+ assert(status_set); - - /* Empty assignment resets the list */ - if (isempty(rvalue)) { -@@ -4268,26 +4537,32 @@ int config_parse_set_status( - return 0; - } - -- FOREACH_WORD(word, l, rvalue, state) { -- _cleanup_free_ char *temp; -+ for (const char *p = rvalue;;) { -+ _cleanup_free_ char *word = NULL; - Bitmap *bitmap; - -- temp = strndup(word, l); -- if (!temp) -+ r = extract_first_word(&p, &word, NULL, 0); -+ if (r == -ENOMEM) - return log_oom(); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse %s=%s, ignoring: %m", lvalue, rvalue); -+ return 0; -+ } -+ if (r == 0) -+ return 0; - - /* We need to call exit_status_from_string() first, because we want - * to parse numbers as exit statuses, not signals. */ - -- r = exit_status_from_string(temp); -+ r = exit_status_from_string(word); - if (r >= 0) { - assert(r >= 0 && r < 256); - bitmap = &status_set->status; - } else { -- r = signal_from_string(temp); -- -- if (r <= 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, -+ r = signal_from_string(word); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, - "Failed to parse value, ignoring: %s", word); - continue; - } -@@ -4296,12 +4571,9 @@ int config_parse_set_status( - - r = bitmap_set(bitmap, r); - if (r < 0) -- return log_error_errno(r, "Failed to set signal or status %s: %m", word); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to set signal or status %s, ignoring: %m", word); - } -- if (!isempty(state)) -- log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); -- -- return 0; - } - - int config_parse_namespace_path_strv( -@@ -4318,7 +4590,6 @@ int config_parse_namespace_path_strv( - - const Unit *u = userdata; - char*** sv = data; -- const char *p = rvalue; - int r; - - assert(filename); -@@ -4332,7 +4603,7 @@ int config_parse_namespace_path_strv( - return 0; - } - -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *resolved = NULL, *joined = NULL; - const char *w; - bool ignore_enoent = false, shall_prefix = false; -@@ -4343,7 +4614,7 @@ int config_parse_namespace_path_strv( - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue); - return 0; - } - -@@ -4359,7 +4630,7 @@ int config_parse_namespace_path_strv( - - r = unit_full_printf(u, w, &resolved); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", w); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s: %m", w); - continue; - } - -@@ -4395,7 +4666,6 @@ int config_parse_temporary_filesystems( - - const Unit *u = userdata; - ExecContext *c = data; -- const char *p = rvalue; - int r; - - assert(filename); -@@ -4411,7 +4681,7 @@ int config_parse_temporary_filesystems( - return 0; - } - -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *word = NULL, *path = NULL, *resolved = NULL; - const char *w; - -@@ -4421,7 +4691,7 @@ int config_parse_temporary_filesystems( - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue); - return 0; - } - -@@ -4430,17 +4700,17 @@ int config_parse_temporary_filesystems( - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", word); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract first word, ignoring: %s", word); - continue; - } - if (r == 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring: %s", word); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid syntax, ignoring: %s", word); - continue; - } - - r = unit_full_printf(u, path, &resolved); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", path); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", path); - continue; - } - -@@ -4468,7 +4738,6 @@ int config_parse_bind_paths( - - ExecContext *c = data; - const Unit *u = userdata; -- const char *p; - int r; - - assert(filename); -@@ -4484,8 +4753,7 @@ int config_parse_bind_paths( - return 0; - } - -- p = rvalue; -- for (;;) { -+ for (const char *p = rvalue;;) { - _cleanup_free_ char *source = NULL, *destination = NULL; - _cleanup_free_ char *sresolved = NULL, *dresolved = NULL; - char *s = NULL, *d = NULL; -@@ -4497,14 +4765,14 @@ int config_parse_bind_paths( - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue); - return 0; - } - - r = unit_full_printf(u, source, &sresolved); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -- "Failed to resolved unit specifiers in \"%s\", ignoring: %m", source); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to resolve unit specifiers in \"%s\", ignoring: %m", source); - continue; - } - -@@ -4524,18 +4792,18 @@ int config_parse_bind_paths( - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue); - return 0; - } - if (r == 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Missing argument after ':', ignoring: %s", s); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Missing argument after ':', ignoring: %s", s); - continue; - } - - r = unit_full_printf(u, destination, &dresolved); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -- "Failed to resolved specifiers in \"%s\", ignoring: %m", destination); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to resolve specifiers in \"%s\", ignoring: %m", destination); - continue; - } - -@@ -4553,7 +4821,7 @@ int config_parse_bind_paths( - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s: %s", lvalue, rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s: %s", lvalue, rvalue); - return 0; - } - -@@ -4562,7 +4830,7 @@ int config_parse_bind_paths( - else if (streq(options, "norbind")) - rbind = false; - else { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid option string, ignoring setting: %s", options); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid option string, ignoring setting: %s", options); - continue; - } - } -@@ -4584,6 +4852,164 @@ int config_parse_bind_paths( - return 0; - } - -+int config_parse_mount_images( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ -+ ExecContext *c = data; -+ const Unit *u = userdata; -+ int r; -+ -+ assert(filename); -+ assert(lvalue); -+ assert(rvalue); -+ assert(data); -+ -+ if (isempty(rvalue)) { -+ /* Empty assignment resets the list */ -+ c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images); -+ return 0; -+ } -+ -+ for (const char *p = rvalue;;) { -+ _cleanup_(mount_options_free_allp) MountOptions *options = NULL; -+ _cleanup_free_ char *first = NULL, *second = NULL, *tuple = NULL; -+ _cleanup_free_ char *sresolved = NULL, *dresolved = NULL; -+ const char *q = NULL; -+ char *s = NULL; -+ bool permissive = false; -+ -+ r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Invalid syntax %s=%s, ignoring: %m", lvalue, rvalue); -+ return 0; -+ } -+ if (r == 0) -+ return 0; -+ -+ q = tuple; -+ r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &first, &second, NULL); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Invalid syntax in %s=, ignoring: %s", lvalue, tuple); -+ return 0; -+ } -+ if (r == 0) -+ continue; -+ -+ r = unit_full_printf(u, first, &sresolved); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to resolve unit specifiers in \"%s\", ignoring: %m", first); -+ continue; -+ } -+ -+ s = sresolved; -+ if (s[0] == '-') { -+ permissive = true; -+ s++; -+ } -+ -+ r = path_simplify_and_warn(s, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); -+ if (r < 0) -+ continue; -+ -+ if (isempty(second)) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Missing destination in %s, ignoring: %s", lvalue, rvalue); -+ continue; -+ } -+ -+ r = unit_full_printf(u, second, &dresolved); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to resolve specifiers in \"%s\", ignoring: %m", second); -+ continue; -+ } -+ -+ r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); -+ if (r < 0) -+ continue; -+ -+ for (;;) { -+ _cleanup_free_ char *partition = NULL, *mount_options = NULL, *mount_options_resolved = NULL; -+ MountOptions *o = NULL; -+ PartitionDesignator partition_designator; -+ -+ r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", q); -+ return 0; -+ } -+ if (r == 0) -+ break; -+ /* Single set of options, applying to the root partition/single filesystem */ -+ if (r == 1) { -+ r = unit_full_printf(u, partition, &mount_options_resolved); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", first); -+ continue; -+ } -+ -+ o = new(MountOptions, 1); -+ if (!o) -+ return log_oom(); -+ *o = (MountOptions) { -+ .partition_designator = PARTITION_ROOT, -+ .options = TAKE_PTR(mount_options_resolved), -+ }; -+ LIST_APPEND(mount_options, options, o); -+ -+ break; -+ } -+ -+ partition_designator = partition_designator_from_string(partition); -+ if (partition_designator < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid partition name %s, ignoring", partition); -+ continue; -+ } -+ r = unit_full_printf(u, mount_options, &mount_options_resolved); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", mount_options); -+ continue; -+ } -+ -+ o = new(MountOptions, 1); -+ if (!o) -+ return log_oom(); -+ *o = (MountOptions) { -+ .partition_designator = partition_designator, -+ .options = TAKE_PTR(mount_options_resolved), -+ }; -+ LIST_APPEND(mount_options, options, o); -+ } -+ -+ r = mount_image_add(&c->mount_images, &c->n_mount_images, -+ &(MountImage) { -+ .source = s, -+ .destination = dresolved, -+ .mount_options = options, -+ .ignore_enoent = permissive, -+ }); -+ if (r < 0) -+ return log_oom(); -+ } -+} -+ - int config_parse_job_timeout_sec( - const char* unit, - const char *filename, -@@ -4607,7 +5033,7 @@ int config_parse_job_timeout_sec( - - r = parse_sec_fix_0(rvalue, &usec); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse JobTimeoutSec= parameter, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse JobTimeoutSec= parameter, ignoring: %s", rvalue); - return 0; - } - -@@ -4646,7 +5072,7 @@ int config_parse_job_running_timeout_sec( - - r = parse_sec_fix_0(rvalue, &usec); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse JobRunningTimeoutSec= parameter, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse JobRunningTimeoutSec= parameter, ignoring: %s", rvalue); - return 0; - } - -@@ -4695,11 +5121,11 @@ int config_parse_emergency_action( - } - - if (r == -EOPNOTSUPP) -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "%s= specified as %s mode action, ignoring: %s", - lvalue, MANAGER_IS_SYSTEM(m) ? "user" : "system", rvalue); - else -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse %s=, ignoring: %s", lvalue, rvalue); - return 0; - } -@@ -4737,7 +5163,7 @@ int config_parse_pid_file( - - r = unit_full_printf(u, rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -4786,7 +5212,7 @@ int config_parse_exit_status( - - r = safe_atou8(rvalue, &u); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse exit status '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse exit status '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -4820,7 +5246,7 @@ int config_parse_disable_controllers( - - r = cg_mask_from_string(rvalue, &disabled_mask); - if (r < 0 || disabled_mask <= 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid cgroup string: %s, ignoring", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid cgroup string: %s, ignoring", rvalue); - return 0; - } - -@@ -4858,7 +5284,7 @@ int config_parse_ip_filter_bpf_progs( - - r = unit_full_printf(u, rvalue, &resolved); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); - return 0; - } - -@@ -4943,7 +5369,7 @@ int unit_load_fragment(Unit *u) { - - /* Possibly rebuild the fragment map to catch new units */ - r = unit_file_build_name_map(&u->manager->lookup_paths, -- &u->manager->unit_cache_mtime, -+ &u->manager->unit_cache_timestamp_hash, - &u->manager->unit_id_map, - &u->manager->unit_name_map, - &u->manager->unit_path_cache); -@@ -5087,7 +5513,6 @@ void unit_dump_config_items(FILE *f) { - { config_parse_ip_tos, "TOS" }, - { config_parse_unit_condition_path, "CONDITION" }, - { config_parse_unit_condition_string, "CONDITION" }, -- { config_parse_unit_condition_null, "CONDITION" }, - { config_parse_unit_slice, "SLICE" }, - { config_parse_documentation, "URL" }, - { config_parse_service_timeout, "SECONDS" }, -@@ -5099,6 +5524,7 @@ void unit_dump_config_items(FILE *f) { - { config_parse_syscall_filter, "SYSCALLS" }, - { config_parse_syscall_archs, "ARCHS" }, - { config_parse_syscall_errno, "ERRNO" }, -+ { config_parse_syscall_log, "SYSCALLS" }, - { config_parse_address_families, "FAMILIES" }, - { config_parse_restrict_namespaces, "NAMESPACES" }, - #endif -@@ -5207,10 +5633,8 @@ int config_parse_show_status( - assert(data); - - k = parse_show_status(rvalue, b); -- if (k < 0) { -- log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse show status setting, ignoring: %s", rvalue); -- return 0; -- } -+ if (k < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, k, "Failed to parse show status setting, ignoring: %s", rvalue); - - return 0; - } -@@ -5244,12 +5668,12 @@ int config_parse_output_restricted( - } else { - t = exec_output_from_string(rvalue); - if (t < 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output type, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse output type, ignoring: %s", rvalue); - return 0; - } - - if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file:, append: are not supported as defaults, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Standard output types socket, fd:, file:, append: are not supported as defaults, ignoring: %s", rvalue); - return 0; - } - } -@@ -5283,10 +5707,8 @@ int config_parse_crash_chvt( - assert(data); - - r = parse_crash_chvt(rvalue, data); -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CrashChangeVT= setting, ignoring: %s", rvalue); -- return 0; -- } -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse CrashChangeVT= setting, ignoring: %s", rvalue); - - return 0; - } -@@ -5320,17 +5742,17 @@ int config_parse_swap_priority( - - r = safe_atoi(rvalue, &priority); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap priority '%s', ignoring.", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid swap priority '%s', ignoring.", rvalue); - return 0; - } - - if (priority < -1) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Sorry, swap priorities smaller than -1 may only be assigned by the kernel itself, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Sorry, swap priorities smaller than -1 may only be assigned by the kernel itself, ignoring: %s", rvalue); - return 0; - } - - if (priority > 32767) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Swap priority out of range, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Swap priority out of range, ignoring: %s", rvalue); - return 0; - } - -diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h -index ac3940a..3504227 100644 ---- a/src/core/load-fragment.h -+++ b/src/core/load-fragment.h -@@ -44,6 +44,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_policy); - CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio); - CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity); - CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits); -+CONFIG_PARSER_PROTOTYPE(config_parse_root_image_options); - CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash); - CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash_sig); - CONFIG_PARSER_PROTOTYPE(config_parse_capability_set); -@@ -57,7 +58,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_unit_env_file); - CONFIG_PARSER_PROTOTYPE(config_parse_ip_tos); - CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_path); - CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_string); --CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_null); - CONFIG_PARSER_PROTOTYPE(config_parse_kill_mode); - CONFIG_PARSER_PROTOTYPE(config_parse_notify_access); - CONFIG_PARSER_PROTOTYPE(config_parse_emergency_action); -@@ -65,6 +65,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_unit_requires_mounts_for); - CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter); - CONFIG_PARSER_PROTOTYPE(config_parse_syscall_archs); - CONFIG_PARSER_PROTOTYPE(config_parse_syscall_errno); -+CONFIG_PARSER_PROTOTYPE(config_parse_syscall_log); - CONFIG_PARSER_PROTOTYPE(config_parse_environ); - CONFIG_PARSER_PROTOTYPE(config_parse_pass_environ); - CONFIG_PARSER_PROTOTYPE(config_parse_unset_environ); -@@ -90,6 +91,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_smack_process_label); - CONFIG_PARSER_PROTOTYPE(config_parse_address_families); - CONFIG_PARSER_PROTOTYPE(config_parse_runtime_preserve_mode); - CONFIG_PARSER_PROTOTYPE(config_parse_exec_directories); -+CONFIG_PARSER_PROTOTYPE(config_parse_set_credential); -+CONFIG_PARSER_PROTOTYPE(config_parse_load_credential); - CONFIG_PARSER_PROTOTYPE(config_parse_set_status); - CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv); - CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems); -@@ -108,6 +111,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_user_group_strv_compat); - CONFIG_PARSER_PROTOTYPE(config_parse_restrict_namespaces); - CONFIG_PARSER_PROTOTYPE(config_parse_bind_paths); - CONFIG_PARSER_PROTOTYPE(config_parse_exec_keyring_mode); -+CONFIG_PARSER_PROTOTYPE(config_parse_protect_proc); -+CONFIG_PARSER_PROTOTYPE(config_parse_proc_subset); - CONFIG_PARSER_PROTOTYPE(config_parse_job_timeout_sec); - CONFIG_PARSER_PROTOTYPE(config_parse_job_running_timeout_sec); - CONFIG_PARSER_PROTOTYPE(config_parse_log_extra_fields); -@@ -127,6 +132,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_output_restricted); - CONFIG_PARSER_PROTOTYPE(config_parse_crash_chvt); - CONFIG_PARSER_PROTOTYPE(config_parse_timeout_abort); - CONFIG_PARSER_PROTOTYPE(config_parse_swap_priority); -+CONFIG_PARSER_PROTOTYPE(config_parse_mount_images); - - /* gperf prototypes */ - const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length); -diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c -index f76b82a..90f03db 100644 ---- a/src/core/machine-id-setup.c -+++ b/src/core/machine-id-setup.c -@@ -44,7 +44,7 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) { - fd = safe_close(fd); - } - -- if (isempty(root)) { -+ if (isempty(root) && running_in_chroot() <= 0) { - /* If that didn't work, see if we are running in a container, - * and a machine ID was passed in via $container_uuid the way - * libvirt/LXC does it */ -diff --git a/src/core/main.c b/src/core/main.c -index 4a37697..51e04da 100644 ---- a/src/core/main.c -+++ b/src/core/main.c -@@ -32,6 +32,7 @@ - #include "dbus-manager.h" - #include "dbus.h" - #include "def.h" -+#include "dev-setup.h" - #include "efi-random.h" - #include "efivars.h" - #include "emergency-action.h" -@@ -53,6 +54,7 @@ - #include "loopback-setup.h" - #include "machine-id-setup.h" - #include "manager.h" -+#include "mkdir.h" - #include "mount-setup.h" - #include "os-util.h" - #include "pager.h" -@@ -2073,6 +2075,20 @@ static int initialize_runtime( - if (r < 0) - log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m", arg_watchdog_device); - } -+ } else { -+ _cleanup_free_ char *p = NULL; -+ -+ /* Create the runtime directory and place the inaccessible device nodes there, if we run in -+ * user mode. In system mode mount_setup() already did that. */ -+ -+ r = xdg_user_runtime_dir(&p, "/systemd"); -+ if (r < 0) { -+ *ret_error_message = "$XDG_RUNTIME_DIR is not set"; -+ return log_emergency_errno(r, "Failed to determine $XDG_RUNTIME_DIR path: %m"); -+ } -+ -+ (void) mkdir_p_label(p, 0755); -+ (void) make_inaccessible_nodes(p, UID_INVALID, GID_INVALID); - } - - if (arg_timer_slack_nsec != NSEC_INFINITY) -@@ -2653,22 +2669,6 @@ int main(int argc, char *argv[]) { - goto finish; - } - -- } else { -- /* Running as user instance */ -- arg_system = false; -- log_set_target(LOG_TARGET_AUTO); -- log_open(); -- -- /* clear the kernel timestamp, because we are not PID 1 */ -- kernel_timestamp = DUAL_TIMESTAMP_NULL; -- -- if (mac_selinux_init() < 0) { -- error_message = "Failed to initialize SELinux support"; -- goto finish; -- } -- } -- -- if (arg_system) { - /* Try to figure out if we can use colors with the console. No need to do that for user instances since - * they never log into the console. */ - log_show_color(colors_enabled()); -@@ -2676,15 +2676,12 @@ int main(int argc, char *argv[]) { - r = make_null_stdio(); - if (r < 0) - log_warning_errno(r, "Failed to redirect standard streams to /dev/null, ignoring: %m"); -- } -- -- /* Mount /proc, /sys and friends, so that /proc/cmdline and /proc/$PID/fd is available. */ -- if (getpid_cached() == 1) { - - /* Load the kernel modules early. */ - if (!skip_setup) - kmod_setup(); - -+ /* Mount /proc, /sys and friends, so that /proc/cmdline and /proc/$PID/fd is available. */ - r = mount_setup(loaded_policy, skip_setup); - if (r < 0) { - error_message = "Failed to mount API filesystems"; -@@ -2697,6 +2694,19 @@ int main(int argc, char *argv[]) { - /* Cache command-line options passed from EFI variables */ - if (!skip_setup) - (void) cache_efi_options_variable(); -+ } else { -+ /* Running as user instance */ -+ arg_system = false; -+ log_set_target(LOG_TARGET_AUTO); -+ log_open(); -+ -+ /* clear the kernel timestamp, because we are not PID 1 */ -+ kernel_timestamp = DUAL_TIMESTAMP_NULL; -+ -+ if (mac_selinux_init() < 0) { -+ error_message = "Failed to initialize SELinux support"; -+ goto finish; -+ } - } - - /* Save the original RLIMIT_NOFILE/RLIMIT_MEMLOCK so that we can reset it later when -diff --git a/src/core/manager.c b/src/core/manager.c -index 41e0d73..b3f6df8 100644 ---- a/src/core/manager.c -+++ b/src/core/manager.c -@@ -63,6 +63,7 @@ - #include "ratelimit.h" - #include "rlimit-util.h" - #include "rm-rf.h" -+#include "selinux-util.h" - #include "serialize.h" - #include "signal-util.h" - #include "socket-util.h" -@@ -197,7 +198,6 @@ static void manager_flip_auto_status(Manager *m, bool enable, const char *reason - - static void manager_print_jobs_in_progress(Manager *m) { - _cleanup_free_ char *job_of_n = NULL; -- Iterator i; - Job *j; - unsigned counter = 0, print_nr; - char cylon[6 + CYLON_BUFFER_EXTRA + 1]; -@@ -212,7 +212,7 @@ static void manager_print_jobs_in_progress(Manager *m) { - - print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs; - -- HASHMAP_FOREACH(j, m->jobs, i) -+ HASHMAP_FOREACH(j, m->jobs) - if (j->state == JOB_RUNNING && counter++ == print_nr) - break; - -@@ -591,6 +591,7 @@ static char** sanitize_environment(char **l) { - l, - "CACHE_DIRECTORY", - "CONFIGURATION_DIRECTORY", -+ "CREDENTIALS_DIRECTORY", - "EXIT_CODE", - "EXIT_STATUS", - "INVOCATION_ID", -@@ -670,19 +671,19 @@ static int manager_setup_prefix(Manager *m) { - }; - - static const struct table_entry paths_system[_EXEC_DIRECTORY_TYPE_MAX] = { -- [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_SYSTEM_RUNTIME, NULL }, -- [EXEC_DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE, NULL }, -- [EXEC_DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE, NULL }, -- [EXEC_DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS, NULL }, -+ [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_SYSTEM_RUNTIME, NULL }, -+ [EXEC_DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE, NULL }, -+ [EXEC_DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE, NULL }, -+ [EXEC_DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS, NULL }, - [EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_SYSTEM_CONFIGURATION, NULL }, - }; - - static const struct table_entry paths_user[_EXEC_DIRECTORY_TYPE_MAX] = { -- [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_USER_RUNTIME, NULL }, -- [EXEC_DIRECTORY_STATE] = { SD_PATH_USER_CONFIGURATION, NULL }, -- [EXEC_DIRECTORY_CACHE] = { SD_PATH_USER_STATE_CACHE, NULL }, -- [EXEC_DIRECTORY_LOGS] = { SD_PATH_USER_CONFIGURATION, "log" }, -- [EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL }, -+ [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_USER_RUNTIME, NULL }, -+ [EXEC_DIRECTORY_STATE] = { SD_PATH_USER_CONFIGURATION, NULL }, -+ [EXEC_DIRECTORY_CACHE] = { SD_PATH_USER_STATE_CACHE, NULL }, -+ [EXEC_DIRECTORY_LOGS] = { SD_PATH_USER_CONFIGURATION, "log" }, -+ [EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL }, - }; - - assert(m); -@@ -703,7 +704,7 @@ static void manager_free_unit_name_maps(Manager *m) { - m->unit_id_map = hashmap_free(m->unit_id_map); - m->unit_name_map = hashmap_free(m->unit_name_map); - m->unit_path_cache = set_free(m->unit_path_cache); -- m->unit_cache_mtime = 0; -+ m->unit_cache_timestamp_hash = 0; - } - - static int manager_setup_run_queue(Manager *m) { -@@ -754,6 +755,7 @@ static int manager_setup_sigchld_event_source(Manager *m) { - - int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager **_m) { - _cleanup_(manager_freep) Manager *m = NULL; -+ const char *e; - int r; - - assert(_m); -@@ -857,6 +859,13 @@ int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager - if (r < 0) - return r; - -+ e = secure_getenv("CREDENTIALS_DIRECTORY"); -+ if (e) { -+ m->received_credentials = strdup(e); -+ if (!m->received_credentials) -+ return -ENOMEM; -+ } -+ - r = sd_event_default(&m->event); - if (r < 0) - return r; -@@ -954,9 +963,9 @@ static int manager_setup_notify(Manager *m) { - (void) mkdir_parents_label(m->notify_socket, 0755); - (void) sockaddr_un_unlink(&sa.un); - -- r = bind(fd, &sa.sa, sa_len); -+ r = mac_selinux_bind(fd, &sa.sa, sa_len); - if (r < 0) -- return log_error_errno(errno, "bind(%s) failed: %m", m->notify_socket); -+ return log_error_errno(r, "bind(%s) failed: %m", m->notify_socket); - - r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true); - if (r < 0) -@@ -1137,13 +1146,12 @@ enum { - - static void unit_gc_mark_good(Unit *u, unsigned gc_marker) { - Unit *other; -- Iterator i; - void *v; - - u->gc_marker = gc_marker + GC_OFFSET_GOOD; - - /* Recursively mark referenced units as GOOD as well */ -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REFERENCES], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REFERENCES]) - if (other->gc_marker == gc_marker + GC_OFFSET_UNSURE) - unit_gc_mark_good(other, gc_marker); - } -@@ -1151,7 +1159,6 @@ static void unit_gc_mark_good(Unit *u, unsigned gc_marker) { - static void unit_gc_sweep(Unit *u, unsigned gc_marker) { - Unit *other; - bool is_bad; -- Iterator i; - void *v; - - assert(u); -@@ -1170,7 +1177,7 @@ static void unit_gc_sweep(Unit *u, unsigned gc_marker) { - - is_bad = true; - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REFERENCED_BY], i) { -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REFERENCED_BY]) { - unit_gc_sweep(other, gc_marker); - - if (other->gc_marker == gc_marker + GC_OFFSET_GOOD) -@@ -1420,6 +1427,7 @@ Manager* manager_free(Manager *m) { - - for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) - m->prefix[dt] = mfree(m->prefix[dt]); -+ free(m->received_credentials); - - return mfree(m); - } -@@ -1463,7 +1471,6 @@ static void manager_enumerate(Manager *m) { - } - - static void manager_coldplug(Manager *m) { -- Iterator i; - Unit *u; - char *k; - int r; -@@ -1473,7 +1480,7 @@ static void manager_coldplug(Manager *m) { - log_debug("Invoking unit coldplug() handlers…"); - - /* Let's place the units back into their deserialized state */ -- HASHMAP_FOREACH_KEY(u, k, m->units, i) { -+ HASHMAP_FOREACH_KEY(u, k, m->units) { - - /* ignore aliases */ - if (u->id != k) -@@ -1486,7 +1493,6 @@ static void manager_coldplug(Manager *m) { - } - - static void manager_catchup(Manager *m) { -- Iterator i; - Unit *u; - char *k; - -@@ -1495,7 +1501,7 @@ static void manager_catchup(Manager *m) { - log_debug("Invoking unit catchup() handlers…"); - - /* Let's catch up on any state changes that happened while we were reloading/reexecing */ -- HASHMAP_FOREACH_KEY(u, k, m->units, i) { -+ HASHMAP_FOREACH_KEY(u, k, m->units) { - - /* ignore aliases */ - if (u->id != k) -@@ -1506,12 +1512,11 @@ static void manager_catchup(Manager *m) { - } - - static void manager_distribute_fds(Manager *m, FDSet *fds) { -- Iterator i; - Unit *u; - - assert(m); - -- HASHMAP_FOREACH(u, m->units, i) { -+ HASHMAP_FOREACH(u, m->units) { - - if (fdset_size(fds) <= 0) - break; -@@ -1872,7 +1877,6 @@ Unit *manager_get_unit(Manager *m, const char *name) { - - static int manager_dispatch_target_deps_queue(Manager *m) { - Unit *u; -- unsigned k; - int r = 0; - - static const UnitDependency deps[] = { -@@ -1890,12 +1894,11 @@ static int manager_dispatch_target_deps_queue(Manager *m) { - LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u); - u->in_target_deps_queue = false; - -- for (k = 0; k < ELEMENTSOF(deps); k++) { -+ for (size_t k = 0; k < ELEMENTSOF(deps); k++) { - Unit *target; -- Iterator i; - void *v; - -- HASHMAP_FOREACH_KEY(v, target, u->dependencies[deps[k]], i) { -+ HASHMAP_FOREACH_KEY(v, target, u->dependencies[deps[k]]) { - r = unit_add_default_target_dependency(u, target); - if (r < 0) - return r; -@@ -1937,19 +1940,22 @@ unsigned manager_dispatch_load_queue(Manager *m) { - return n; - } - --bool manager_unit_file_maybe_loadable_from_cache(Unit *u) { -+bool manager_unit_cache_should_retry_load(Unit *u) { - assert(u); - -+ /* Automatic reloading from disk only applies to units which were not found sometime in the past, and -+ * the not-found stub is kept pinned in the unit graph by dependencies. For units that were -+ * previously loaded, we don't do automatic reloading, and daemon-reload is necessary to update. */ - if (u->load_state != UNIT_NOT_FOUND) - return false; - -- if (u->manager->unit_cache_mtime == 0) -- return false; -- -- if (u->manager->unit_cache_mtime > u->fragment_loadtime) -+ /* The cache has been updated since the last time we tried to load the unit. There might be new -+ * fragment paths to read. */ -+ if (u->manager->unit_cache_timestamp_hash != u->fragment_not_found_timestamp_hash) - return true; - -- return !lookup_paths_mtime_good(&u->manager->lookup_paths, u->manager->unit_cache_mtime); -+ /* The cache needs to be updated because there are modifications on disk. */ -+ return !lookup_paths_timestamp_hash_same(&u->manager->lookup_paths, u->manager->unit_cache_timestamp_hash, NULL); - } - - int manager_load_unit_prepare( -@@ -1998,10 +2004,10 @@ int manager_load_unit_prepare( - * first if anything in the usual paths was modified since the last time - * the cache was loaded. Also check if the last time an attempt to load the - * unit was made was before the most recent cache refresh, so that we know -- * we need to try again - even if the cache is current, it might have been -+ * we need to try again — even if the cache is current, it might have been - * updated in a different context before we had a chance to retry loading - * this particular unit. */ -- if (manager_unit_file_maybe_loadable_from_cache(ret)) -+ if (manager_unit_cache_should_retry_load(ret)) - ret->load_state = UNIT_STUB; - else { - *_ret = ret; -@@ -2085,36 +2091,32 @@ int manager_load_startable_unit_or_warn( - } - - void manager_dump_jobs(Manager *s, FILE *f, const char *prefix) { -- Iterator i; - Job *j; - - assert(s); - assert(f); - -- HASHMAP_FOREACH(j, s->jobs, i) -+ HASHMAP_FOREACH(j, s->jobs) - job_dump(j, f, prefix); - } - - void manager_dump_units(Manager *s, FILE *f, const char *prefix) { -- Iterator i; - Unit *u; - const char *t; - - assert(s); - assert(f); - -- HASHMAP_FOREACH_KEY(u, t, s->units, i) -+ HASHMAP_FOREACH_KEY(u, t, s->units) - if (u->id == t) - unit_dump(u, f, prefix); - } - - void manager_dump(Manager *m, FILE *f, const char *prefix) { -- ManagerTimestamp q; -- - assert(m); - assert(f); - -- for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { -+ for (ManagerTimestamp q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { - const dual_timestamp *t = m->timestamps + q; - char buf[CONST_MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)]; - -@@ -2826,7 +2828,6 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t - - static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { - Manager *m = userdata; -- Iterator i; - Unit *u; - - assert(m); -@@ -2839,7 +2840,7 @@ static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint - /* Restart the watch */ - (void) manager_setup_time_change(m); - -- HASHMAP_FOREACH(u, m->units, i) -+ HASHMAP_FOREACH(u, m->units) - if (UNIT_VTABLE(u)->time_change) - UNIT_VTABLE(u)->time_change(u); - -@@ -2853,7 +2854,6 @@ static int manager_dispatch_timezone_change( - - Manager *m = userdata; - int changed; -- Iterator i; - Unit *u; - - assert(m); -@@ -2872,7 +2872,7 @@ static int manager_dispatch_timezone_change( - - log_debug("Timezone has been changed (now: %s).", tzname[daylight]); - -- HASHMAP_FOREACH(u, m->units, i) -+ HASHMAP_FOREACH(u, m->units) - if (UNIT_VTABLE(u)->timezone_change) - UNIT_VTABLE(u)->timezone_change(u); - -@@ -2902,15 +2902,13 @@ static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32 - static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) { - Manager *m = userdata; - int r; -- uint64_t next; - - assert(m); - assert(source); - - manager_print_jobs_in_progress(m); - -- next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_PERIOD_USEC; -- r = sd_event_source_set_time(source, next); -+ r = sd_event_source_set_time_relative(source, JOBS_IN_PROGRESS_PERIOD_USEC); - if (r < 0) - return r; - -@@ -3177,7 +3175,6 @@ static void manager_serialize_uid_refs_internal( - Hashmap **uid_refs, - const char *field_name) { - -- Iterator i; - void *p, *k; - - assert(m); -@@ -3188,7 +3185,7 @@ static void manager_serialize_uid_refs_internal( - /* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as - * the actual counter of it is better rebuild after a reload/reexec. */ - -- HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) { -+ HASHMAP_FOREACH_KEY(p, k, *uid_refs) { - uint32_t c; - uid_t uid; - -@@ -3216,9 +3213,7 @@ int manager_serialize( - FDSet *fds, - bool switching_root) { - -- ManagerTimestamp q; - const char *t; -- Iterator i; - Unit *u; - int r; - -@@ -3252,7 +3247,7 @@ int manager_serialize( - (void) serialize_usec(f, "reboot-watchdog-overridden", m->watchdog_overridden[WATCHDOG_REBOOT]); - (void) serialize_usec(f, "kexec-watchdog-overridden", m->watchdog_overridden[WATCHDOG_KEXEC]); - -- for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { -+ for (ManagerTimestamp q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { - _cleanup_free_ char *joined = NULL; - - if (!manager_timestamp_shall_serialize(q)) -@@ -3311,7 +3306,7 @@ int manager_serialize( - - (void) fputc('\n', f); - -- HASHMAP_FOREACH_KEY(u, t, m->units, i) { -+ HASHMAP_FOREACH_KEY(u, t, m->units) { - if (u->id != t) - continue; - -@@ -3814,11 +3809,10 @@ int manager_reload(Manager *m) { - - void manager_reset_failed(Manager *m) { - Unit *u; -- Iterator i; - - assert(m); - -- HASHMAP_FOREACH(u, m->units, i) -+ HASHMAP_FOREACH(u, m->units) - unit_reset_failed(u); - } - -@@ -4181,11 +4175,9 @@ int manager_get_effective_environment(Manager *m, char ***ret) { - } - - int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) { -- int i; -- - assert(m); - -- for (i = 0; i < _RLIMIT_MAX; i++) { -+ for (unsigned i = 0; i < _RLIMIT_MAX; i++) { - m->rlimit[i] = mfree(m->rlimit[i]); - - if (!default_rlimit[i]) -@@ -4373,11 +4365,11 @@ const char *manager_get_confirm_spawn(Manager *m) { - * - * If the console suddenly disappear at the time our children will really it - * then they will simply fail to acquire it and a positive answer will be -- * assumed. New children will fallback to /dev/console though. -+ * assumed. New children will fall back to /dev/console though. - * - * Note: TTYs are devices that can come and go any time, and frequently aren't - * available yet during early boot (consider a USB rs232 dongle...). If for any -- * reason the configured console is not ready, we fallback to the default -+ * reason the configured console is not ready, we fall back to the default - * console. */ - - if (!m->confirm_spawn || path_equal(m->confirm_spawn, "/dev/console")) -@@ -4651,14 +4643,13 @@ static void manager_vacuum_uid_refs_internal( - Hashmap **uid_refs, - int (*_clean_ipc)(uid_t uid)) { - -- Iterator i; - void *p, *k; - - assert(m); - assert(uid_refs); - assert(_clean_ipc); - -- HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) { -+ HASHMAP_FOREACH_KEY(p, k, *uid_refs) { - uint32_t c, n; - uid_t uid; - -diff --git a/src/core/manager.h b/src/core/manager.h -index 81b0c13..9e98b31 100644 ---- a/src/core/manager.h -+++ b/src/core/manager.h -@@ -233,7 +233,7 @@ struct Manager { - Hashmap *unit_id_map; - Hashmap *unit_name_map; - Set *unit_path_cache; -- usec_t unit_cache_mtime; -+ uint64_t unit_cache_timestamp_hash; - - char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */ - char **client_environment; /* Environment variables created by clients through the bus API */ -@@ -424,6 +424,7 @@ struct Manager { - - /* Prefixes of e.g. RuntimeDirectory= */ - char *prefix[_EXEC_DIRECTORY_TYPE_MAX]; -+ char *received_credentials; - - /* Used in the SIGCHLD and sd_notify() message invocation logic to avoid that we dispatch the same event - * multiple times on the same unit. */ -@@ -463,7 +464,7 @@ Unit *manager_get_unit(Manager *m, const char *name); - - int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j); - --bool manager_unit_file_maybe_loadable_from_cache(Unit *u); -+bool manager_unit_cache_should_retry_load(Unit *u); - int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret); - int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret); - int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret); -diff --git a/src/core/meson.build b/src/core/meson.build -index fa95108..72a00f1 100644 ---- a/src/core/meson.build -+++ b/src/core/meson.build -@@ -178,7 +178,8 @@ libcore = static_library( - libkmod, - libapparmor, - libselinux, -- libmount]) -+ libmount, -+ libacl]) - - systemd_sources = files('main.c') - -diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c -index feb88f3..7c17783 100644 ---- a/src/core/mount-setup.c -+++ b/src/core/mount-setup.c -@@ -85,6 +85,8 @@ static const MountPoint mount_table[] = { - #endif - { "tmpfs", "/run", "tmpfs", "mode=755" TMPFS_LIMITS_RUN, MS_NOSUID|MS_NODEV|MS_STRICTATIME, - NULL, MNT_FATAL|MNT_IN_CONTAINER }, -+ { "cgroup2", "/sys/fs/cgroup", "cgroup2", "nsdelegate,memory_recursiveprot", MS_NOSUID|MS_NOEXEC|MS_NODEV, -+ cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, - { "cgroup2", "/sys/fs/cgroup", "cgroup2", "nsdelegate", MS_NOSUID|MS_NOEXEC|MS_NODEV, - cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, - { "cgroup2", "/sys/fs/cgroup", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, -@@ -480,7 +482,7 @@ static int relabel_extra(void) { - #endif - - int mount_setup(bool loaded_policy, bool leave_propagation) { -- int r = 0; -+ int r; - - r = mount_points_setup(ELEMENTSOF(mount_table), loaded_policy); - if (r < 0) -@@ -535,9 +537,21 @@ int mount_setup(bool loaded_policy, bool leave_propagation) { - (void) mkdir_label("/run/systemd", 0755); - (void) mkdir_label("/run/systemd/system", 0755); - -+ /* Make sure we have a mount point to hide in sandboxes */ -+ (void) mkdir_label("/run/credentials", 0755); -+ - /* Also create /run/systemd/inaccessible nodes, so that we always have something to mount -- * inaccessible nodes from. */ -- (void) make_inaccessible_nodes(NULL, UID_INVALID, GID_INVALID); -+ * inaccessible nodes from. If we run in a container the host might have created these for us already -+ * in /run/host/inaccessible/. Use those if we can, since that way we likely get access to block/char -+ * device nodes that are inaccessible, and if userns is used to nodes that are on mounts owned by a -+ * userns outside the container and thus nicely read-only and not remountable. */ -+ if (access("/run/host/inaccessible/", F_OK) < 0) { -+ if (errno != ENOENT) -+ log_debug_errno(errno, "Failed to check if /run/host/inaccessible exists, ignoring: %m"); -+ -+ (void) make_inaccessible_nodes("/run/systemd", UID_INVALID, GID_INVALID); -+ } else -+ (void) symlink("../host/inaccessible", "/run/systemd/inaccessible"); - - return 0; - } -diff --git a/src/core/mount.c b/src/core/mount.c -index 337e94e..dbbb73f 100644 ---- a/src/core/mount.c -+++ b/src/core/mount.c -@@ -281,7 +281,6 @@ static int update_parameters_proc_self_mountinfo( - static int mount_add_mount_dependencies(Mount *m) { - MountParameters *pm; - Unit *other; -- Iterator i; - Set *s; - int r; - -@@ -315,7 +314,7 @@ static int mount_add_mount_dependencies(Mount *m) { - - /* Adds in dependencies to other units that use this path or paths further down in the hierarchy */ - s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where); -- SET_FOREACH(other, s, i) { -+ SET_FOREACH(other, s) { - - if (other->load_state != UNIT_LOADED) - continue; -@@ -869,7 +868,7 @@ static void mount_enter_dead(Mount *m, MountResult f) { - - m->exec_runtime = exec_runtime_unref(m->exec_runtime, true); - -- unit_destroy_runtime_directory(UNIT(m), &m->exec_context); -+ unit_destroy_runtime_data(UNIT(m), &m->exec_context); - - unit_unref_uid_gid(UNIT(m), true); - -@@ -1903,7 +1902,6 @@ static int drain_libmount(Manager *m) { - static int mount_process_proc_self_mountinfo(Manager *m) { - _cleanup_set_free_free_ Set *around = NULL, *gone = NULL; - const char *what; -- Iterator i; - Unit *u; - int r; - -@@ -2001,7 +1999,7 @@ static int mount_process_proc_self_mountinfo(Manager *m) { - mount->proc_flags = 0; - } - -- SET_FOREACH(what, gone, i) { -+ SET_FOREACH(what, gone) { - if (set_contains(around, what)) - continue; - -diff --git a/src/core/namespace.c b/src/core/namespace.c -index 36d5ff6..5a5095e 100644 ---- a/src/core/namespace.c -+++ b/src/core/namespace.c -@@ -15,6 +15,7 @@ - #include "format-util.h" - #include "fs-util.h" - #include "label.h" -+#include "list.h" - #include "loop-util.h" - #include "loopback-setup.h" - #include "mkdir.h" -@@ -40,6 +41,7 @@ - typedef enum MountMode { - /* This is ordered by priority! */ - INACCESSIBLE, -+ MOUNT_IMAGES, - BIND_MOUNT, - BIND_MOUNT_RECURSIVE, - PRIVATE_TMP, -@@ -65,12 +67,13 @@ typedef struct MountEntry { - bool nosuid:1; /* Shall set MS_NOSUID on the mount itself */ - bool applied:1; /* Already applied */ - char *path_malloc; /* Use this instead of 'path_const' if we had to allocate memory */ -- const char *source_const; /* The source path, for bind mounts */ -+ const char *source_const; /* The source path, for bind mounts or images */ - char *source_malloc; - const char *options_const;/* Mount options for tmpfs */ - char *options_malloc; - unsigned long flags; /* Mount flags used by EMPTY_DIR and TMPFS. Do not include MS_RDONLY here, but please use read_only. */ - unsigned n_followed; -+ LIST_HEAD(MountOptions, image_options); - } MountEntry; - - /* If MountAPIVFS= is used, let's mount /sys and /proc into the it, but only as a fallback if the user hasn't mounted -@@ -94,7 +97,7 @@ static const MountEntry protect_kernel_tunables_table[] = { - { "/proc/latency_stats", READONLY, true }, - { "/proc/mtrr", READONLY, true }, - { "/proc/scsi", READONLY, true }, -- { "/proc/sys", READONLY, false }, -+ { "/proc/sys", READONLY, true }, - { "/proc/sysrq-trigger", READONLY, true }, - { "/proc/timer_stats", READONLY, true }, - { "/sys", READONLY, false }, -@@ -205,6 +208,7 @@ static const char * const mount_mode_table[_MOUNT_MODE_MAX] = { - [READONLY] = "read-only", - [READWRITE] = "read-write", - [TMPFS] = "tmpfs", -+ [MOUNT_IMAGES] = "mount-images", - [READWRITE_IMPLICIT] = "rw-implicit", - }; - -@@ -243,6 +247,7 @@ static void mount_entry_done(MountEntry *p) { - p->path_malloc = mfree(p->path_malloc); - p->source_malloc = mfree(p->source_malloc); - p->options_malloc = mfree(p->options_malloc); -+ p->image_options = mount_options_free_all(p->image_options); - } - - static int append_access_mounts(MountEntry **p, char **strv, MountMode mode, bool forcibly_require_prefix) { -@@ -325,6 +330,24 @@ static int append_bind_mounts(MountEntry **p, const BindMount *binds, size_t n) - return 0; - } - -+static int append_mount_images(MountEntry **p, const MountImage *mount_images, size_t n) { -+ assert(p); -+ -+ for (size_t i = 0; i < n; i++) { -+ const MountImage *m = mount_images + i; -+ -+ *((*p)++) = (MountEntry) { -+ .path_const = m->destination, -+ .mode = MOUNT_IMAGES, -+ .source_const = m->source, -+ .image_options = m->mount_options, -+ .ignore = m->ignore_enoent, -+ }; -+ } -+ -+ return 0; -+} -+ - static int append_tmpfs_mounts(MountEntry **p, const TemporaryFileSystem *tmpfs, size_t n) { - assert(p); - -@@ -627,7 +650,7 @@ static int clone_device_node( - *make_devnode = false; - } - -- /* We're about to fallback to bind-mounting the device -+ /* We're about to fall back to bind-mounting the device - * node. So create a dummy bind-mount target. - * Do not prepare device-node SELinux label (see issue 13762) */ - r = mknod(dn, S_IFREG, 0); -@@ -840,33 +863,66 @@ static int mount_sysfs(const MountEntry *m) { - return 1; - } - --static int mount_procfs(const MountEntry *m) { -- int r; -+static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) { -+ const char *entry_path; - - assert(m); -+ assert(ns_info); - -- (void) mkdir_p_label(mount_entry_path(m), 0755); -+ entry_path = mount_entry_path(m); - -- r = path_is_mount_point(mount_entry_path(m), NULL, 0); -- if (r < 0) -- return log_debug_errno(r, "Unable to determine whether /proc is already mounted: %m"); -- if (r > 0) /* make this a NOP if /proc is already a mount point */ -- return 0; -+ /* Mount a new instance, so that we get the one that matches our user namespace, if we are running in -+ * one. i.e we don't reuse existing mounts here under any condition, we want a new instance owned by -+ * our user namespace and with our hidepid= settings applied. Hence, let's get rid of everything -+ * mounted on /proc/ first. */ - -- /* Mount a new instance, so that we get the one that matches our user namespace, if we are running in one */ -- if (mount("proc", mount_entry_path(m), "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0) -- return log_debug_errno(errno, "Failed to mount %s: %m", mount_entry_path(m)); -+ (void) mkdir_p_label(entry_path, 0755); -+ (void) umount_recursive(entry_path, 0); -+ -+ if (ns_info->protect_proc != PROTECT_PROC_DEFAULT || -+ ns_info->proc_subset != PROC_SUBSET_ALL) { -+ _cleanup_free_ char *opts = NULL; -+ -+ /* Starting with kernel 5.8 procfs' hidepid= logic is truly per-instance (previously it -+ * pretended to be per-instance but actually was per-namespace), hence let's make use of it -+ * if requested. To make sure this logic succeeds only on kernels where hidepid= is -+ * per-instance, we'll exclusively use the textual value for hidepid=, since support was -+ * added in the same commit: if it's supported it is thus also per-instance. */ -+ -+ opts = strjoin("hidepid=", -+ ns_info->protect_proc == PROTECT_PROC_DEFAULT ? "off" : -+ protect_proc_to_string(ns_info->protect_proc), -+ ns_info->proc_subset == PROC_SUBSET_PID ? ",subset=pid" : ""); -+ if (!opts) -+ return -ENOMEM; -+ -+ if (mount("proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, opts) < 0) { -+ if (errno != EINVAL) -+ return log_debug_errno(errno, "Failed to mount %s (options=%s): %m", mount_entry_path(m), opts); -+ -+ /* If this failed with EINVAL then this likely means the textual hidepid= stuff is -+ * not supported by the kernel, and thus the per-instance hidepid= neither, which -+ * means we really don't want to use it, since it would affect our host's /proc -+ * mount. Hence let's gracefully fallback to a classic, unrestricted version. */ -+ } else -+ return 1; -+ } -+ -+ if (mount("proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0) -+ return log_debug_errno(errno, "Failed to mount %s (no options): %m", mount_entry_path(m)); - - return 1; - } - - static int mount_tmpfs(const MountEntry *m) { -+ const char *entry_path, *inner_path; - int r; -- const char *entry_path = mount_entry_path(m); -- const char *source_path = m->path_const; - - assert(m); - -+ entry_path = mount_entry_path(m); -+ inner_path = m->path_const; -+ - /* First, get rid of everything that is below if there is anything. Then, overmount with our new tmpfs */ - - (void) mkdir_p_label(entry_path, 0755); -@@ -875,9 +931,64 @@ static int mount_tmpfs(const MountEntry *m) { - if (mount("tmpfs", entry_path, "tmpfs", m->flags, mount_entry_options(m)) < 0) - return log_debug_errno(errno, "Failed to mount %s: %m", entry_path); - -- r = label_fix_container(entry_path, source_path, 0); -+ r = label_fix_container(entry_path, inner_path, 0); - if (r < 0) -- return log_debug_errno(r, "Failed to fix label of '%s' as '%s': %m", entry_path, source_path); -+ return log_debug_errno(r, "Failed to fix label of '%s' as '%s': %m", entry_path, inner_path); -+ -+ return 1; -+} -+ -+static int mount_images(const MountEntry *m) { -+ _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; -+ _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL; -+ _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL; -+ _cleanup_free_ void *root_hash_decoded = NULL; -+ _cleanup_free_ char *verity_data = NULL, *hash_sig = NULL; -+ DissectImageFlags dissect_image_flags = m->read_only ? DISSECT_IMAGE_READ_ONLY : 0; -+ size_t root_hash_size = 0; -+ int r; -+ -+ r = verity_metadata_load(mount_entry_source(m), NULL, &root_hash_decoded, &root_hash_size, &verity_data, &hash_sig); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to load root hash: %m"); -+ dissect_image_flags |= verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0; -+ -+ r = loop_device_make_by_path(mount_entry_source(m), -+ m->read_only ? O_RDONLY : -1 /* < 0 means writable if possible, read-only as fallback */, -+ verity_data ? 0 : LO_FLAGS_PARTSCAN, -+ &loop_device); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to create loop device for image: %m"); -+ -+ r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, m->image_options, dissect_image_flags, &dissected_image); -+ /* No partition table? Might be a single-filesystem image, try again */ -+ if (!verity_data && r < 0 && r == -ENOPKG) -+ r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, m->image_options, dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE, &dissected_image); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to dissect image: %m"); -+ -+ r = dissected_image_decrypt(dissected_image, NULL, root_hash_decoded, root_hash_size, verity_data, hash_sig, NULL, 0, dissect_image_flags, &decrypted_image); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to decrypt dissected image: %m"); -+ -+ r = mkdir_p_label(mount_entry_path(m), 0755); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to create destination directory %s: %m", mount_entry_path(m)); -+ r = umount_recursive(mount_entry_path(m), 0); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to umount under destination directory %s: %m", mount_entry_path(m)); -+ -+ r = dissected_image_mount(dissected_image, mount_entry_path(m), UID_INVALID, dissect_image_flags); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to mount image: %m"); -+ -+ if (decrypted_image) { -+ r = decrypted_image_relinquish(decrypted_image); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to relinquish decrypted image: %m"); -+ } -+ -+ loop_device_relinquish(loop_device); - - return 1; - } -@@ -917,7 +1028,8 @@ static int follow_symlink( - - static int apply_mount( - const char *root_directory, -- MountEntry *m) { -+ MountEntry *m, -+ const NamespaceInfo *ns_info) { - - _cleanup_free_ char *inaccessible = NULL; - bool rbind = true, make = false; -@@ -925,6 +1037,7 @@ static int apply_mount( - int r; - - assert(m); -+ assert(ns_info); - - log_debug("Applying namespace mount on %s", mount_entry_path(m)); - -@@ -1029,7 +1142,10 @@ static int apply_mount( - return mount_sysfs(m); - - case PROCFS: -- return mount_procfs(m); -+ return mount_procfs(m, ns_info); -+ -+ case MOUNT_IMAGES: -+ return mount_images(m); - - default: - assert_not_reached("Unknown mode"); -@@ -1138,7 +1254,9 @@ static bool namespace_info_mount_apivfs(const NamespaceInfo *ns_info) { - - return ns_info->mount_apivfs || - ns_info->protect_control_groups || -- ns_info->protect_kernel_tunables; -+ ns_info->protect_kernel_tunables || -+ ns_info->protect_proc != PROTECT_PROC_DEFAULT || -+ ns_info->proc_subset != PROC_SUBSET_ALL; - } - - static size_t namespace_calculate_mounts( -@@ -1149,27 +1267,27 @@ static size_t namespace_calculate_mounts( - char** empty_directories, - size_t n_bind_mounts, - size_t n_temporary_filesystems, -+ size_t n_mount_images, - const char* tmp_dir, - const char* var_tmp_dir, -- const char* log_namespace, -- ProtectHome protect_home, -- ProtectSystem protect_system) { -+ const char *creds_path, -+ const char* log_namespace) { - - size_t protect_home_cnt; - size_t protect_system_cnt = -- (protect_system == PROTECT_SYSTEM_STRICT ? -+ (ns_info->protect_system == PROTECT_SYSTEM_STRICT ? - ELEMENTSOF(protect_system_strict_table) : -- ((protect_system == PROTECT_SYSTEM_FULL) ? -+ ((ns_info->protect_system == PROTECT_SYSTEM_FULL) ? - ELEMENTSOF(protect_system_full_table) : -- ((protect_system == PROTECT_SYSTEM_YES) ? -+ ((ns_info->protect_system == PROTECT_SYSTEM_YES) ? - ELEMENTSOF(protect_system_yes_table) : 0))); - - protect_home_cnt = -- (protect_home == PROTECT_HOME_YES ? -+ (ns_info->protect_home == PROTECT_HOME_YES ? - ELEMENTSOF(protect_home_yes_table) : -- ((protect_home == PROTECT_HOME_READ_ONLY) ? -+ ((ns_info->protect_home == PROTECT_HOME_READ_ONLY) ? - ELEMENTSOF(protect_home_read_only_table) : -- ((protect_home == PROTECT_HOME_TMPFS) ? -+ ((ns_info->protect_home == PROTECT_HOME_TMPFS) ? - ELEMENTSOF(protect_home_tmpfs_table) : 0))); - - return !!tmp_dir + !!var_tmp_dir + -@@ -1178,6 +1296,7 @@ static size_t namespace_calculate_mounts( - strv_length(inaccessible_paths) + - strv_length(empty_directories) + - n_bind_mounts + -+ n_mount_images + - n_temporary_filesystems + - ns_info->private_dev + - (ns_info->protect_kernel_tunables ? ELEMENTSOF(protect_kernel_tunables_table) : 0) + -@@ -1187,6 +1306,7 @@ static size_t namespace_calculate_mounts( - protect_home_cnt + protect_system_cnt + - (ns_info->protect_hostname ? 2 : 0) + - (namespace_info_mount_apivfs(ns_info) ? ELEMENTSOF(apivfs_table) : 0) + -+ (creds_path ? 2 : 1) + - !!log_namespace; - } - -@@ -1257,6 +1377,7 @@ static bool home_read_only( - int setup_namespace( - const char* root_directory, - const char* root_image, -+ const MountOptions *root_image_options, - const NamespaceInfo *ns_info, - char** read_write_paths, - char** read_only_paths, -@@ -1266,11 +1387,12 @@ int setup_namespace( - size_t n_bind_mounts, - const TemporaryFileSystem *temporary_filesystems, - size_t n_temporary_filesystems, -+ const MountImage *mount_images, -+ size_t n_mount_images, - const char* tmp_dir, - const char* var_tmp_dir, -+ const char *creds_path, - const char *log_namespace, -- ProtectHome protect_home, -- ProtectSystem protect_system, - unsigned long mount_flags, - const void *root_hash, - size_t root_hash_size, -@@ -1303,10 +1425,10 @@ int setup_namespace( - - /* Make the whole image read-only if we can determine that we only access it in a read-only fashion. */ - if (root_read_only(read_only_paths, -- protect_system) && -+ ns_info->protect_system) && - home_read_only(read_only_paths, inaccessible_paths, empty_directories, - bind_mounts, n_bind_mounts, temporary_filesystems, n_temporary_filesystems, -- protect_home) && -+ ns_info->protect_home) && - strv_isempty(read_write_paths)) - dissect_image_flags |= DISSECT_IMAGE_READ_ONLY; - -@@ -1331,6 +1453,7 @@ int setup_namespace( - root_hash ?: root_hash_decoded, - root_hash_size, - root_verity ?: verity_data, -+ root_image_options, - dissect_image_flags, - &dissected_image); - if (r < 0) -@@ -1372,9 +1495,10 @@ int setup_namespace( - empty_directories, - n_bind_mounts, - n_temporary_filesystems, -+ n_mount_images, - tmp_dir, var_tmp_dir, -- log_namespace, -- protect_home, protect_system); -+ creds_path, -+ log_namespace); - - if (n_mounts > 0) { - m = mounts = new0(MountEntry, n_mounts); -@@ -1425,6 +1549,10 @@ int setup_namespace( - }; - } - -+ r = append_mount_images(&m, mount_images, n_mount_images); -+ if (r < 0) -+ goto finish; -+ - if (ns_info->private_dev) { - *(m++) = (MountEntry) { - .path_const = "/dev", -@@ -1467,11 +1595,11 @@ int setup_namespace( - }; - } - -- r = append_protect_home(&m, protect_home, ns_info->ignore_protect_paths); -+ r = append_protect_home(&m, ns_info->protect_home, ns_info->ignore_protect_paths); - if (r < 0) - goto finish; - -- r = append_protect_system(&m, protect_system, false); -+ r = append_protect_system(&m, ns_info->protect_system, false); - if (r < 0) - goto finish; - -@@ -1495,6 +1623,35 @@ int setup_namespace( - }; - } - -+ if (creds_path) { -+ /* If our service has a credentials store configured, then bind that one in, but hide -+ * everything else. */ -+ -+ *(m++) = (MountEntry) { -+ .path_const = "/run/credentials", -+ .mode = TMPFS, -+ .read_only = true, -+ .options_const = "mode=0755" TMPFS_LIMITS_EMPTY_OR_ALMOST, -+ .flags = MS_NODEV|MS_STRICTATIME|MS_NOSUID|MS_NOEXEC, -+ }; -+ -+ *(m++) = (MountEntry) { -+ .path_const = creds_path, -+ .mode = BIND_MOUNT, -+ .read_only = true, -+ .source_const = creds_path, -+ }; -+ } else { -+ /* If our service has no credentials store configured, then make the whole -+ * credentials tree inaccessible wholesale. */ -+ -+ *(m++) = (MountEntry) { -+ .path_const = "/run/credentials", -+ .mode = INACCESSIBLE, -+ .ignore = true, -+ }; -+ } -+ - if (log_namespace) { - _cleanup_free_ char *q; - -@@ -1628,7 +1785,7 @@ int setup_namespace( - break; - } - -- r = apply_mount(root, m); -+ r = apply_mount(root, m, ns_info); - if (r < 0) { - if (error_path && mount_entry_path(m)) - *error_path = strdup(mount_entry_path(m)); -@@ -1739,6 +1896,74 @@ int bind_mount_add(BindMount **b, size_t *n, const BindMount *item) { - return 0; - } - -+MountImage* mount_image_free_many(MountImage *m, size_t *n) { -+ size_t i; -+ -+ assert(n); -+ assert(m || *n == 0); -+ -+ for (i = 0; i < *n; i++) { -+ free(m[i].source); -+ free(m[i].destination); -+ mount_options_free_all(m[i].mount_options); -+ } -+ -+ free(m); -+ *n = 0; -+ return NULL; -+} -+ -+int mount_image_add(MountImage **m, size_t *n, const MountImage *item) { -+ _cleanup_free_ char *s = NULL, *d = NULL; -+ _cleanup_(mount_options_free_allp) MountOptions *options = NULL; -+ MountOptions *i; -+ MountImage *c; -+ -+ assert(m); -+ assert(n); -+ assert(item); -+ -+ s = strdup(item->source); -+ if (!s) -+ return -ENOMEM; -+ -+ d = strdup(item->destination); -+ if (!d) -+ return -ENOMEM; -+ -+ LIST_FOREACH(mount_options, i, item->mount_options) { -+ _cleanup_(mount_options_free_allp) MountOptions *o; -+ -+ o = new(MountOptions, 1); -+ if (!o) -+ return -ENOMEM; -+ -+ *o = (MountOptions) { -+ .partition_designator = i->partition_designator, -+ .options = strdup(i->options), -+ }; -+ if (!o->options) -+ return -ENOMEM; -+ -+ LIST_APPEND(mount_options, options, TAKE_PTR(o)); -+ } -+ -+ c = reallocarray(*m, *n + 1, sizeof(MountImage)); -+ if (!c) -+ return -ENOMEM; -+ -+ *m = c; -+ -+ c[(*n) ++] = (MountImage) { -+ .source = TAKE_PTR(s), -+ .destination = TAKE_PTR(d), -+ .mount_options = TAKE_PTR(options), -+ .ignore_enoent = item->ignore_enoent, -+ }; -+ -+ return 0; -+} -+ - void temporary_filesystem_free_many(TemporaryFileSystem *t, size_t n) { - size_t i; - -@@ -1830,11 +2055,11 @@ static int make_tmp_prefix(const char *prefix) { - static int make_tmp_subdir(const char *parent, char **ret) { - _cleanup_free_ char *y = NULL; - -- RUN_WITH_UMASK(0000) { -- y = strjoin(parent, "/tmp"); -- if (!y) -- return -ENOMEM; -+ y = path_join(parent, "/tmp"); -+ if (!y) -+ return -ENOMEM; - -+ RUN_WITH_UMASK(0000) { - if (mkdir(y, 0777 | S_ISVTX) < 0) - return -errno; - } -@@ -1890,9 +2115,9 @@ static int setup_one_tmp_dir(const char *id, const char *prefix, char **path, ch - if (r < 0) - return r; - -- x = strdup(RUN_SYSTEMD_EMPTY); -- if (!x) -- return -ENOMEM; -+ r = free_and_strdup(&x, RUN_SYSTEMD_EMPTY); -+ if (r < 0) -+ return r; - } - - *path = TAKE_PTR(x); -@@ -2080,3 +2305,19 @@ static const char* const namespace_type_table[] = { - }; - - DEFINE_STRING_TABLE_LOOKUP(namespace_type, NamespaceType); -+ -+static const char* const protect_proc_table[_PROTECT_PROC_MAX] = { -+ [PROTECT_PROC_DEFAULT] = "default", -+ [PROTECT_PROC_NOACCESS] = "noaccess", -+ [PROTECT_PROC_INVISIBLE] = "invisible", -+ [PROTECT_PROC_PTRACEABLE] = "ptraceable", -+}; -+ -+DEFINE_STRING_TABLE_LOOKUP(protect_proc, ProtectProc); -+ -+static const char* const proc_subset_table[_PROC_SUBSET_MAX] = { -+ [PROC_SUBSET_ALL] = "all", -+ [PROC_SUBSET_PID] = "pid", -+}; -+ -+DEFINE_STRING_TABLE_LOOKUP(proc_subset, ProcSubset); -diff --git a/src/core/namespace.h b/src/core/namespace.h -index b182223..13cc0e8 100644 ---- a/src/core/namespace.h -+++ b/src/core/namespace.h -@@ -8,6 +8,7 @@ - typedef struct NamespaceInfo NamespaceInfo; - typedef struct BindMount BindMount; - typedef struct TemporaryFileSystem TemporaryFileSystem; -+typedef struct MountImage MountImage; - - #include - -@@ -46,6 +47,22 @@ typedef enum ProtectSystem { - _PROTECT_SYSTEM_INVALID = -1 - } ProtectSystem; - -+typedef enum ProtectProc { -+ PROTECT_PROC_DEFAULT, -+ PROTECT_PROC_NOACCESS, /* hidepid=noaccess */ -+ PROTECT_PROC_INVISIBLE, /* hidepid=invisible */ -+ PROTECT_PROC_PTRACEABLE, /* hidepid=ptraceable */ -+ _PROTECT_PROC_MAX, -+ _PROTECT_PROC_INVALID = -1, -+} ProtectProc; -+ -+typedef enum ProcSubset { -+ PROC_SUBSET_ALL, -+ PROC_SUBSET_PID, /* subset=pid */ -+ _PROC_SUBSET_MAX, -+ _PROC_SUBSET_INVALID = -1, -+} ProcSubset; -+ - struct NamespaceInfo { - bool ignore_protect_paths:1; - bool private_dev:1; -@@ -56,6 +73,10 @@ struct NamespaceInfo { - bool protect_kernel_logs:1; - bool mount_apivfs:1; - bool protect_hostname:1; -+ ProtectHome protect_home; -+ ProtectSystem protect_system; -+ ProtectProc protect_proc; -+ ProcSubset proc_subset; - }; - - struct BindMount { -@@ -72,9 +93,17 @@ struct TemporaryFileSystem { - char *options; - }; - -+struct MountImage { -+ char *source; -+ char *destination; -+ LIST_HEAD(MountOptions, mount_options); -+ bool ignore_enoent; -+}; -+ - int setup_namespace( - const char *root_directory, - const char *root_image, -+ const MountOptions *root_image_options, - const NamespaceInfo *ns_info, - char **read_write_paths, - char **read_only_paths, -@@ -84,11 +113,12 @@ int setup_namespace( - size_t n_bind_mounts, - const TemporaryFileSystem *temporary_filesystems, - size_t n_temporary_filesystems, -+ const MountImage *mount_images, -+ size_t n_mount_images, - const char *tmp_dir, - const char *var_tmp_dir, -+ const char *creds_path, - const char *log_namespace, -- ProtectHome protect_home, -- ProtectSystem protect_system, - unsigned long mount_flags, - const void *root_hash, - size_t root_hash_size, -@@ -124,6 +154,12 @@ ProtectHome protect_home_from_string(const char *s) _pure_; - const char* protect_system_to_string(ProtectSystem p) _const_; - ProtectSystem protect_system_from_string(const char *s) _pure_; - -+const char* protect_proc_to_string(ProtectProc i) _const_; -+ProtectProc protect_proc_from_string(const char *s) _pure_; -+ -+const char* proc_subset_to_string(ProcSubset i) _const_; -+ProcSubset proc_subset_from_string(const char *s) _pure_; -+ - void bind_mount_free_many(BindMount *b, size_t n); - int bind_mount_add(BindMount **b, size_t *n, const BindMount *item); - -@@ -131,6 +167,9 @@ void temporary_filesystem_free_many(TemporaryFileSystem *t, size_t n); - int temporary_filesystem_add(TemporaryFileSystem **t, size_t *n, - const char *path, const char *options); - -+MountImage* mount_image_free_many(MountImage *m, size_t *n); -+int mount_image_add(MountImage **m, size_t *n, const MountImage *item); -+ - const char* namespace_type_to_string(NamespaceType t) _const_; - NamespaceType namespace_type_from_string(const char *s) _pure_; - -diff --git a/src/core/path.c b/src/core/path.c -index 1c3c28e..4f4e710 100644 ---- a/src/core/path.c -+++ b/src/core/path.c -@@ -748,10 +748,23 @@ static void path_trigger_notify(Unit *u, Unit *other) { - assert(u); - assert(other); - -- /* Invoked whenever the unit we trigger changes state or gains -- * or loses a job */ -+ /* Invoked whenever the unit we trigger changes state or gains or loses a job */ - -- if (other->load_state != UNIT_LOADED) -+ /* Filter out invocations with bogus state */ -+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); -+ -+ /* Don't propagate state changes from the triggered unit if we are already down */ -+ if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING)) -+ return; -+ -+ /* Propagate start limit hit state */ -+ if (other->start_limit_hit) { -+ path_enter_dead(p, PATH_FAILURE_UNIT_START_LIMIT_HIT); -+ return; -+ } -+ -+ /* Don't propagate anything if there's still a job queued */ -+ if (other->job) - return; - - if (p->state == PATH_RUNNING && -@@ -790,6 +803,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = { - [PATH_SUCCESS] = "success", - [PATH_FAILURE_RESOURCES] = "resources", - [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", -+ [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit", - }; - - DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); -diff --git a/src/core/path.h b/src/core/path.h -index 9e28365..4043650 100644 ---- a/src/core/path.h -+++ b/src/core/path.h -@@ -45,6 +45,7 @@ typedef enum PathResult { - PATH_SUCCESS, - PATH_FAILURE_RESOURCES, - PATH_FAILURE_START_LIMIT_HIT, -+ PATH_FAILURE_UNIT_START_LIMIT_HIT, - _PATH_RESULT_MAX, - _PATH_RESULT_INVALID = -1 - } PathResult; -diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c -index 1d52b5f..b81714f 100644 ---- a/src/core/selinux-access.c -+++ b/src/core/selinux-access.c -@@ -198,7 +198,7 @@ int mac_selinux_generic_access_check( - return r; - - /* delay call until we checked in `access_init()` if SELinux is actually enabled */ -- enforce = security_getenforce() != 0; -+ enforce = mac_selinux_enforcing(); - - r = sd_bus_query_sender_creds( - message, -@@ -278,7 +278,7 @@ int mac_selinux_generic_access_check( - return enforce ? r : 0; - } - --#else -+#else /* HAVE_SELINUX */ - - int mac_selinux_generic_access_check( - sd_bus_message *message, -@@ -289,4 +289,4 @@ int mac_selinux_generic_access_check( - return 0; - } - --#endif -+#endif /* HAVE_SELINUX */ -diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c -index 817069b..40da8dd 100644 ---- a/src/core/selinux-setup.c -+++ b/src/core/selinux-setup.c -@@ -50,7 +50,10 @@ int mac_selinux_setup(bool *loaded_policy) { - - /* Already initialized by somebody else? */ - r = getcon_raw(&con); -- /* getcon_raw can return 0, and still give us a NULL pointer. */ -+ /* getcon_raw can return 0, and still give us a NULL pointer if -+ * /proc/self/attr/current is empty. SELinux guarantees this won't -+ * happen, but that file isn't specific to SELinux, and may be provided -+ * by some other arbitrary LSM with different semantics. */ - if (r == 0 && con) { - initialized = !streq(con, "kernel"); - freecon(con); -diff --git a/src/core/service.c b/src/core/service.c -index 00e6194..863b675 100644 ---- a/src/core/service.c -+++ b/src/core/service.c -@@ -589,9 +589,6 @@ static int service_verify(Service *s) { - return -ENOEXEC; - } - -- if (s->bus_name && s->type != SERVICE_DBUS) -- log_unit_warning(UNIT(s), "Service has a D-Bus service name specified, but is not of type dbus. Ignoring."); -- - if (s->exec_context.pam_name && !IN_SET(s->kill_context.kill_mode, KILL_CONTROL_GROUP, KILL_MIXED)) { - log_unit_error(UNIT(s), "Service has PAM enabled. Kill mode must be set to 'control-group' or 'mixed'. Refusing."); - return -ENOEXEC; -@@ -687,7 +684,7 @@ static int service_setup_bus_name(Service *s) { - - assert(s); - -- if (!s->bus_name) -+ if (s->type != SERVICE_DBUS) - return 0; - - r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, true, UNIT_DEPENDENCY_FILE); -@@ -918,17 +915,17 @@ static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) { - * good */ - - if (pid == getpid_cached() || pid == 1) { -- log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the manager, refusing.", pid); -+ log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" is the manager, refusing.", pid); - return -EPERM; - } - - if (pid == s->control_pid) { -- log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the control process, refusing.", pid); -+ log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" is the control process, refusing.", pid); - return -EPERM; - } - - if (!pid_is_alive(pid)) { -- log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" does not exist or is a zombie.", pid); -+ log_unit_full(UNIT(s), prio, "New main PID "PID_FMT" does not exist or is a zombie.", pid); - return -ESRCH; - } - -@@ -958,16 +955,16 @@ static int service_load_pid_file(Service *s, bool may_warn) { - - r = chase_symlinks(s->pid_file, NULL, CHASE_SAFE, NULL, &fd); - if (r == -ENOLINK) { -- log_unit_full(UNIT(s), LOG_DEBUG, r, -- "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); -+ log_unit_debug_errno(UNIT(s), r, -+ "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); - - questionable_pid_file = true; - - r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd); - } - if (r < 0) -- return log_unit_full(UNIT(s), prio, fd, -- "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); -+ return log_unit_full_errno(UNIT(s), prio, fd, -+ "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); - - /* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd - * chase_symlinks() returned us into a proper fd first. */ -@@ -980,7 +977,7 @@ static int service_load_pid_file(Service *s, bool may_warn) { - - r = parse_pid(k, &pid); - if (r < 0) -- return log_unit_full(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file); -+ return log_unit_full_errno(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file); - - if (s->main_pid_known && pid == s->main_pid) - return 0; -@@ -1034,7 +1031,7 @@ static void service_search_main_pid(Service *s) { - - assert(s); - -- /* If we know it anyway, don't ever fallback to unreliable -+ /* If we know it anyway, don't ever fall back to unreliable - * heuristics */ - if (s->main_pid_known) - return; -@@ -1273,13 +1270,12 @@ static int service_collect_fds( - - rn_socket_fds = 1; - } else { -- Iterator i; - void *v; - Unit *u; - - /* Pass all our configured sockets for singleton services */ - -- HASHMAP_FOREACH_KEY(v, u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i) { -+ HASHMAP_FOREACH_KEY(v, u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY]) { - _cleanup_free_ int *cfds = NULL; - Socket *sock; - int cn_fds; -@@ -1801,7 +1797,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) - s->exec_runtime = exec_runtime_unref(s->exec_runtime, true); - - /* Also, remove the runtime directory */ -- unit_destroy_runtime_directory(UNIT(s), &s->exec_context); -+ unit_destroy_runtime_data(UNIT(s), &s->exec_context); - - /* Get rid of the IPC bits of the user */ - unit_unref_uid_gid(UNIT(s), true); -@@ -2156,7 +2152,7 @@ static void service_enter_start(Service *s) { - r = service_spawn(s, - c, - timeout, -- EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG, -+ EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG|EXEC_WRITE_CREDENTIALS, - &pid); - if (r < 0) - goto fail; -@@ -2314,7 +2310,7 @@ static void service_enter_restart(Service *s) { - return; - - fail: -- log_unit_warning(UNIT(s), "Failed to schedule restart job: %s", bus_error_message(&error, -r)); -+ log_unit_warning(UNIT(s), "Failed to schedule restart job: %s", bus_error_message(&error, r)); - service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false); - } - -@@ -2330,7 +2326,7 @@ static void service_enter_reload_by_notify(Service *s) { - /* service_enter_reload_by_notify is never called during a reload, thus no loops are possible. */ - r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error); - if (r < 0) -- log_unit_warning(UNIT(s), "Failed to schedule propagation of reload: %s", bus_error_message(&error, -r)); -+ log_unit_warning(UNIT(s), "Failed to schedule propagation of reload: %s", bus_error_message(&error, r)); - } - - static void service_enter_reload(Service *s) { -diff --git a/src/core/slice.c b/src/core/slice.c -index f4f63fc..49541aa 100644 ---- a/src/core/slice.c -+++ b/src/core/slice.c -@@ -351,11 +351,10 @@ static void slice_enumerate_perpetual(Manager *m) { - static bool slice_freezer_action_supported_by_children(Unit *s) { - Unit *member; - void *v; -- Iterator i; - - assert(s); - -- HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE], i) { -+ HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE]) { - int r; - - if (UNIT_DEREF(member->slice) != s) -@@ -377,16 +376,17 @@ static bool slice_freezer_action_supported_by_children(Unit *s) { - static int slice_freezer_action(Unit *s, FreezerAction action) { - Unit *member; - void *v; -- Iterator i; - int r; - - assert(s); - assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW)); - -- if (!slice_freezer_action_supported_by_children(s)) -- return log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice"); -+ if (!slice_freezer_action_supported_by_children(s)) { -+ log_unit_warning(s, "Requested freezer operation is not supported by all children of the slice"); -+ return 0; -+ } - -- HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE], i) { -+ HASHMAP_FOREACH_KEY(v, member, s->dependencies[UNIT_BEFORE]) { - if (UNIT_DEREF(member->slice) != s) - continue; - -diff --git a/src/core/socket.c b/src/core/socket.c -index 127195c..be7d364 100644 ---- a/src/core/socket.c -+++ b/src/core/socket.c -@@ -18,6 +18,7 @@ - #include "dbus-socket.h" - #include "dbus-unit.h" - #include "def.h" -+#include "errno-list.h" - #include "exit-status.h" - #include "fd-util.h" - #include "format-util.h" -@@ -72,6 +73,7 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { - - static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); - static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); -+static void flush_ports(Socket *s); - - static void socket_init(Unit *u) { - Socket *s = SOCKET(u); -@@ -205,27 +207,6 @@ static int socket_arm_timer(Socket *s, usec_t usec) { - return 0; - } - --static int socket_instantiate_service(Socket *s, int cfd) { -- Unit *service; -- int r; -- -- assert(s); -- assert(cfd >= 0); -- -- /* This fills in s->service if it isn't filled in yet. For Accept=yes sockets we create the next -- * connection service here. For Accept=no this is mostly a NOP since the service is figured out at -- * load time anyway. */ -- -- r = socket_load_service_unit(s, cfd, &service); -- if (r < 0) -- return r; -- -- unit_ref_set(&s->service, UNIT(s), service); -- -- return unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, service, -- false, UNIT_DEPENDENCY_IMPLICIT); --} -- - static bool have_non_accept_socket(Socket *s) { - SocketPort *p; - -@@ -669,6 +650,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { - prefix, s->n_connections, - prefix, s->max_connections, - prefix, s->max_connections_per_source); -+ else -+ fprintf(f, -+ "%sFlushPending: %s\n", -+ prefix, yes_no(s->flush_pending)); -+ - - if (s->priority >= 0) - fprintf(f, -@@ -993,10 +979,11 @@ static void socket_close_fds(Socket *s) { - (void) unlink(*i); - } - --static void socket_apply_socket_options(Socket *s, int fd) { -+static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) { - int r; - - assert(s); -+ assert(p); - assert(fd >= 0); - - if (s->keep_alive) { -@@ -1060,7 +1047,7 @@ static void socket_apply_socket_options(Socket *s, int fd) { - } - - if (s->pass_pktinfo) { -- r = socket_pass_pktinfo(fd, true); -+ r = socket_set_recvpktinfo(fd, socket_address_family(&p->address), true); - if (r < 0) - log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m"); - } -@@ -1072,20 +1059,17 @@ static void socket_apply_socket_options(Socket *s, int fd) { - } - - if (s->receive_buffer > 0) { -- /* We first try with SO_RCVBUFFORCE, in case we have the perms for that */ -- if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, s->receive_buffer) < 0) { -- r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, s->receive_buffer); -- if (r < 0) -- log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF failed: %m"); -- } -+ r = fd_set_rcvbuf(fd, s->receive_buffer, false); -+ if (r < 0) -+ log_unit_full_errno(UNIT(s), ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_WARNING, r, -+ "SO_RCVBUF/SO_RCVBUFFORCE failed: %m"); - } - - if (s->send_buffer > 0) { -- if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, s->send_buffer) < 0) { -- r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, s->send_buffer); -- if (r < 0) -- log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF failed: %m"); -- } -+ r = fd_set_sndbuf(fd, s->send_buffer, false); -+ if (r < 0) -+ log_unit_full_errno(UNIT(s), ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_WARNING, r, -+ "SO_SNDBUF/SO_SNDBUFFORCE failed: %m"); - } - - if (s->mark >= 0) { -@@ -1101,16 +1085,8 @@ static void socket_apply_socket_options(Socket *s, int fd) { - } - - if (s->ip_ttl >= 0) { -- int x; -- -- r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, s->ip_ttl); -- -- if (socket_ipv6_is_supported()) -- x = setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, s->ip_ttl); -- else -- x = -EAFNOSUPPORT; -- -- if (r < 0 && x < 0) -+ r = socket_set_ttl(fd, socket_address_family(&p->address), s->ip_ttl); -+ if (r < 0) - log_unit_warning_errno(UNIT(s), r, "IP_TTL/IPV6_UNICAST_HOPS failed: %m"); - } - -@@ -1418,11 +1394,12 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) { - - if (cfd >= 0) { - r = instance_from_socket(cfd, s->n_accepted, &instance); -- if (r == -ENOTCONN) -- /* ENOTCONN is legitimate if TCP RST was received. -- * This connection is over, but the socket unit lives on. */ -+ if (ERRNO_IS_DISCONNECT(r)) -+ /* ENOTCONN is legitimate if TCP RST was received. Other socket families might return -+ * different errors. This connection is over, but the socket unit lives on. */ - return log_unit_debug_errno(UNIT(s), r, -- "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring."); -+ "Got %s on incoming socket, assuming aborted connection attempt, ignoring.", -+ errno_to_name(r)); - if (r < 0) - return r; - } -@@ -1682,7 +1659,7 @@ static int socket_open_fds(Socket *_s) { - if (p->fd < 0) - return p->fd; - -- socket_apply_socket_options(s, p->fd); -+ socket_apply_socket_options(s, p, p->fd); - socket_symlink(s); - break; - -@@ -2080,7 +2057,7 @@ static void socket_enter_dead(Socket *s, SocketResult f) { - - s->exec_runtime = exec_runtime_unref(s->exec_runtime, true); - -- unit_destroy_runtime_directory(UNIT(s), &s->exec_context); -+ unit_destroy_runtime_data(UNIT(s), &s->exec_context); - - unit_unref_uid_gid(UNIT(s), true); - -@@ -2201,6 +2178,11 @@ static void socket_enter_listening(Socket *s) { - int r; - assert(s); - -+ if (!s->accept && s->flush_pending) { -+ log_unit_debug(UNIT(s), "Flushing socket before listening."); -+ flush_ports(s); -+ } -+ - r = socket_watch_fds(s); - if (r < 0) { - log_unit_warning_errno(UNIT(s), r, "Failed to watch sockets: %m"); -@@ -2315,13 +2297,14 @@ static void flush_ports(Socket *s) { - } - } - --static void socket_enter_running(Socket *s, int cfd) { -+static void socket_enter_running(Socket *s, int cfd_in) { -+ /* Note that this call takes possession of the connection fd passed. It either has to assign it -+ * somewhere or close it. */ -+ _cleanup_close_ int cfd = cfd_in; -+ - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - int r; - -- /* Note that this call takes possession of the connection fd passed. It either has to assign it somewhere or -- * close it. */ -- - assert(s); - - /* We don't take connections anymore if we are supposed to shut down anyway */ -@@ -2331,9 +2314,8 @@ static void socket_enter_running(Socket *s, int cfd) { - - if (cfd >= 0) - goto refuse; -- else -- flush_ports(s); - -+ flush_ports(s); - return; - } - -@@ -2346,12 +2328,11 @@ static void socket_enter_running(Socket *s, int cfd) { - if (cfd < 0) { - bool pending = false; - Unit *other; -- Iterator i; - void *v; - - /* If there's already a start pending don't bother to - * do anything */ -- HASHMAP_FOREACH_KEY(v, other, UNIT(s)->dependencies[UNIT_TRIGGERS], i) -+ HASHMAP_FOREACH_KEY(v, other, UNIT(s)->dependencies[UNIT_TRIGGERS]) - if (unit_active_or_pending(other)) { - pending = true; - break; -@@ -2359,8 +2340,8 @@ static void socket_enter_running(Socket *s, int cfd) { - - if (!pending) { - if (!UNIT_ISSET(s->service)) { -- log_unit_error(UNIT(s), "Service to activate vanished, refusing activation."); -- r = -ENOENT; -+ r = log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT), -+ "Service to activate vanished, refusing activation."); - goto fail; - } - -@@ -2372,7 +2353,7 @@ static void socket_enter_running(Socket *s, int cfd) { - socket_set_state(s, SOCKET_RUNNING); - } else { - _cleanup_(socket_peer_unrefp) SocketPeer *p = NULL; -- Service *service; -+ Unit *service; - - if (s->n_connections >= s->max_connections) { - log_unit_warning(UNIT(s), "Too many incoming connections (%u), dropping connection.", -@@ -2382,8 +2363,10 @@ static void socket_enter_running(Socket *s, int cfd) { - - if (s->max_connections_per_source > 0) { - r = socket_acquire_peer(s, cfd, &p); -- if (r < 0) -- goto refuse; -+ if (ERRNO_IS_DISCONNECT(r)) -+ return; -+ if (r < 0) /* We didn't have enough resources to acquire peer information, let's fail. */ -+ goto fail; - if (r > 0 && p->n_ref > s->max_connections_per_source) { - _cleanup_free_ char *t = NULL; - -@@ -2396,29 +2379,35 @@ static void socket_enter_running(Socket *s, int cfd) { - } - } - -- r = socket_instantiate_service(s, cfd); -+ r = socket_load_service_unit(s, cfd, &service); -+ if (ERRNO_IS_DISCONNECT(r)) -+ return; - if (r < 0) - goto fail; - -- service = SERVICE(UNIT_DEREF(s->service)); -- unit_ref_unset(&s->service); -+ r = unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, service, -+ false, UNIT_DEPENDENCY_IMPLICIT); -+ if (r < 0) -+ goto fail; - - s->n_accepted++; - -- r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net); -+ r = service_set_socket_fd(SERVICE(service), cfd, s, s->selinux_context_from_net); -+ if (ERRNO_IS_DISCONNECT(r)) -+ return; - if (r < 0) - goto fail; - - TAKE_FD(cfd); /* We passed ownership of the fd to the service now. Forget it here. */ - s->n_connections++; - -- service->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */ -+ SERVICE(service)->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */ - -- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, NULL, &error, NULL); -+ r = manager_add_job(UNIT(s)->manager, JOB_START, service, JOB_REPLACE, NULL, &error, NULL); - if (r < 0) { - /* We failed to activate the new service, but it still exists. Let's make sure the - * service closes and forgets the connection fd again, immediately. */ -- service_close_socket_fd(service); -+ service_close_socket_fd(SERVICE(service)); - goto fail; - } - -@@ -2426,20 +2415,23 @@ static void socket_enter_running(Socket *s, int cfd) { - unit_add_to_dbus_queue(UNIT(s)); - } - -+ TAKE_FD(cfd); - return; - - refuse: - s->n_refused++; -- safe_close(cfd); - return; - - fail: -- log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s", -- cfd >= 0 ? "template" : "non-template", -- bus_error_message(&error, r)); -+ if (ERRNO_IS_RESOURCE(r)) -+ log_unit_warning(UNIT(s), "Failed to queue service startup job: %s", -+ bus_error_message(&error, r)); -+ else -+ log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s", -+ cfd >= 0 ? "template" : "non-template", -+ bus_error_message(&error, r)); - - socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); -- safe_close(cfd); - } - - static void socket_run_next(Socket *s) { -@@ -2785,7 +2777,6 @@ static void socket_distribute_fds(Unit *u, FDSet *fds) { - assert(u); - - LIST_FOREACH(port, p, s->ports) { -- Iterator i; - int fd; - - if (p->type != SOCKET_SOCKET) -@@ -2794,7 +2785,7 @@ static void socket_distribute_fds(Unit *u, FDSet *fds) { - if (p->fd >= 0) - continue; - -- FDSET_FOREACH(fd, fds, i) { -+ FDSET_FOREACH(fd, fds) { - if (socket_address_matches_fd(&p->address, fd)) { - p->fd = fdset_remove(fds, fd); - s->deserialized_state = SOCKET_LISTENING; -@@ -3008,7 +2999,7 @@ static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, - if (cfd < 0) - goto fail; - -- socket_apply_socket_options(p->socket, cfd); -+ socket_apply_socket_options(p->socket, p, cfd); - } - - socket_enter_running(p->socket, cfd); -@@ -3274,13 +3265,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) { - assert(other); - - /* Filter out invocations with bogus state */ -- if (!IN_SET(other->load_state, -- UNIT_LOADED, -- UNIT_NOT_FOUND, -- UNIT_BAD_SETTING, -- UNIT_ERROR, -- UNIT_MASKED) || other->type != UNIT_SERVICE) -- return; -+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); -+ assert(other->type == UNIT_SERVICE); - - /* Don't propagate state changes from the service if we are already down */ - if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING)) -diff --git a/src/core/socket.h b/src/core/socket.h -index bb14e6b..cf475e2 100644 ---- a/src/core/socket.h -+++ b/src/core/socket.h -@@ -110,6 +110,7 @@ struct Socket { - bool accept; - bool remove_on_stop; - bool writable; -+ bool flush_pending; - - int socket_protocol; - -diff --git a/src/core/swap.c b/src/core/swap.c -index 20179de..fa600a9 100644 ---- a/src/core/swap.c -+++ b/src/core/swap.c -@@ -284,8 +284,8 @@ static int swap_load_devnode(Swap *s) { - - r = device_new_from_stat_rdev(&d, &st); - if (r < 0) { -- log_unit_full(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, -- "Failed to allocate device for swap %s: %m", s->what); -+ log_unit_full_errno(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, -+ "Failed to allocate device for swap %s: %m", s->what); - return 0; - } - -@@ -706,7 +706,7 @@ static void swap_enter_dead(Swap *s, SwapResult f) { - - s->exec_runtime = exec_runtime_unref(s->exec_runtime, true); - -- unit_destroy_runtime_directory(UNIT(s), &s->exec_context); -+ unit_destroy_runtime_data(UNIT(s), &s->exec_context); - - unit_unref_uid_gid(UNIT(s), true); - -@@ -1425,7 +1425,7 @@ int swap_process_device_new(Manager *m, sd_device *dev) { - _cleanup_free_ char *e = NULL; - const char *dn, *devlink; - Unit *u; -- int r = 0; -+ int r; - - assert(m); - assert(dev); -@@ -1463,7 +1463,7 @@ int swap_process_device_new(Manager *m, sd_device *dev) { - - int swap_process_device_remove(Manager *m, sd_device *dev) { - const char *dn; -- int r = 0; -+ int r; - Swap *s; - - r = sd_device_get_devname(dev, &dn); -diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in -index 8424837..3af9f99 100644 ---- a/src/core/systemd.pc.in -+++ b/src/core/systemd.pc.in -@@ -11,7 +11,7 @@ - # considered deprecated (though there is no plan to remove them). New names - # shall have underscores. - --prefix=@prefix@ -+prefix=/usr - root_prefix=@rootprefix_noslash@ - rootprefix=${root_prefix} - sysconf_dir=@sysconfdir@ -@@ -26,10 +26,10 @@ systemdsystemunitdir=${systemd_system_unit_dir} - systemd_system_preset_dir=${rootprefix}/lib/systemd/system-preset - systemdsystempresetdir=${systemd_system_preset_dir} - --systemd_user_unit_dir=${prefix}/lib/systemd/user -+systemd_user_unit_dir=/usr/lib/systemd/user - systemduserunitdir=${systemd_user_unit_dir} - --systemd_user_preset_dir=${prefix}/lib/systemd/user-preset -+systemd_user_preset_dir=/usr/lib/systemd/user-preset - systemduserpresetdir=${systemd_user_preset_dir} - - systemd_system_conf_dir=${sysconfdir}/systemd/system -@@ -47,7 +47,7 @@ systemduserunitpath=${systemd_user_unit_path} - systemd_system_generator_dir=${root_prefix}/lib/systemd/system-generators - systemdsystemgeneratordir=${systemd_system_generator_dir} - --systemd_user_generator_dir=${prefix}/lib/systemd/user-generators -+systemd_user_generator_dir=/usr/lib/systemd/user-generators - systemdusergeneratordir=${systemd_user_generator_dir} - - systemd_system_generator_path=/run/systemd/system-generators:/etc/systemd/system-generators:/usr/local/lib/systemd/system-generators:${systemd_system_generator_dir} -@@ -62,7 +62,7 @@ systemdsleepdir=${systemd_sleep_dir} - systemd_shutdown_dir=${root_prefix}/lib/systemd/system-shutdown - systemdshutdowndir=${systemd_shutdown_dir} - --tmpfiles_dir=${prefix}/lib/tmpfiles.d -+tmpfiles_dir=/usr/lib/tmpfiles.d - tmpfilesdir=${tmpfiles_dir} - - sysusers_dir=${rootprefix}/lib/sysusers.d -@@ -77,7 +77,7 @@ binfmtdir=${binfmt_dir} - modules_load_dir=${rootprefix}/lib/modules-load.d - modulesloaddir=${modules_load_dir} - --catalog_dir=${prefix}/lib/systemd/catalog -+catalog_dir=/usr/lib/systemd/catalog - catalogdir=${catalog_dir} - - system_uid_max=@systemuidmax@ -diff --git a/src/core/target.c b/src/core/target.c -index 65affce..3f85773 100644 ---- a/src/core/target.c -+++ b/src/core/target.c -@@ -57,10 +57,9 @@ static int target_add_default_dependencies(Target *t) { - - for (k = 0; k < ELEMENTSOF(deps); k++) { - Unit *other; -- Iterator i; - void *v; - -- HASHMAP_FOREACH_KEY(v, other, UNIT(t)->dependencies[deps[k]], i) { -+ HASHMAP_FOREACH_KEY(v, other, UNIT(t)->dependencies[deps[k]]) { - r = unit_add_default_target_dependency(other, UNIT(t)); - if (r < 0) - return r; -diff --git a/src/core/timer.c b/src/core/timer.c -index 03a9c14..94388f0 100644 ---- a/src/core/timer.c -+++ b/src/core/timer.c -@@ -746,8 +746,8 @@ static void timer_trigger_notify(Unit *u, Unit *other) { - assert(u); - assert(other); - -- if (other->load_state != UNIT_LOADED) -- return; -+ /* Filter out invocations with bogus state */ -+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); - - /* Reenable all timers that depend on unit state */ - LIST_FOREACH(value, v, t->values) -diff --git a/src/core/transaction.c b/src/core/transaction.c -index 4a57b8e..f4cdbfe 100644 ---- a/src/core/transaction.c -+++ b/src/core/transaction.c -@@ -218,14 +218,13 @@ static int delete_one_unmergeable_job(Transaction *tr, Job *j) { - - static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) { - Job *j; -- Iterator i; - int r; - - assert(tr); - - /* First step, check whether any of the jobs for one specific - * task conflict. If so, try to drop one of them. */ -- HASHMAP_FOREACH(j, tr->jobs, i) { -+ HASHMAP_FOREACH(j, tr->jobs) { - JobType t; - Job *k; - -@@ -256,7 +255,7 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) { - } - - /* Second step, merge the jobs. */ -- HASHMAP_FOREACH(j, tr->jobs, i) { -+ HASHMAP_FOREACH(j, tr->jobs) { - JobType t = j->type; - Job *k; - -@@ -288,12 +287,11 @@ static void transaction_drop_redundant(Transaction *tr) { - assert(tr); - - do { -- Iterator i; - Job *j; - - again = false; - -- HASHMAP_FOREACH(j, tr->jobs, i) { -+ HASHMAP_FOREACH(j, tr->jobs) { - bool keep = false; - Job *k; - -@@ -349,7 +347,6 @@ static char* merge_unit_ids(const char* unit_log_field, char **pairs) { - } - - static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) { -- Iterator i; - Unit *u; - void *v; - int r; -@@ -453,7 +450,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi - * ordering dependencies and we test with job_compare() whether it is the 'before' edge in the job - * execution ordering. */ - for (d = 0; d < ELEMENTSOF(directions); d++) { -- HASHMAP_FOREACH_KEY(v, u, j->unit->dependencies[directions[d]], i) { -+ HASHMAP_FOREACH_KEY(v, u, j->unit->dependencies[directions[d]]) { - Job *o; - - /* Is there a job for this unit? */ -@@ -487,7 +484,6 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi - static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bus_error *e) { - Job *j; - int r; -- Iterator i; - unsigned g; - - assert(tr); -@@ -498,7 +494,7 @@ static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bu - - g = (*generation)++; - -- HASHMAP_FOREACH(j, tr->jobs, i) { -+ HASHMAP_FOREACH(j, tr->jobs) { - r = transaction_verify_order_one(tr, j, NULL, g, e); - if (r < 0) - return r; -@@ -515,12 +511,11 @@ static void transaction_collect_garbage(Transaction *tr) { - /* Drop jobs that are not required by any other job */ - - do { -- Iterator i; - Job *j; - - again = false; - -- HASHMAP_FOREACH(j, tr->jobs, i) { -+ HASHMAP_FOREACH(j, tr->jobs) { - if (tr->anchor_job == j) - continue; - -@@ -541,7 +536,6 @@ static void transaction_collect_garbage(Transaction *tr) { - } - - static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_error *e) { -- Iterator i; - Job *j; - - assert(tr); -@@ -549,7 +543,7 @@ static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_erro - /* Checks whether applying this transaction means that - * existing jobs would be replaced */ - -- HASHMAP_FOREACH(j, tr->jobs, i) { -+ HASHMAP_FOREACH(j, tr->jobs) { - - /* Assume merged */ - assert(!j->transaction_prev); -@@ -568,7 +562,6 @@ static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_erro - - static void transaction_minimize_impact(Transaction *tr) { - Job *j; -- Iterator i; - - assert(tr); - -@@ -576,7 +569,7 @@ static void transaction_minimize_impact(Transaction *tr) { - * or that stop a running service. */ - - rescan: -- HASHMAP_FOREACH(j, tr->jobs, i) { -+ HASHMAP_FOREACH(j, tr->jobs) { - LIST_FOREACH(transaction, j, j) { - bool stops_running_service, changes_existing_job; - -@@ -625,7 +618,6 @@ static int transaction_apply( - JobMode mode, - Set *affected_jobs) { - -- Iterator i; - Job *j; - int r; - -@@ -635,7 +627,7 @@ static int transaction_apply( - - /* When isolating first kill all installed jobs which - * aren't part of the new transaction */ -- HASHMAP_FOREACH(j, m->jobs, i) { -+ HASHMAP_FOREACH(j, m->jobs) { - assert(j->installed); - - if (j->unit->ignore_on_isolate) -@@ -651,7 +643,7 @@ static int transaction_apply( - } - } - -- HASHMAP_FOREACH(j, tr->jobs, i) { -+ HASHMAP_FOREACH(j, tr->jobs) { - /* Assume merged */ - assert(!j->transaction_prev); - assert(!j->transaction_next); -@@ -696,7 +688,7 @@ static int transaction_apply( - - rollback: - -- HASHMAP_FOREACH(j, tr->jobs, i) -+ HASHMAP_FOREACH(j, tr->jobs) - hashmap_remove(m->jobs, UINT32_TO_PTR(j->id)); - - return r; -@@ -709,7 +701,6 @@ int transaction_activate( - Set *affected_jobs, - sd_bus_error *e) { - -- Iterator i; - Job *j; - int r; - unsigned generation = 1; -@@ -722,7 +713,7 @@ int transaction_activate( - /* Reset the generation counter of all installed jobs. The detection of cycles - * looks at installed jobs. If they had a non-zero generation from some previous - * walk of the graph, the algorithm would break. */ -- HASHMAP_FOREACH(j, m->jobs, i) -+ HASHMAP_FOREACH(j, m->jobs) - j->generation = 0; - - /* First step: figure out which jobs matter */ -@@ -890,7 +881,6 @@ static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependen - } - - void transaction_add_propagate_reload_jobs(Transaction *tr, Unit *unit, Job *by, bool ignore_order, sd_bus_error *e) { -- Iterator i; - JobType nt; - Unit *dep; - void *v; -@@ -899,7 +889,7 @@ void transaction_add_propagate_reload_jobs(Transaction *tr, Unit *unit, Job *by, - assert(tr); - assert(unit); - -- HASHMAP_FOREACH_KEY(v, dep, unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) { -+ HASHMAP_FOREACH_KEY(v, dep, unit->dependencies[UNIT_PROPAGATES_RELOAD_TO]) { - nt = job_type_collapse(JOB_TRY_RELOAD, dep); - if (nt == JOB_NOP) - continue; -@@ -926,7 +916,6 @@ int transaction_add_job_and_dependencies( - sd_bus_error *e) { - - bool is_new; -- Iterator i; - Unit *dep; - Job *ret; - void *v; -@@ -949,7 +938,7 @@ int transaction_add_job_and_dependencies( - - /* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set - * temporarily. */ -- if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED)) -+ if (!UNIT_IS_LOAD_COMPLETE(unit->load_state)) - return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id); - - if (type != JOB_STOP) { -@@ -960,12 +949,14 @@ int transaction_add_job_and_dependencies( - * first if anything in the usual paths was modified since the last time - * the cache was loaded. Also check if the last time an attempt to load the - * unit was made was before the most recent cache refresh, so that we know -- * we need to try again - even if the cache is current, it might have been -+ * we need to try again — even if the cache is current, it might have been - * updated in a different context before we had a chance to retry loading - * this particular unit. -+ * - * Given building up the transaction is a synchronous operation, attempt - * to load the unit immediately. */ -- if (r < 0 && manager_unit_file_maybe_loadable_from_cache(unit)) { -+ if (r < 0 && manager_unit_cache_should_retry_load(unit)) { -+ sd_bus_error_free(e); - unit->load_state = UNIT_STUB; - r = unit_load(unit); - if (r < 0 || unit->load_state == UNIT_STUB) -@@ -1004,13 +995,12 @@ int transaction_add_job_and_dependencies( - /* If we are following some other unit, make sure we - * add all dependencies of everybody following. */ - if (unit_following_set(ret->unit, &following) > 0) { -- SET_FOREACH(dep, following, i) { -+ SET_FOREACH(dep, following) { - r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, false, false, ignore_order, e); - if (r < 0) { -- log_unit_full(dep, -- r == -ERFKILL ? LOG_INFO : LOG_WARNING, -- r, "Cannot add dependency job, ignoring: %s", -- bus_error_message(e, r)); -+ log_unit_full_errno(dep, r == -ERFKILL ? LOG_INFO : LOG_WARNING, r, -+ "Cannot add dependency job, ignoring: %s", -+ bus_error_message(e, r)); - sd_bus_error_free(e); - } - } -@@ -1020,7 +1010,7 @@ int transaction_add_job_and_dependencies( - - /* Finally, recursively add in all dependencies. */ - if (IN_SET(type, JOB_START, JOB_RESTART)) { -- HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_REQUIRES], i) { -+ HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_REQUIRES]) { - r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e); - if (r < 0) { - if (r != -EBADR) /* job type not applicable */ -@@ -1030,7 +1020,7 @@ int transaction_add_job_and_dependencies( - } - } - -- HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_BINDS_TO], i) { -+ HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_BINDS_TO]) { - r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e); - if (r < 0) { - if (r != -EBADR) /* job type not applicable */ -@@ -1040,19 +1030,19 @@ int transaction_add_job_and_dependencies( - } - } - -- HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_WANTS], i) { -+ HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_WANTS]) { - r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e); - if (r < 0) { - /* unit masked, job type not applicable and unit not found are not considered as errors. */ -- log_unit_full(dep, -- IN_SET(r, -ERFKILL, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING, -- r, "Cannot add dependency job, ignoring: %s", -- bus_error_message(e, r)); -+ log_unit_full_errno(dep, -+ IN_SET(r, -ERFKILL, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING, -+ r, "Cannot add dependency job, ignoring: %s", -+ bus_error_message(e, r)); - sd_bus_error_free(e); - } - } - -- HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_REQUISITE], i) { -+ HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_REQUISITE]) { - r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, false, false, ignore_order, e); - if (r < 0) { - if (r != -EBADR) /* job type not applicable */ -@@ -1062,7 +1052,7 @@ int transaction_add_job_and_dependencies( - } - } - -- HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_CONFLICTS], i) { -+ HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_CONFLICTS]) { - r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, true, false, ignore_order, e); - if (r < 0) { - if (r != -EBADR) /* job type not applicable */ -@@ -1072,7 +1062,7 @@ int transaction_add_job_and_dependencies( - } - } - -- HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) { -+ HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_CONFLICTED_BY]) { - r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, false, false, ignore_order, e); - if (r < 0) { - log_unit_warning(dep, -@@ -1101,7 +1091,7 @@ int transaction_add_job_and_dependencies( - ptype = type == JOB_RESTART ? JOB_TRY_RESTART : type; - - for (j = 0; j < ELEMENTSOF(propagate_deps); j++) -- HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[propagate_deps[j]], i) { -+ HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[propagate_deps[j]]) { - JobType nt; - - nt = job_type_collapse(ptype, dep); -@@ -1131,7 +1121,6 @@ fail: - } - - int transaction_add_isolate_jobs(Transaction *tr, Manager *m) { -- Iterator i; - Unit *u; - char *k; - int r; -@@ -1139,7 +1128,7 @@ int transaction_add_isolate_jobs(Transaction *tr, Manager *m) { - assert(tr); - assert(m); - -- HASHMAP_FOREACH_KEY(u, k, m->units, i) { -+ HASHMAP_FOREACH_KEY(u, k, m->units) { - - /* ignore aliases */ - if (u->id != k) -@@ -1165,7 +1154,6 @@ int transaction_add_isolate_jobs(Transaction *tr, Manager *m) { - } - - int transaction_add_triggering_jobs(Transaction *tr, Unit *u) { -- Iterator i; - void *v; - Unit *trigger; - int r; -@@ -1173,7 +1161,7 @@ int transaction_add_triggering_jobs(Transaction *tr, Unit *u) { - assert(tr); - assert(u); - -- HASHMAP_FOREACH_KEY(v, trigger, u->dependencies[UNIT_TRIGGERED_BY], i) { -+ HASHMAP_FOREACH_KEY(v, trigger, u->dependencies[UNIT_TRIGGERED_BY]) { - /* No need to stop inactive jobs */ - if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(trigger)) && !trigger->job) - continue; -diff --git a/src/core/unit.c b/src/core/unit.c -index 2c09def..c3d7d24 100644 ---- a/src/core/unit.c -+++ b/src/core/unit.c -@@ -24,10 +24,10 @@ - #include "fileio-label.h" - #include "fileio.h" - #include "format-util.h" --#include "fs-util.h" - #include "id128-util.h" - #include "io-util.h" - #include "install.h" -+#include "label.h" - #include "load-dropin.h" - #include "load-fragment.h" - #include "log.h" -@@ -209,11 +209,7 @@ static int unit_add_alias(Unit *u, char *donated_name) { - - /* Make sure that u->names is allocated. We may leave u->names - * empty if we fail later, but this is not a problem. */ -- r = set_ensure_allocated(&u->aliases, &string_hash_ops); -- if (r < 0) -- return r; -- -- r = set_put(u->aliases, donated_name); -+ r = set_ensure_put(&u->aliases, &string_hash_ops, donated_name); - if (r < 0) - return r; - assert(r > 0); -@@ -510,14 +506,13 @@ void unit_submit_to_stop_when_unneeded_queue(Unit *u) { - - static void bidi_set_free(Unit *u, Hashmap *h) { - Unit *other; -- Iterator i; - void *v; - - assert(u); - - /* Frees the hashmap and makes sure we are dropped from the inverse pointers */ - -- HASHMAP_FOREACH_KEY(v, other, h, i) { -+ HASHMAP_FOREACH_KEY(v, other, h) { - for (UnitDependency d = 0; d < _UNIT_DEPENDENCY_MAX; d++) - hashmap_remove(other->dependencies[d], u); - -@@ -614,20 +609,11 @@ static void unit_done(Unit *u) { - } - - void unit_free(Unit *u) { -- Iterator i; - char *t; - - if (!u) - return; - -- if (UNIT_ISSET(u->slice)) { -- /* A unit is being dropped from the tree, make sure our parent slice recalculates the member mask */ -- unit_invalidate_cgroup_members_masks(UNIT_DEREF(u->slice)); -- -- /* And make sure the parent is realized again, updating cgroup memberships */ -- unit_add_to_cgroup_realize_queue(UNIT_DEREF(u->slice)); -- } -- - u->transient_file = safe_fclose(u->transient_file); - - if (!MANAGER_IS_RELOADING(u->manager)) -@@ -646,7 +632,7 @@ void unit_free(Unit *u) { - - unit_free_requires_mounts_for(u); - -- SET_FOREACH(t, u->aliases, i) -+ SET_FOREACH(t, u->aliases) - hashmap_remove_value(u->manager->units, t, u); - if (u->id) - hashmap_remove_value(u->manager->units, u->id, u); -@@ -669,6 +655,11 @@ void unit_free(Unit *u) { - for (UnitDependency d = 0; d < _UNIT_DEPENDENCY_MAX; d++) - bidi_set_free(u, u->dependencies[d]); - -+ /* A unit is being dropped from the tree, make sure our family is realized properly. Do this after we -+ * detach the unit from slice tree in order to eliminate its effect on controller masks. */ -+ if (UNIT_ISSET(u->slice)) -+ unit_add_family_to_cgroup_realize_queue(UNIT_DEREF(u->slice)); -+ - if (u->on_console) - manager_unref_console(u->manager); - -@@ -822,7 +813,6 @@ static int hashmap_complete_move(Hashmap **s, Hashmap **other) { - - static int merge_names(Unit *u, Unit *other) { - char *name; -- Iterator i; - int r; - - assert(u); -@@ -841,7 +831,7 @@ static int merge_names(Unit *u, Unit *other) { - TAKE_PTR(other->id); - other->aliases = set_free_free(other->aliases); - -- SET_FOREACH(name, u->aliases, i) -+ SET_FOREACH(name, u->aliases) - assert_se(hashmap_replace(u->manager->units, name, u) == 0); - - return 0; -@@ -869,7 +859,6 @@ static int reserve_dependencies(Unit *u, Unit *other, UnitDependency d) { - } - - static void merge_dependencies(Unit *u, Unit *other, const char *other_id, UnitDependency d) { -- Iterator i; - Unit *back; - void *v; - int r; -@@ -881,7 +870,7 @@ static void merge_dependencies(Unit *u, Unit *other, const char *other_id, UnitD - assert(d < _UNIT_DEPENDENCY_MAX); - - /* Fix backwards pointers. Let's iterate through all dependent units of the other unit. */ -- HASHMAP_FOREACH_KEY(v, back, other->dependencies[d], i) -+ HASHMAP_FOREACH_KEY(v, back, other->dependencies[d]) - - /* Let's now iterate through the dependencies of that dependencies of the other units, - * looking for pointers back, and let's fix them up, to instead point to 'u'. */ -@@ -1043,8 +1032,6 @@ Unit* unit_follow_merge(Unit *u) { - } - - int unit_add_exec_dependencies(Unit *u, ExecContext *c) { -- ExecDirectoryType dt; -- char **dp; - int r; - - assert(u); -@@ -1068,10 +1055,11 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { - return r; - } - -- for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { -+ for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { - if (!u->manager->prefix[dt]) - continue; - -+ char **dp; - STRV_FOREACH(dp, c->directories[dt].paths) { - _cleanup_free_ char *p; - -@@ -1191,13 +1179,12 @@ static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependency - { UNIT_DEPENDENCY_MOUNTINFO_DEFAULT, "mountinfo-default" }, - { UNIT_DEPENDENCY_PROC_SWAP, "proc-swap" }, - }; -- size_t i; - - assert(f); - assert(kind); - assert(space); - -- for (i = 0; i < ELEMENTSOF(table); i++) { -+ for (size_t i = 0; i < ELEMENTSOF(table); i++) { - - if (mask == 0) - break; -@@ -1221,12 +1208,10 @@ static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependency - - void unit_dump(Unit *u, FILE *f, const char *prefix) { - char *t, **j; -- Iterator i; - const char *prefix2; - char timestamp[5][FORMAT_TIMESTAMP_MAX], timespan[FORMAT_TIMESPAN_MAX]; - Unit *following; - _cleanup_set_free_ Set *following_set = NULL; -- const char *n; - CGroupMask m; - int r; - -@@ -1240,7 +1225,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { - "%s-> Unit %s:\n", - prefix, u->id); - -- SET_FOREACH(t, u->aliases, i) -+ SET_FOREACH(t, u->aliases) - fprintf(f, "%s\tAlias: %s\n", prefix, t); - - fprintf(f, -@@ -1327,7 +1312,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { - if (r >= 0) { - Unit *other; - -- SET_FOREACH(other, following_set, i) -+ SET_FOREACH(other, following_set) - fprintf(f, "%s\tFollowing Set Member: %s\n", prefix, other->id); - } - -@@ -1379,7 +1364,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { - UnitDependencyInfo di; - Unit *other; - -- HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d], i) { -+ HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d]) { - bool space = false; - - fprintf(f, "%s\t%s: %s (", prefix, unit_dependency_to_string(d), other->id); -@@ -1395,7 +1380,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { - UnitDependencyInfo di; - const char *path; - -- HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for, i) { -+ HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for) { - bool space = false; - - fprintf(f, "%s\tRequiresMountsFor: %s (", prefix, path); -@@ -1433,7 +1418,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { - else if (u->load_state == UNIT_ERROR) - fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror_safe(u->load_error)); - -- for (n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track)) -+ for (const char *n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track)) - fprintf(f, "%s\tBus Ref: %s\n", prefix, n); - - if (u->job) -@@ -1542,12 +1527,11 @@ static int unit_add_slice_dependencies(Unit *u) { - static int unit_add_mount_dependencies(Unit *u) { - UnitDependencyInfo di; - const char *path; -- Iterator i; - int r; - - assert(u); - -- HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for, i) { -+ HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for) { - char prefix[strlen(path) + 1]; - - PATH_FOREACH_PREFIX_MORE(prefix, path) { -@@ -1674,18 +1658,18 @@ int unit_load(Unit *u) { - return 0; - - fail: -- /* We convert ENOEXEC errors to the UNIT_BAD_SETTING load state here. Configuration parsing code should hence -- * return ENOEXEC to ensure units are placed in this state after loading */ -+ /* We convert ENOEXEC errors to the UNIT_BAD_SETTING load state here. Configuration parsing code -+ * should hence return ENOEXEC to ensure units are placed in this state after loading. */ - - u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND : - r == -ENOEXEC ? UNIT_BAD_SETTING : - UNIT_ERROR; - u->load_error = r; - -- /* Record the last time we tried to load the unit, so that if the cache gets updated between now -- * and the next time an attempt is made to load this unit, we know we need to check again */ -+ /* Record the timestamp on the cache, so that if the cache gets updated between now and the next time -+ * an attempt is made to load this unit, we know we need to check again. */ - if (u->load_state == UNIT_NOT_FOUND) -- u->fragment_loadtime = now(CLOCK_REALTIME); -+ u->fragment_not_found_timestamp_hash = u->manager->unit_cache_timestamp_hash; - - unit_add_to_dbus_queue(u); - unit_add_to_gc_queue(u); -@@ -1810,7 +1794,6 @@ bool unit_shall_confirm_spawn(Unit *u) { - - static bool unit_verify_deps(Unit *u) { - Unit *other; -- Iterator j; - void *v; - - assert(u); -@@ -1820,7 +1803,7 @@ static bool unit_verify_deps(Unit *u) { - * processing, but do not have any effect afterwards. We don't check BindsTo= dependencies that are not used in - * conjunction with After= as for them any such check would make things entirely racy. */ - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], j) { -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO]) { - - if (!hashmap_contains(u->dependencies[UNIT_AFTER], other)) - continue; -@@ -2047,7 +2030,6 @@ bool unit_is_unneeded(Unit *u) { - UNIT_WANTED_BY, - UNIT_BOUND_BY, - }; -- size_t j; - - assert(u); - -@@ -2060,15 +2042,14 @@ bool unit_is_unneeded(Unit *u) { - if (u->job) - return false; - -- for (j = 0; j < ELEMENTSOF(deps); j++) { -+ for (size_t j = 0; j < ELEMENTSOF(deps); j++) { - Unit *other; -- Iterator i; - void *v; - - /* If a dependent unit has a job queued, is active or transitioning, or is marked for - * restart, then don't clean this one up. */ - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i) { -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]]) { - if (other->job) - return false; - -@@ -2091,18 +2072,16 @@ static void check_unneeded_dependencies(Unit *u) { - UNIT_WANTS, - UNIT_BINDS_TO, - }; -- size_t j; - - assert(u); - - /* Add all units this unit depends on to the queue that processes StopWhenUnneeded= behaviour. */ - -- for (j = 0; j < ELEMENTSOF(deps); j++) { -+ for (size_t j = 0; j < ELEMENTSOF(deps); j++) { - Unit *other; -- Iterator i; - void *v; - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]]) - unit_submit_to_stop_when_unneeded_queue(other); - } - } -@@ -2111,7 +2090,6 @@ static void unit_check_binds_to(Unit *u) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - bool stop = false; - Unit *other; -- Iterator i; - void *v; - int r; - -@@ -2123,7 +2101,7 @@ static void unit_check_binds_to(Unit *u) { - if (unit_active_state(u) != UNIT_ACTIVE) - return; - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], i) { -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO]) { - if (other->job) - continue; - -@@ -2159,54 +2137,51 @@ static void unit_check_binds_to(Unit *u) { - } - - static void retroactively_start_dependencies(Unit *u) { -- Iterator i; - Unit *other; - void *v; - - assert(u); - assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))); - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRES], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRES]) - if (!hashmap_get(u->dependencies[UNIT_AFTER], other) && - !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) - manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL, NULL); - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO]) - if (!hashmap_get(u->dependencies[UNIT_AFTER], other) && - !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) - manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL, NULL); - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_WANTS], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_WANTS]) - if (!hashmap_get(u->dependencies[UNIT_AFTER], other) && - !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) - manager_add_job(u->manager, JOB_START, other, JOB_FAIL, NULL, NULL, NULL); - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTS], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTS]) - if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) - manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL); - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTED_BY], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTED_BY]) - if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) - manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL); - } - - static void retroactively_stop_dependencies(Unit *u) { - Unit *other; -- Iterator i; - void *v; - - assert(u); - assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))); - - /* Pull down units which are bound to us recursively if enabled */ -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BOUND_BY], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BOUND_BY]) - if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) - manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL); - } - - void unit_start_on_failure(Unit *u) { - Unit *other; -- Iterator i; - void *v; - int r; - -@@ -2217,7 +2192,7 @@ void unit_start_on_failure(Unit *u) { - - log_unit_info(u, "Triggering OnFailure= dependencies."); - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_ON_FAILURE], i) { -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_ON_FAILURE]) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - - r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, NULL, &error, NULL); -@@ -2228,12 +2203,11 @@ void unit_start_on_failure(Unit *u) { - - void unit_trigger_notify(Unit *u) { - Unit *other; -- Iterator i; - void *v; - - assert(u); - -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_TRIGGERED_BY], i) -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_TRIGGERED_BY]) - if (UNIT_VTABLE(other)->trigger_notify) - UNIT_VTABLE(other)->trigger_notify(other, u); - } -@@ -2254,8 +2228,6 @@ static int unit_log_resources(Unit *u) { - size_t n_message_parts = 0, n_iovec = 0; - char* message_parts[1 + 2 + 2 + 1], *t; - nsec_t nsec = NSEC_INFINITY; -- CGroupIPAccountingMetric m; -- size_t i; - int r; - const char* const ip_fields[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = { - [CGROUP_IP_INGRESS_BYTES] = "IP_METRIC_INGRESS_BYTES", -@@ -2367,7 +2339,7 @@ static int unit_log_resources(Unit *u) { - } - } - -- for (m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) { -+ for (CGroupIPAccountingMetric m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) { - char buf[FORMAT_BYTES_MAX] = ""; - uint64_t value = UINT64_MAX; - -@@ -2470,10 +2442,10 @@ static int unit_log_resources(Unit *u) { - r = 0; - - finish: -- for (i = 0; i < n_message_parts; i++) -+ for (size_t i = 0; i < n_message_parts; i++) - free(message_parts[i]); - -- for (i = 0; i < n_iovec; i++) -+ for (size_t i = 0; i < n_iovec; i++) - free(iovec[i].iov_base); - - return r; -@@ -2801,10 +2773,10 @@ void unit_unwatch_pid(Unit *u, pid_t pid) { - /* Then, let's also drop the unit, in case it's in the array keyed by -pid */ - array = hashmap_get(u->manager->watch_pids, PID_TO_PTR(-pid)); - if (array) { -- size_t n, m = 0; -- - /* Let's iterate through the array, dropping our own entry */ -- for (n = 0; array[n]; n++) -+ -+ size_t m = 0; -+ for (size_t n = 0; array[n]; n++) - if (array[n] != u) - array[m++] = array[n]; - array[m] = NULL; -@@ -2830,7 +2802,6 @@ void unit_unwatch_all_pids(Unit *u) { - - static void unit_tidy_watch_pids(Unit *u) { - pid_t except1, except2; -- Iterator i; - void *e; - - assert(u); -@@ -2840,7 +2811,7 @@ static void unit_tidy_watch_pids(Unit *u) { - except1 = unit_main_pid(u); - except2 = unit_control_pid(u); - -- SET_FOREACH(e, u->pids, i) { -+ SET_FOREACH(e, u->pids) { - pid_t pid = PTR_TO_PID(e); - - if (pid == except1 || pid == except2) -@@ -3534,7 +3505,6 @@ static const char *const io_accounting_metric_field_last[_CGROUP_IO_ACCOUNTING_M - }; - - int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { -- CGroupIPAccountingMetric m; - int r; - - assert(u); -@@ -3606,7 +3576,7 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { - - bus_track_serialize(u->bus_track, f, "ref"); - -- for (m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) { -+ for (CGroupIPAccountingMetric m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) { - uint64_t v; - - r = unit_get_ip_accounting(u, m, &v); -@@ -4447,7 +4417,6 @@ static int user_from_unit_name(Unit *u, char **ret) { - int unit_patch_contexts(Unit *u) { - CGroupContext *cc; - ExecContext *ec; -- unsigned i; - int r; - - assert(u); -@@ -4459,7 +4428,7 @@ int unit_patch_contexts(Unit *u) { - ec = unit_get_exec_context(u); - if (ec) { - /* This only copies in the ones that need memory */ -- for (i = 0; i < _RLIMIT_MAX; i++) -+ for (unsigned i = 0; i < _RLIMIT_MAX; i++) - if (u->manager->rlimit[i] && !ec->rlimit[i]) { - ec->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1); - if (!ec->rlimit[i]) -@@ -4527,11 +4496,11 @@ int unit_patch_contexts(Unit *u) { - cc->device_policy == CGROUP_DEVICE_POLICY_AUTO) - cc->device_policy = CGROUP_DEVICE_POLICY_CLOSED; - -- if (ec->root_image && -+ if ((ec->root_image || !LIST_IS_EMPTY(ec->mount_images)) && - (cc->device_policy != CGROUP_DEVICE_POLICY_AUTO || cc->device_allow)) { - const char *p; - -- /* When RootImage= is specified, the following devices are touched. */ -+ /* When RootImage= or MountImages= is specified, the following devices are touched. */ - FOREACH_STRING(p, "/dev/loop-control", "/dev/mapper/control") { - r = cgroup_add_device_allow(cc, p, "rw"); - if (r < 0) -@@ -5114,7 +5083,6 @@ int unit_setup_exec_runtime(Unit *u) { - ExecRuntime **rt; - size_t offset; - Unit *other; -- Iterator i; - void *v; - int r; - -@@ -5127,7 +5095,7 @@ int unit_setup_exec_runtime(Unit *u) { - return 0; - - /* Try to get it from somebody else */ -- HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_JOINS_NAMESPACE_OF], i) { -+ HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_JOINS_NAMESPACE_OF]) { - r = exec_runtime_acquire(u->manager, NULL, other->id, false, rt); - if (r == 1) - return 1; -@@ -5432,6 +5400,8 @@ int unit_set_exec_params(Unit *u, ExecParameters *p) { - p->cgroup_path = u->cgroup_path; - SET_FLAG(p->flags, EXEC_CGROUP_DELEGATE, unit_cgroup_delegate(u)); - -+ p->received_credentials = u->manager->received_credentials; -+ - return 0; - } - -@@ -5528,11 +5498,10 @@ void unit_remove_dependencies(Unit *u, UnitDependencyMask mask) { - do { - UnitDependencyInfo di; - Unit *other; -- Iterator i; - - done = true; - -- HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d], i) { -+ HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d]) { - if ((di.origin_mask & ~mask) == di.origin_mask) - continue; - di.origin_mask &= ~mask; -@@ -5604,7 +5573,7 @@ static int unit_export_invocation_id(Unit *u) { - if (r < 0) - return log_unit_debug_errno(u, r, "Failed to get invocation path: %m"); - -- r = symlink_atomic(u->invocation_id_string, p); -+ r = symlink_atomic_label(u->invocation_id_string, p); - if (r < 0) - return log_unit_debug_errno(u, r, "Failed to create invocation ID symlink %s: %m", p); - -@@ -5647,7 +5616,6 @@ static int unit_export_log_extra_fields(Unit *u, const ExecContext *c) { - char *pattern; - le64_t *sizes; - ssize_t n; -- size_t i; - int r; - - if (u->exported_log_extra_fields) -@@ -5659,7 +5627,7 @@ static int unit_export_log_extra_fields(Unit *u, const ExecContext *c) { - sizes = newa(le64_t, c->n_log_extra_fields); - iovec = newa(struct iovec, c->n_log_extra_fields * 2); - -- for (i = 0; i < c->n_log_extra_fields; i++) { -+ for (size_t i = 0; i < c->n_log_extra_fields; i++) { - sizes[i] = htole64(c->log_extra_fields[i].iov_len); - - iovec[i*2] = IOVEC_MAKE(sizes + i, sizeof(le64_t)); -@@ -6126,10 +6094,15 @@ int unit_test_trigger_loaded(Unit *u) { - return 0; - } - --void unit_destroy_runtime_directory(Unit *u, const ExecContext *context) { -+void unit_destroy_runtime_data(Unit *u, const ExecContext *context) { -+ assert(u); -+ assert(context); -+ - if (context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO || - (context->runtime_directory_preserve_mode == EXEC_PRESERVE_RESTART && !unit_will_restart(u))) - exec_context_destroy_runtime_directory(context, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]); -+ -+ exec_context_destroy_credentials(context, u->manager->prefix[EXEC_DIRECTORY_RUNTIME], u->id); - } - - int unit_clean(Unit *u, ExecCleanMask mask) { -diff --git a/src/core/unit.h b/src/core/unit.h -index d5e4c65..35873d5 100644 ---- a/src/core/unit.h -+++ b/src/core/unit.h -@@ -49,6 +49,10 @@ static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) { - return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED); - } - -+static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) { -+ return t >= 0 && t < _UNIT_LOAD_STATE_MAX && t != UNIT_STUB && t != UNIT_MERGED; -+} -+ - /* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We - * use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be - * created as a result of multiple "reasons", hence the bitmask. */ -@@ -136,7 +140,7 @@ typedef struct Unit { - char *source_path; /* if converted, the source file */ - char **dropin_paths; - -- usec_t fragment_loadtime; -+ usec_t fragment_not_found_timestamp_hash; - usec_t fragment_mtime; - usec_t source_mtime; - usec_t dropin_mtime; -@@ -880,7 +884,7 @@ int unit_failure_action_exit_status(Unit *u); - - int unit_test_trigger_loaded(Unit *u); - --void unit_destroy_runtime_directory(Unit *u, const ExecContext *context); -+void unit_destroy_runtime_data(Unit *u, const ExecContext *context); - int unit_clean(Unit *u, ExecCleanMask mask); - int unit_can_clean(Unit *u, ExecCleanMask *ret_mask); - -@@ -896,7 +900,7 @@ int unit_thaw_vtable_common(Unit *u); - - /* Macros which append UNIT= or USER_UNIT= to the message */ - --#define log_unit_full(unit, level, error, ...) \ -+#define log_unit_full_errno(unit, level, error, ...) \ - ({ \ - const Unit *_u = (unit); \ - (log_get_max_level() < LOG_PRI(level)) ? -ERRNO_VALUE(error) : \ -@@ -904,17 +908,19 @@ int unit_thaw_vtable_common(Unit *u); - log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ - }) - --#define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__) --#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, 0, ##__VA_ARGS__) --#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, 0, ##__VA_ARGS__) --#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, 0, ##__VA_ARGS__) --#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, 0, ##__VA_ARGS__) -- --#define log_unit_debug_errno(unit, error, ...) log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__) --#define log_unit_info_errno(unit, error, ...) log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__) --#define log_unit_notice_errno(unit, error, ...) log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__) --#define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__) --#define log_unit_error_errno(unit, error, ...) log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__) -+#define log_unit_full(unit, level, ...) (void) log_unit_full_errno(unit, level, 0, __VA_ARGS__) -+ -+#define log_unit_debug(unit, ...) log_unit_full_errno(unit, LOG_DEBUG, 0, __VA_ARGS__) -+#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, __VA_ARGS__) -+#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, __VA_ARGS__) -+#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, __VA_ARGS__) -+#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, __VA_ARGS__) -+ -+#define log_unit_debug_errno(unit, error, ...) log_unit_full_errno(unit, LOG_DEBUG, error, __VA_ARGS__) -+#define log_unit_info_errno(unit, error, ...) log_unit_full_errno(unit, LOG_INFO, error, __VA_ARGS__) -+#define log_unit_notice_errno(unit, error, ...) log_unit_full_errno(unit, LOG_NOTICE, error, __VA_ARGS__) -+#define log_unit_warning_errno(unit, error, ...) log_unit_full_errno(unit, LOG_WARNING, error, __VA_ARGS__) -+#define log_unit_error_errno(unit, error, ...) log_unit_full_errno(unit, LOG_ERR, error, __VA_ARGS__) - - #define LOG_UNIT_MESSAGE(unit, fmt, ...) "MESSAGE=%s: " fmt, (unit)->id, ##__VA_ARGS__ - #define LOG_UNIT_ID(unit) (unit)->manager->unit_log_format_string, (unit)->id -diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c -index 8b052da..88739ed 100644 ---- a/src/coredump/coredump.c -+++ b/src/coredump/coredump.c -@@ -77,7 +77,7 @@ enum { - META_ARGV_UID, /* %u: as seen in the initial user namespace */ - META_ARGV_GID, /* %g: as seen in the initial user namespace */ - META_ARGV_SIGNAL, /* %s: number of signal causing dump */ -- META_ARGV_TIMESTAMP, /* %t: time of dump, expressed as seconds since the Epoch */ -+ META_ARGV_TIMESTAMP, /* %t: time of dump, expressed as seconds since the Epoch (we expand this to µs granularity) */ - META_ARGV_RLIMIT, /* %c: core file size soft resource limit */ - META_ARGV_HOSTNAME, /* %h: hostname */ - _META_ARGV_MAX, -@@ -186,9 +186,9 @@ static int fix_acl(int fd, uid_t uid) { - return 0; - - /* Make sure normal users can read (but not write or delete) their own coredumps */ -- r = add_acls_for_user(fd, uid); -+ r = fd_add_uid_acl_permission(fd, uid, ACL_READ); - if (r < 0) -- return log_error_errno(r, "Failed to adjust ACL of coredump: %m"); -+ return log_error_errno(r, "Failed to adjust ACL of the coredump: %m"); - #endif - - return 0; -@@ -311,7 +311,7 @@ static int make_filename(const Context *context, char **ret) { - return -ENOMEM; - - if (asprintf(ret, -- "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000", -+ "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s", - c, - u, - SD_ID128_FORMAT_VAL(boot), -@@ -607,7 +607,7 @@ static int get_process_ns(pid_t pid, const char *namespace, ino_t *ns) { - static int get_mount_namespace_leader(pid_t pid, pid_t *container_pid) { - pid_t cpid = pid, ppid = 0; - ino_t proc_mntns; -- int r = 0; -+ int r; - - r = get_process_ns(pid, "mnt", &proc_mntns); - if (r < 0) -@@ -1016,8 +1016,11 @@ static int send_iovec(const struct iovec_wrapper *iovw, int input_fd) { - return 0; - } - --static int gather_pid_metadata_from_argv(struct iovec_wrapper *iovw, Context *context, -- int argc, char **argv) { -+static int gather_pid_metadata_from_argv( -+ struct iovec_wrapper *iovw, -+ Context *context, -+ int argc, char **argv) { -+ - _cleanup_free_ char *free_timestamp = NULL; - int i, r, signo; - char *t; -@@ -1035,6 +1038,7 @@ static int gather_pid_metadata_from_argv(struct iovec_wrapper *iovw, Context *co - t = argv[i]; - - switch (i) { -+ - case META_ARGV_TIMESTAMP: - /* The journal fields contain the timestamp padded with six - * zeroes, so that the kernel-supplied 1s granularity timestamps -@@ -1044,12 +1048,14 @@ static int gather_pid_metadata_from_argv(struct iovec_wrapper *iovw, Context *co - if (!t) - return log_oom(); - break; -+ - case META_ARGV_SIGNAL: - /* For signal, record its pretty name too */ - if (safe_atoi(argv[i], &signo) >= 0 && SIGNAL_VALID(signo)) - (void) iovw_put_string_field(iovw, "COREDUMP_SIGNAL_NAME=SIG", - signal_to_string(signo)); - break; -+ - default: - break; - } -diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c -index b93fbb8..dec4d20 100644 ---- a/src/cryptsetup/cryptsetup-generator.c -+++ b/src/cryptsetup/cryptsetup-generator.c -@@ -181,6 +181,47 @@ static int generate_keydev_mount( - return 0; - } - -+static int generate_keydev_umount(const char *name, -+ const char *keydev_mount, -+ char **ret_umount_unit) { -+ _cleanup_fclose_ FILE *f = NULL; -+ _cleanup_free_ char *u = NULL, *name_escaped = NULL, *mount = NULL; -+ int r; -+ -+ assert(name); -+ assert(ret_umount_unit); -+ -+ name_escaped = cescape(name); -+ if (!name_escaped) -+ return -ENOMEM; -+ -+ u = strjoin("keydev-", name_escaped, "-umount.service"); -+ if (!u) -+ return -ENOMEM; -+ -+ r = unit_name_from_path(keydev_mount, ".mount", &mount); -+ if (r < 0) -+ return r; -+ -+ r = generator_open_unit_file(arg_dest, NULL, u, &f); -+ if (r < 0) -+ return r; -+ -+ fprintf(f, -+ "[Unit]\n" -+ "DefaultDependencies=no\n" -+ "After=%s\n\n" -+ "[Service]\n" -+ "ExecStart=-" UMOUNT_PATH " %s\n\n", mount, keydev_mount); -+ -+ r = fflush_and_check(f); -+ if (r < 0) -+ return r; -+ -+ *ret_umount_unit = TAKE_PTR(u); -+ return 0; -+} -+ - static int print_dependencies(FILE *f, const char* device_path) { - int r; - -@@ -314,12 +355,16 @@ static int create_disk( - fprintf(f, "Conflicts=umount.target\n"); - - if (keydev) { -- _cleanup_free_ char *unit = NULL; -+ _cleanup_free_ char *unit = NULL, *umount_unit = NULL; - - r = generate_keydev_mount(name, keydev, keyfile_timeout_value, keyfile_can_timeout > 0, &unit, &keydev_mount); - if (r < 0) - return log_error_errno(r, "Failed to generate keydev mount unit: %m"); - -+ r = generate_keydev_umount(name, keydev_mount, &umount_unit); -+ if (r < 0) -+ return log_error_errno(r, "Failed to generate keydev umount unit: %m"); -+ - password_buffer = path_join(keydev_mount, password); - if (!password_buffer) - return log_oom(); -@@ -331,6 +376,15 @@ static int create_disk( - fprintf(f, "Wants=%s\n", unit); - else - fprintf(f, "Requires=%s\n", unit); -+ -+ if (umount_unit) { -+ fprintf(f, -+ "Wants=%s\n" -+ "Before=%s\n", -+ umount_unit, -+ umount_unit -+ ); -+ } - } - - if (!nofail) -@@ -394,11 +448,6 @@ static int create_disk( - "ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs swap '/dev/mapper/%s'\n", - name_escaped); - -- if (keydev) -- fprintf(f, -- "ExecStartPost=-" UMOUNT_PATH " %s\n\n", -- keydev_mount); -- - r = fflush_and_check(f); - if (r < 0) - return log_error_errno(r, "Failed to write unit file %s: %m", n); -@@ -644,10 +693,9 @@ static int add_crypttab_devices(void) { - - static int add_proc_cmdline_devices(void) { - int r; -- Iterator i; - crypto_device *d; - -- HASHMAP_FOREACH(d, arg_disks, i) { -+ HASHMAP_FOREACH(d, arg_disks) { - _cleanup_free_ char *device = NULL; - - if (!d->create) -diff --git a/src/cryptsetup/cryptsetup-util.c b/src/cryptsetup/cryptsetup-keyfile.c -similarity index 99% -rename from src/cryptsetup/cryptsetup-util.c -rename to src/cryptsetup/cryptsetup-keyfile.c -index 8ae70a5..ebf4cb1 100644 ---- a/src/cryptsetup/cryptsetup-util.c -+++ b/src/cryptsetup/cryptsetup-keyfile.c -@@ -2,7 +2,7 @@ - - #include - --#include "cryptsetup-util.h" -+#include "cryptsetup-keyfile.h" - #include "fd-util.h" - #include "format-util.h" - #include "memory-util.h" -diff --git a/src/cryptsetup/cryptsetup-util.h b/src/cryptsetup/cryptsetup-keyfile.h -similarity index 100% -rename from src/cryptsetup/cryptsetup-util.h -rename to src/cryptsetup/cryptsetup-keyfile.h -diff --git a/src/cryptsetup/cryptsetup-pkcs11.c b/src/cryptsetup/cryptsetup-pkcs11.c -index 642a1b7..bbc0122 100644 ---- a/src/cryptsetup/cryptsetup-pkcs11.c -+++ b/src/cryptsetup/cryptsetup-pkcs11.c -@@ -10,7 +10,7 @@ - #include "alloc-util.h" - #include "ask-password-api.h" - #include "cryptsetup-pkcs11.h" --#include "cryptsetup-util.h" -+#include "cryptsetup-keyfile.h" - #include "escape.h" - #include "fd-util.h" - #include "format-util.h" -diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c -index 6d3f842..7d0571f 100644 ---- a/src/cryptsetup/cryptsetup.c -+++ b/src/cryptsetup/cryptsetup.c -@@ -11,7 +11,7 @@ - - #include "alloc-util.h" - #include "ask-password-api.h" --#include "crypt-util.h" -+#include "cryptsetup-keyfile.h" - #include "cryptsetup-pkcs11.h" - #include "cryptsetup-util.h" - #include "device-util.h" -@@ -288,19 +288,19 @@ static int parse_one_option(const char *option) { - } - - static int parse_options(const char *options) { -- const char *word, *state; -- size_t l; -- int r; -- - assert(options); - -- FOREACH_WORD_SEPARATOR(word, l, options, ",", state) { -- _cleanup_free_ char *o; -+ for (;;) { -+ _cleanup_free_ char *word = NULL; -+ int r; -+ -+ r = extract_first_word(&options, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to parse options: %m"); -+ if (r == 0) -+ break; - -- o = strndup(word, l); -- if (!o) -- return -ENOMEM; -- r = parse_one_option(o); -+ r = parse_one_option(word); - if (r < 0) - return r; - } -@@ -839,10 +839,7 @@ static int run(int argc, char *argv[]) { - - log_setup_service(); - -- crypt_set_log_callback(NULL, cryptsetup_log_glue, NULL); -- if (DEBUG_LOGGING) -- /* libcryptsetup won't even consider debug messages by default */ -- crypt_set_debug_level(CRYPT_DEBUG_ALL); -+ cryptsetup_enable_logging(cd); - - umask(0022); - -@@ -906,7 +903,7 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return log_error_errno(r, "crypt_init() failed: %m"); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - status = crypt_status(cd, argv[2]); - if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) { -@@ -1032,7 +1029,7 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return log_error_errno(r, "crypt_init_by_name() failed: %m"); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - r = crypt_deactivate(cd, argv[2]); - if (r < 0) -diff --git a/src/delta/delta.c b/src/delta/delta.c -index 29e5120..a88eed0 100644 ---- a/src/delta/delta.c -+++ b/src/delta/delta.c -@@ -401,13 +401,9 @@ static int should_skip_path(const char *prefix, const char *suffix) { - - static int process_suffix(const char *suffix, const char *onlyprefix) { - const char *p; -- char *f; -- OrderedHashmap *top, *bottom, *drops; -- OrderedHashmap *h; -- char *key; -- int r = 0, k; -- Iterator i, j; -- int n_found = 0; -+ char *f, *key; -+ OrderedHashmap *top, *bottom, *drops, *h; -+ int r = 0, k, n_found = 0; - bool dropins; - - assert(suffix); -@@ -441,7 +437,7 @@ static int process_suffix(const char *suffix, const char *onlyprefix) { - r = k; - } - -- ORDERED_HASHMAP_FOREACH_KEY(f, key, top, i) { -+ ORDERED_HASHMAP_FOREACH_KEY(f, key, top) { - char *o; - - o = ordered_hashmap_get(bottom, key); -@@ -461,7 +457,7 @@ static int process_suffix(const char *suffix, const char *onlyprefix) { - - h = ordered_hashmap_get(drops, key); - if (h) -- ORDERED_HASHMAP_FOREACH(o, h, j) -+ ORDERED_HASHMAP_FOREACH(o, h) - if (!onlyprefix || startswith(o, onlyprefix)) - n_found += notify_override_extended(f, o); - } -@@ -470,7 +466,7 @@ finish: - ordered_hashmap_free_free(top); - ordered_hashmap_free_free(bottom); - -- ORDERED_HASHMAP_FOREACH_KEY(h, key, drops, i) { -+ ORDERED_HASHMAP_FOREACH_KEY(h, key, drops) { - ordered_hashmap_free_free(ordered_hashmap_remove(drops, key)); - ordered_hashmap_remove(drops, key); - free(key); -@@ -545,28 +541,33 @@ static int help(void) { - } - - static int parse_flags(const char *flag_str, int flags) { -- const char *word, *state; -- size_t l; -+ for (;;) { -+ _cleanup_free_ char *word = NULL; -+ int r; - -- FOREACH_WORD_SEPARATOR(word, l, flag_str, ",", state) { -- if (strneq("masked", word, l)) -+ r = extract_first_word(&flag_str, &word, ",", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return flags; -+ -+ if (streq(word, "masked")) - flags |= SHOW_MASKED; -- else if (strneq ("equivalent", word, l)) -+ else if (streq(word, "equivalent")) - flags |= SHOW_EQUIVALENT; -- else if (strneq("redirected", word, l)) -+ else if (streq(word, "redirected")) - flags |= SHOW_REDIRECTED; -- else if (strneq("overridden", word, l)) -+ else if (streq(word, "overridden")) - flags |= SHOW_OVERRIDDEN; -- else if (strneq("unchanged", word, l)) -+ else if (streq(word, "unchanged")) - flags |= SHOW_UNCHANGED; -- else if (strneq("extended", word, l)) -+ else if (streq(word, "extended")) - flags |= SHOW_EXTENDED; -- else if (strneq("default", word, l)) -+ else if (streq(word, "default")) - flags |= SHOW_DEFAULTS; - else - return -EINVAL; - } -- return flags; - } - - static int parse_argv(int argc, char *argv[]) { -diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c -index 66ac638..239bddc 100644 ---- a/src/dissect/dissect.c -+++ b/src/dissect/dissect.c -@@ -4,26 +4,44 @@ - #include - #include - #include -+#include -+#include - - #include "architecture.h" -+#include "copy.h" - #include "dissect-image.h" -+#include "fd-util.h" -+#include "format-table.h" -+#include "format-util.h" -+#include "fs-util.h" - #include "hexdecoct.h" - #include "log.h" - #include "loop-util.h" - #include "main-func.h" -+#include "mkdir.h" -+#include "mount-util.h" -+#include "namespace-util.h" - #include "parse-util.h" - #include "path-util.h" -+#include "pretty-print.h" -+#include "stat-util.h" - #include "string-util.h" - #include "strv.h" -+#include "terminal-util.h" -+#include "tmpfile-util.h" - #include "user-util.h" - #include "util.h" - - static enum { - ACTION_DISSECT, - ACTION_MOUNT, -+ ACTION_COPY_FROM, -+ ACTION_COPY_TO, - } arg_action = ACTION_DISSECT; - static const char *arg_image = NULL; - static const char *arg_path = NULL; -+static const char *arg_source = NULL; -+static const char *arg_target = NULL; - static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK; - static void *arg_root_hash = NULL; - static char *arg_verity_data = NULL; -@@ -31,21 +49,31 @@ static size_t arg_root_hash_size = 0; - static char *arg_root_hash_sig_path = NULL; - static void *arg_root_hash_sig = NULL; - static size_t arg_root_hash_sig_size = 0; -+static bool arg_json = false; -+static JsonFormatFlags arg_json_format_flags = 0; - - STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep); - STATIC_DESTRUCTOR_REGISTER(arg_verity_data, freep); - STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig_path, freep); - STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig, freep); - --static void help(void) { -- printf("%s [OPTIONS...] IMAGE\n" -- "%s [OPTIONS...] --mount IMAGE PATH\n" -- "Dissect a file system OS image.\n\n" -- " -h --help Show this help\n" -- " --version Show package version\n" -- " -m --mount Mount the image to the specified directory\n" -+static int help(void) { -+ _cleanup_free_ char *link = NULL; -+ int r; -+ -+ r = terminal_urlify_man("systemd-dissect", "1", &link); -+ if (r < 0) -+ return log_oom(); -+ -+ printf("%1$s [OPTIONS...] IMAGE\n" -+ "%1$s [OPTIONS...] --mount IMAGE PATH\n" -+ "%1$s [OPTIONS...] --copy-from IMAGE PATH [TARGET]\n" -+ "%1$s [OPTIONS...] --copy-to IMAGE [SOURCE] PATH\n\n" -+ "%5$sDissect a file system OS image.%6$s\n\n" -+ "%3$sOptions:%4$s\n" - " -r --read-only Mount read-only\n" - " --fsck=BOOL Run fsck before mounting\n" -+ " --mkdir Make mount directory before mounting, if missing\n" - " --discard=MODE Choose 'discard' mode (disabled, loop, all, crypto)\n" - " --root-hash=HASH Specify root hash for verity\n" - " --root-hash-sig=SIG Specify pkcs7 signature of root hash for verity\n" -@@ -53,9 +81,23 @@ static void help(void) { - " or as an ASCII base64 encoded string prefixed by\n" - " 'base64:'\n" - " --verity-data=PATH Specify data file with hash tree for verity if it is\n" -- " not embedded in IMAGE\n", -- program_invocation_short_name, -- program_invocation_short_name); -+ " not embedded in IMAGE\n" -+ " --json=pretty|short|off\n" -+ " Generate JSON output\n" -+ "\n%3$sCommands:%4$s\n" -+ " -h --help Show this help\n" -+ " --version Show package version\n" -+ " -m --mount Mount the image to the specified directory\n" -+ " -M Shortcut for --mount --mkdir\n" -+ " -x --copy-from Copy files from image to host\n" -+ " -a --copy-to Copy files from host to image\n" -+ "\nSee the %2$s for details.\n" -+ , program_invocation_short_name -+ , link -+ , ansi_underline(), ansi_normal() -+ , ansi_highlight(), ansi_normal()); -+ -+ return 0; - } - - static int parse_argv(int argc, char *argv[]) { -@@ -67,6 +109,8 @@ static int parse_argv(int argc, char *argv[]) { - ARG_FSCK, - ARG_VERITY_DATA, - ARG_ROOT_HASH_SIG, -+ ARG_MKDIR, -+ ARG_JSON, - }; - - static const struct option options[] = { -@@ -79,6 +123,10 @@ static int parse_argv(int argc, char *argv[]) { - { "fsck", required_argument, NULL, ARG_FSCK }, - { "verity-data", required_argument, NULL, ARG_VERITY_DATA }, - { "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG }, -+ { "mkdir", no_argument, NULL, ARG_MKDIR }, -+ { "copy-from", no_argument, NULL, 'x' }, -+ { "copy-to", no_argument, NULL, 'a' }, -+ { "json", required_argument, NULL, ARG_JSON }, - {} - }; - -@@ -87,13 +135,12 @@ static int parse_argv(int argc, char *argv[]) { - assert(argc >= 0); - assert(argv); - -- while ((c = getopt_long(argc, argv, "hmr", options, NULL)) >= 0) { -+ while ((c = getopt_long(argc, argv, "hmrMxa", options, NULL)) >= 0) { - - switch (c) { - - case 'h': -- help(); -- return 0; -+ return help(); - - case ARG_VERSION: - return version(); -@@ -102,6 +149,25 @@ static int parse_argv(int argc, char *argv[]) { - arg_action = ACTION_MOUNT; - break; - -+ case ARG_MKDIR: -+ arg_flags |= DISSECT_IMAGE_MKDIR; -+ break; -+ -+ case 'M': -+ /* Shortcut combination of the above two */ -+ arg_action = ACTION_MOUNT; -+ arg_flags |= DISSECT_IMAGE_MKDIR; -+ break; -+ -+ case 'x': -+ arg_action = ACTION_COPY_FROM; -+ arg_flags |= DISSECT_IMAGE_READ_ONLY; -+ break; -+ -+ case 'a': -+ arg_action = ACTION_COPY_TO; -+ break; -+ - case 'r': - arg_flags |= DISSECT_IMAGE_READ_ONLY; - break; -@@ -117,7 +183,13 @@ static int parse_argv(int argc, char *argv[]) { - flags = DISSECT_IMAGE_DISCARD_ON_LOOP | DISSECT_IMAGE_DISCARD; - else if (streq(optarg, "crypt")) - flags = DISSECT_IMAGE_DISCARD_ANY; -- else -+ else if (streq(optarg, "list")) { -+ puts("disabled\n" -+ "all\n" -+ "crypt\n" -+ "loop"); -+ return 0; -+ } else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Unknown --discard= parameter: %s", - optarg); -@@ -184,6 +256,26 @@ static int parse_argv(int argc, char *argv[]) { - SET_FLAG(arg_flags, DISSECT_IMAGE_FSCK, r); - break; - -+ case ARG_JSON: -+ if (streq(optarg, "pretty")) { -+ arg_json = true; -+ arg_json_format_flags = JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR_AUTO; -+ } else if (streq(optarg, "short")) { -+ arg_json = true; -+ arg_json_format_flags = JSON_FORMAT_NEWLINE; -+ } else if (streq(optarg, "off")) { -+ arg_json = false; -+ arg_json_format_flags = 0; -+ } else if (streq(optarg, "help")) { -+ puts("pretty\n" -+ "short\n" -+ "off"); -+ return 0; -+ } else -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown argument to --json=: %s", optarg); -+ -+ break; -+ - case '?': - return -EINVAL; - -@@ -198,7 +290,7 @@ static int parse_argv(int argc, char *argv[]) { - case ACTION_DISSECT: - if (optind + 1 != argc) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -- "Expected a file path as only argument."); -+ "Expected an image file path as only argument."); - - arg_image = argv[optind]; - arg_flags |= DISSECT_IMAGE_READ_ONLY; -@@ -207,87 +299,102 @@ static int parse_argv(int argc, char *argv[]) { - case ACTION_MOUNT: - if (optind + 2 != argc) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -- "Expected a file path and mount point path as only arguments."); -+ "Expected an image file path and mount point path as only arguments."); - - arg_image = argv[optind]; - arg_path = argv[optind + 1]; - break; - -- default: -- assert_not_reached("Unknown action."); -- } -- -- return 1; --} -- --static int run(int argc, char *argv[]) { -- _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; -- _cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL; -- _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; -- int r; -- -- log_parse_environment(); -- log_open(); -+ case ACTION_COPY_FROM: -+ if (argc < optind + 2 || argc > optind + 3) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "Expected an image file path, a source path and an optional destination path as only arguments."); - -- r = parse_argv(argc, argv); -- if (r <= 0) -- return r; -+ arg_image = argv[optind]; -+ arg_source = argv[optind + 1]; -+ arg_target = argc > optind + 2 ? argv[optind + 2] : "-" /* this means stdout */ ; - -- r = loop_device_make_by_path(arg_image, (arg_flags & DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR, LO_FLAGS_PARTSCAN, &d); -- if (r < 0) -- return log_error_errno(r, "Failed to set up loopback device: %m"); -+ arg_flags |= DISSECT_IMAGE_READ_ONLY; -+ break; - -- r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size, -- arg_verity_data ? NULL : &arg_verity_data, -- arg_root_hash_sig_path || arg_root_hash_sig ? NULL : &arg_root_hash_sig_path); -- if (r < 0) -- return log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image); -- arg_flags |= arg_verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0; -+ case ACTION_COPY_TO: -+ if (argc < optind + 2 || argc > optind + 3) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "Expected an image file path, an optional source path and a destination path as only arguments."); - -- r = dissect_image_and_warn(d->fd, arg_image, arg_root_hash, arg_root_hash_size, arg_verity_data, arg_flags, &m); -- if (r < 0) -- return r; -+ arg_image = argv[optind]; - -- switch (arg_action) { -+ if (argc > optind + 2) { -+ arg_source = argv[optind + 1]; -+ arg_target = argv[optind + 2]; -+ } else { -+ arg_source = "-"; /* this means stdin */ -+ arg_target = argv[optind + 1]; -+ } - -- case ACTION_DISSECT: { -- unsigned i; -+ break; - -- for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { -- DissectedPartition *p = m->partitions + i; -+ default: -+ assert_not_reached("Unknown action."); -+ } - -- if (!p->found) -- continue; -+ return 1; -+} - -- printf("Found %s '%s' partition", -- p->rw ? "writable" : "read-only", -- partition_designator_to_string(i)); -+static int strv_pair_to_json(char **l, JsonVariant **ret) { -+ _cleanup_strv_free_ char **jl = NULL; -+ char **a, **b; - -- if (!sd_id128_is_null(p->uuid)) -- printf(" (UUID " SD_ID128_FORMAT_STR ")", SD_ID128_FORMAT_VAL(p->uuid)); -+ STRV_FOREACH_PAIR(a, b, l) { -+ char *j; - -- if (p->fstype) -- printf(" of type %s", p->fstype); -+ j = strjoin(*a, "=", *b); -+ if (!j) -+ return log_oom(); - -- if (p->architecture != _ARCHITECTURE_INVALID) -- printf(" for %s", architecture_to_string(p->architecture)); -+ if (strv_consume(&jl, j) < 0) -+ return log_oom(); -+ } - -- if (dissected_image_can_do_verity(m, i)) -- printf(" %s verity", dissected_image_has_verity(m, i) ? "with" : "without"); -+ return json_variant_new_array_strv(ret, jl); -+} - -- if (p->partno >= 0) -- printf(" on partition #%i", p->partno); -+static int action_dissect(DissectedImage *m, LoopDevice *d) { -+ _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; -+ _cleanup_(table_unrefp) Table *t = NULL; -+ uint64_t size = UINT64_MAX; -+ int r; - -- if (p->node) -- printf(" (%s)", p->node); -+ assert(m); -+ assert(d); - -- putchar('\n'); -- } -+ if (!arg_json) -+ printf(" Name: %s\n", basename(arg_image)); - -- r = dissected_image_acquire_metadata(m); -- if (r < 0) -- return log_error_errno(r, "Failed to acquire image metadata: %m"); -+ if (ioctl(d->fd, BLKGETSIZE64, &size) < 0) -+ log_debug_errno(errno, "Failed to query size of loopback device: %m"); -+ else if (!arg_json) { -+ char s[FORMAT_BYTES_MAX]; -+ printf(" Size: %s\n", format_bytes(s, sizeof(s), size)); -+ } - -+ if (!arg_json) -+ putc('\n', stdout); -+ -+ r = dissected_image_acquire_metadata(m); -+ if (r == -ENXIO) -+ return log_error_errno(r, "No root partition discovered."); -+ if (r == -EMEDIUMTYPE) -+ return log_error_errno(r, "Not a valid OS image, no os-release file included."); -+ if (r == -EUCLEAN) -+ return log_error_errno(r, "File system check of image failed."); -+ if (r == -EUNATCH) -+ log_warning_errno(r, "OS image is encrypted, proceeding without showing OS image metadata."); -+ else if (r == -EBUSY) -+ log_warning_errno(r, "OS image is currently in use, proceeding without showing OS image metadata."); -+ else if (r < 0) -+ return log_error_errno(r, "Failed to acquire image metadata: %m"); -+ else if (!arg_json) { - if (m->hostname) - printf(" Hostname: %s\n", m->hostname); - -@@ -311,35 +418,381 @@ static int run(int argc, char *argv[]) { - p == m->os_release ? "OS Release:" : " ", - *p, *q); - } -+ } - -- break; -+ if (arg_json) { -+ _cleanup_(json_variant_unrefp) JsonVariant *mi = NULL, *osr = NULL; -+ -+ if (!strv_isempty(m->machine_info)) { -+ r = strv_pair_to_json(m->machine_info, &mi); -+ if (r < 0) -+ return log_oom(); -+ } -+ -+ if (!strv_isempty(m->os_release)) { -+ r = strv_pair_to_json(m->os_release, &osr); -+ if (r < 0) -+ return log_oom(); -+ } -+ -+ r = json_build(&v, JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR("name", JSON_BUILD_STRING(basename(arg_image))), -+ JSON_BUILD_PAIR("size", JSON_BUILD_INTEGER(size)), -+ JSON_BUILD_PAIR_CONDITION(m->hostname, "hostname", JSON_BUILD_STRING(m->hostname)), -+ JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(m->machine_id), "machineId", JSON_BUILD_ID128(m->machine_id)), -+ JSON_BUILD_PAIR_CONDITION(mi, "machineInfo", JSON_BUILD_VARIANT(mi)), -+ JSON_BUILD_PAIR_CONDITION(osr, "osRelease", JSON_BUILD_VARIANT(osr)))); -+ if (r < 0) -+ return log_oom(); - } - -- case ACTION_MOUNT: -- r = dissected_image_decrypt_interactively(m, NULL, arg_root_hash, arg_root_hash_size, arg_verity_data, arg_root_hash_sig_path, arg_root_hash_sig, arg_root_hash_sig_size, arg_flags, &di); -+ if (!arg_json) -+ putc('\n', stdout); -+ -+ t = table_new("rw", "designator", "partition uuid", "fstype", "architecture", "verity", "node", "partno"); -+ if (!t) -+ return log_oom(); -+ -+ (void) table_set_empty_string(t, "-"); -+ (void) table_set_align_percent(t, table_get_cell(t, 0, 7), 100); -+ -+ for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { -+ DissectedPartition *p = m->partitions + i; -+ -+ if (!p->found) -+ continue; -+ -+ r = table_add_many( -+ t, -+ TABLE_STRING, p->rw ? "rw" : "ro", -+ TABLE_STRING, partition_designator_to_string(i)); - if (r < 0) -- return r; -+ return table_log_add_error(r); - -- r = dissected_image_mount(m, arg_path, UID_INVALID, arg_flags); -- if (r == -EUCLEAN) -- return log_error_errno(r, "File system check on image failed: %m"); -+ if (sd_id128_is_null(p->uuid)) -+ r = table_add_cell(t, NULL, TABLE_EMPTY, NULL); -+ else -+ r = table_add_cell(t, NULL, TABLE_UUID, &p->uuid); -+ if (r < 0) -+ return table_log_add_error(r); -+ -+ r = table_add_many( -+ t, -+ TABLE_STRING, p->fstype, -+ TABLE_STRING, architecture_to_string(p->architecture)); -+ if (r < 0) -+ return table_log_add_error(r); -+ -+ if (arg_verity_data) -+ r = table_add_cell(t, NULL, TABLE_STRING, "external"); -+ else if (dissected_image_can_do_verity(m, i)) -+ r = table_add_cell(t, NULL, TABLE_STRING, yes_no(dissected_image_has_verity(m, i))); -+ else -+ r = table_add_cell(t, NULL, TABLE_EMPTY, NULL); - if (r < 0) -- return log_error_errno(r, "Failed to mount image: %m"); -+ return table_log_add_error(r); - -- if (di) { -- r = decrypted_image_relinquish(di); -+ if (p->partno < 0) /* no partition table, naked file system */ { -+ r = table_add_cell(t, NULL, TABLE_STRING, arg_image); - if (r < 0) -- return log_error_errno(r, "Failed to relinquish DM devices: %m"); -+ return table_log_add_error(r); -+ -+ r = table_add_cell(t, NULL, TABLE_EMPTY, NULL); -+ } else { -+ r = table_add_cell(t, NULL, TABLE_STRING, p->node); -+ if (r < 0) -+ return table_log_add_error(r); -+ -+ r = table_add_cell(t, NULL, TABLE_INT, &p->partno); - } -+ if (r < 0) -+ return table_log_add_error(r); -+ } -+ -+ if (arg_json) { -+ _cleanup_(json_variant_unrefp) JsonVariant *jt = NULL; -+ -+ r = table_to_json(t, &jt); -+ if (r < 0) -+ return log_error_errno(r, "Failed to convert table to JSON: %m"); -+ -+ r = json_variant_set_field(&v, "mounts", jt); -+ if (r < 0) -+ return log_oom(); -+ -+ json_variant_dump(v, arg_json_format_flags, stdout, NULL); -+ } else { -+ r = table_print(t, stdout); -+ if (r < 0) -+ return log_error_errno(r, "Failed to dump table: %m"); -+ } -+ -+ return 0; -+} -+ -+static int action_mount(DissectedImage *m, LoopDevice *d) { -+ _cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL; -+ int r; -+ -+ assert(m); -+ assert(d); - -- loop_device_relinquish(d); -+ r = dissected_image_decrypt_interactively( -+ m, NULL, -+ arg_root_hash, arg_root_hash_size, -+ arg_verity_data, -+ arg_root_hash_sig_path, arg_root_hash_sig, arg_root_hash_sig_size, -+ arg_flags, -+ &di); -+ if (r < 0) -+ return r; -+ -+ r = dissected_image_mount_and_warn(m, arg_path, UID_INVALID, arg_flags); -+ if (r < 0) -+ return r; -+ -+ if (di) { -+ r = decrypted_image_relinquish(di); -+ if (r < 0) -+ return log_error_errno(r, "Failed to relinquish DM devices: %m"); -+ } -+ -+ loop_device_relinquish(d); -+ return 0; -+} -+ -+static int action_copy(DissectedImage *m, LoopDevice *d) { -+ _cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL; -+ _cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL; -+ _cleanup_(rmdir_and_freep) char *created_dir = NULL; -+ _cleanup_free_ char *temp = NULL; -+ int r; -+ -+ assert(m); -+ assert(d); -+ -+ r = dissected_image_decrypt_interactively( -+ m, NULL, -+ arg_root_hash, arg_root_hash_size, -+ arg_verity_data, -+ arg_root_hash_sig_path, arg_root_hash_sig, arg_root_hash_sig_size, -+ arg_flags, -+ &di); -+ if (r < 0) -+ return r; -+ -+ r = detach_mount_namespace(); -+ if (r < 0) -+ return log_error_errno(r, "Failed to detach mount namespace: %m"); -+ -+ r = tempfn_random_child(NULL, program_invocation_short_name, &temp); -+ if (r < 0) -+ return log_error_errno(r, "Failed to generate temporary mount directory: %m"); -+ -+ r = mkdir_p(temp, 0700); -+ if (r < 0) -+ return log_error_errno(r, "Failed to create mount point: %m"); -+ -+ created_dir = TAKE_PTR(temp); -+ -+ r = dissected_image_mount_and_warn(m, created_dir, UID_INVALID, arg_flags); -+ if (r < 0) -+ return r; -+ -+ mounted_dir = TAKE_PTR(created_dir); -+ -+ if (di) { -+ r = decrypted_image_relinquish(di); -+ if (r < 0) -+ return log_error_errno(r, "Failed to relinquish DM devices: %m"); -+ } -+ -+ loop_device_relinquish(d); -+ -+ if (arg_action == ACTION_COPY_FROM) { -+ _cleanup_close_ int source_fd = -1, target_fd = -1; -+ -+ source_fd = chase_symlinks_and_open(arg_source, mounted_dir, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL); -+ if (source_fd < 0) -+ return log_error_errno(source_fd, "Failed to open source path '%s' in image '%s': %m", arg_source, arg_image); -+ -+ /* Copying to stdout? */ -+ if (streq(arg_target, "-")) { -+ r = copy_bytes(source_fd, STDOUT_FILENO, (uint64_t) -1, COPY_REFLINK); -+ if (r < 0) -+ return log_error_errno(r, "Failed to copy bytes from %s in mage '%s' to stdout: %m", arg_source, arg_image); -+ -+ /* When we copy to stdou we don't copy any attributes (i.e. no access mode, no ownership, no xattr, no times) */ -+ return 0; -+ } -+ -+ /* Try to copy as directory? */ -+ r = copy_directory_fd(source_fd, arg_target, COPY_REFLINK|COPY_MERGE_EMPTY|COPY_SIGINT|COPY_HARDLINKS); -+ if (r >= 0) -+ return 0; -+ if (r != -ENOTDIR) -+ return log_error_errno(r, "Failed to copy %s in image '%s' to '%s': %m", arg_source, arg_image, arg_target); -+ -+ r = fd_verify_regular(source_fd); -+ if (r == -EISDIR) -+ return log_error_errno(r, "Target '%s' exists already and is not a directory.", arg_target); -+ if (r < 0) -+ return log_error_errno(r, "Source path %s in image '%s' is neither regular file nor directory, refusing: %m", arg_source, arg_image); -+ -+ /* Nah, it's a plain file! */ -+ target_fd = open(arg_target, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600); -+ if (target_fd < 0) -+ return log_error_errno(errno, "Failed to create regular file at target path '%s': %m", arg_target); -+ -+ r = copy_bytes(source_fd, target_fd, (uint64_t) -1, COPY_REFLINK); -+ if (r < 0) -+ return log_error_errno(r, "Failed to copy bytes from %s in mage '%s' to '%s': %m", arg_source, arg_image, arg_target); -+ -+ (void) copy_xattr(source_fd, target_fd); -+ (void) copy_access(source_fd, target_fd); -+ (void) copy_times(source_fd, target_fd, 0); -+ -+ /* When this is a regular file we don't copy ownership! */ -+ -+ } else { -+ _cleanup_close_ int source_fd = -1, target_fd = -1; -+ _cleanup_close_ int dfd = -1; -+ _cleanup_free_ char *dn = NULL; -+ -+ assert(arg_action == ACTION_COPY_TO); -+ -+ dn = dirname_malloc(arg_target); -+ if (!dn) -+ return log_oom(); -+ -+ r = chase_symlinks(dn, mounted_dir, CHASE_PREFIX_ROOT|CHASE_WARN, NULL, &dfd); -+ if (r < 0) -+ return log_error_errno(r, "Failed to open '%s': %m", dn); -+ -+ /* Are we reading from stdin? */ -+ if (streq(arg_source, "-")) { -+ target_fd = openat(dfd, basename(arg_target), O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_EXCL, 0644); -+ if (target_fd < 0) -+ return log_error_errno(errno, "Failed to open target file '%s': %m", arg_target); -+ -+ r = copy_bytes(STDIN_FILENO, target_fd, (uint64_t) -1, COPY_REFLINK); -+ if (r < 0) -+ return log_error_errno(r, "Failed to copy bytes from stdin to '%s' in image '%s': %m", arg_target, arg_image); -+ -+ /* When we copy from stdin we don't copy any attributes (i.e. no access mode, no ownership, no xattr, no times) */ -+ return 0; -+ } -+ -+ source_fd = open(arg_source, O_RDONLY|O_CLOEXEC|O_NOCTTY); -+ if (source_fd < 0) -+ return log_error_errno(source_fd, "Failed to open source path '%s': %m", arg_source); -+ -+ r = fd_verify_regular(source_fd); -+ if (r < 0) { -+ if (r != -EISDIR) -+ return log_error_errno(r, "Source '%s' is neither regular file nor directory: %m", arg_source); -+ -+ /* We are looking at a directory. */ -+ -+ target_fd = openat(dfd, basename(arg_target), O_RDONLY|O_DIRECTORY|O_CLOEXEC); -+ if (target_fd < 0) { -+ if (errno != ENOENT) -+ return log_error_errno(errno, "Failed to open destination '%s': %m", arg_target); -+ -+ r = copy_tree_at(source_fd, ".", dfd, basename(arg_target), UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS); -+ } else -+ r = copy_tree_at(source_fd, ".", target_fd, ".", UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS); -+ if (r < 0) -+ return log_error_errno(r, "Failed to copy '%s' to '%s' in image '%s': %m", arg_source, arg_target, arg_image); -+ -+ return 0; -+ } -+ -+ /* We area looking at a regular file */ -+ target_fd = openat(dfd, basename(arg_target), O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_EXCL, 0600); -+ if (target_fd < 0) -+ return log_error_errno(errno, "Failed to open target file '%s': %m", arg_target); -+ -+ r = copy_bytes(source_fd, target_fd, (uint64_t) -1, COPY_REFLINK); -+ if (r < 0) -+ return log_error_errno(r, "Failed to copy bytes from '%s' to '%s' in image '%s': %m", arg_source, arg_target, arg_image); -+ -+ (void) copy_xattr(source_fd, target_fd); -+ (void) copy_access(source_fd, target_fd); -+ (void) copy_times(source_fd, target_fd, 0); -+ -+ /* When this is a regular file we don't copy ownership! */ -+ } -+ -+ return 0; -+} -+ -+static int run(int argc, char *argv[]) { -+ _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; -+ _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; -+ int r; -+ -+ log_parse_environment(); -+ log_open(); -+ -+ r = parse_argv(argc, argv); -+ if (r <= 0) -+ return r; -+ -+ r = verity_metadata_load( -+ arg_image, NULL, -+ arg_root_hash ? NULL : &arg_root_hash, -+ &arg_root_hash_size, -+ arg_verity_data ? NULL : &arg_verity_data, -+ arg_root_hash_sig_path || arg_root_hash_sig ? NULL : &arg_root_hash_sig_path); -+ if (r < 0) -+ return log_error_errno(r, "Failed to read verity artifacts for %s: %m", arg_image); -+ -+ r = loop_device_make_by_path( -+ arg_image, -+ (arg_flags & DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR, -+ arg_verity_data ? 0 : LO_FLAGS_PARTSCAN, -+ &d); -+ if (r < 0) -+ return log_error_errno(r, "Failed to set up loopback device: %m"); -+ -+ if (arg_verity_data) -+ arg_flags |= DISSECT_IMAGE_NO_PARTITION_TABLE; /* We only support Verity per file system, -+ * hence if there's external Verity data -+ * available we turn off partition table -+ * support */ -+ r = dissect_image_and_warn( -+ d->fd, -+ arg_image, -+ arg_root_hash, -+ arg_root_hash_size, -+ arg_verity_data, -+ NULL, -+ arg_flags, -+ &m); -+ if (r < 0) -+ return r; -+ -+ switch (arg_action) { -+ -+ case ACTION_DISSECT: -+ r = action_dissect(m, d); -+ break; -+ -+ case ACTION_MOUNT: -+ r = action_mount(m, d); -+ break; -+ -+ case ACTION_COPY_FROM: -+ case ACTION_COPY_TO: -+ r = action_copy(m, d); - break; - - default: - assert_not_reached("Unknown action."); - } - -- return 0; -+ return r; - } - - DEFINE_MAIN_FUNCTION(run); -diff --git a/src/escape/escape.c b/src/escape/escape.c -index 0c543a9..3f3dc0a 100644 ---- a/src/escape/escape.c -+++ b/src/escape/escape.c -@@ -211,14 +211,16 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return log_error_errno(r, "Failed to extract instance: %m"); - if (isempty(name)) -- return log_error("Unit %s is missing the instance name.", *i); -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "Unit %s is missing the instance name.", *i); - - r = unit_name_template(*i, &template); - if (r < 0) - return log_error_errno(r, "Failed to extract template: %m"); - if (arg_template && !streq(arg_template, template)) -- return log_error("Unit %s template %s does not match specified template %s.", -- *i, template, arg_template); -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "Unit %s template %s does not match specified template %s.", -+ *i, template, arg_template); - } else { - name = strdup(*i); - if (!name) -diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c -index a3f4425..f8499a6 100644 ---- a/src/firstboot/firstboot.c -+++ b/src/firstboot/firstboot.c -@@ -19,17 +19,16 @@ - #include "kbd-util.h" - #include "libcrypt-util.h" - #include "locale-util.h" --#include "loop-util.h" - #include "main-func.h" - #include "memory-util.h" - #include "mkdir.h" - #include "mount-util.h" --#include "namespace-util.h" - #include "os-util.h" - #include "parse-util.h" - #include "path-util.h" - #include "pretty-print.h" - #include "proc-cmdline.h" -+#include "pwquality-util.h" - #include "random-util.h" - #include "string-util.h" - #include "strv.h" -@@ -94,7 +93,7 @@ static bool press_any_key(void) { - static void print_welcome(void) { - _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL; - static bool done = false; -- const char *pn; -+ const char *pn, *ac; - int r; - - if (!arg_welcome) -@@ -113,9 +112,10 @@ static void print_welcome(void) { - "Failed to read os-release file, ignoring: %m"); - - pn = isempty(pretty_name) ? "Linux" : pretty_name; -+ ac = isempty(ansi_color) ? "0" : ansi_color; - - if (colors_enabled()) -- printf("\nWelcome to your new installation of \x1B[%sm%s\x1B[0m!\n", ansi_color, pn); -+ printf("\nWelcome to your new installation of \x1B[%sm%s\x1B[0m!\n", ac, pn); - else - printf("\nWelcome to your new installation of %s!\n", pn); - -@@ -570,8 +570,11 @@ static int prompt_root_password(void) { - msg1 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter a new root password (empty to skip):"); - msg2 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter new root password again:"); - -+ suggest_passwords(); -+ - for (;;) { - _cleanup_strv_free_erase_ char **a = NULL, **b = NULL; -+ _cleanup_free_ char *error = NULL; - - r = ask_password_tty(-1, msg1, NULL, 0, 0, NULL, &a); - if (r < 0) -@@ -585,6 +588,12 @@ static int prompt_root_password(void) { - break; - } - -+ r = quality_check_password(*a, "root", &error); -+ if (r < 0) -+ return log_error_errno(r, "Failed to check quality of password: %m"); -+ if (r == 0) -+ log_warning("Password is weak, accepting anyway: %s", error); -+ - r = ask_password_tty(-1, msg2, NULL, 0, 0, NULL, &b); - if (r < 0) - return log_error_errno(r, "Failed to query root password: %m"); -@@ -806,6 +815,10 @@ static int process_root_args(void) { - * files. */ - if ((laccess(etc_passwd, F_OK) >= 0 || laccess(etc_shadow, F_OK) >= 0) && !arg_force) - return 0; -+ /* Don't create/modify passwd and shadow if not asked */ -+ if (!(arg_root_password || arg_prompt_root_password || arg_copy_root_password || arg_delete_root_password || -+ arg_root_shell || arg_prompt_root_shell || arg_copy_root_shell)) -+ return 0; - - (void) mkdir_parents(etc_passwd, 0755); - -@@ -907,75 +920,6 @@ static int process_kernel_cmdline(void) { - return 0; - } - --static int setup_image(char **ret_mount_dir, LoopDevice **ret_loop_device, DecryptedImage **ret_decrypted_image) { -- DissectImageFlags f = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK; -- _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; -- _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL; -- _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL; -- _cleanup_(rmdir_and_freep) char *mount_dir = NULL; -- _cleanup_free_ char *temp = NULL; -- int r; -- -- if (!arg_image) { -- *ret_mount_dir = NULL; -- *ret_decrypted_image = NULL; -- *ret_loop_device = NULL; -- return 0; -- } -- -- assert(!arg_root); -- -- r = tempfn_random_child(NULL, "firstboot", &temp); -- if (r < 0) -- return log_error_errno(r, "Failed to generate temporary mount directory: %m"); -- -- r = loop_device_make_by_path(arg_image, O_RDWR, LO_FLAGS_PARTSCAN, &d); -- if (r < 0) -- return log_error_errno(r, "Failed to set up loopback device: %m"); -- -- r = dissect_image_and_warn(d->fd, arg_image, NULL, 0, NULL, f, &dissected_image); -- if (r < 0) -- return r; -- -- r = dissected_image_decrypt_interactively(dissected_image, NULL, NULL, 0, NULL, NULL, NULL, 0, f, &decrypted_image); -- if (r < 0) -- return r; -- -- r = detach_mount_namespace(); -- if (r < 0) -- return log_error_errno(r, "Failed to detach mount namespace: %m"); -- -- mount_dir = strdup(temp); -- if (!mount_dir) -- return log_oom(); -- -- r = mkdir_p(mount_dir, 0700); -- if (r < 0) { -- mount_dir = mfree(mount_dir); -- return log_error_errno(r, "Failed to create mount point: %m"); -- } -- -- r = dissected_image_mount(dissected_image, mount_dir, UID_INVALID, f); -- if (r < 0) -- return log_error_errno(r, "Failed to mount image: %m"); -- -- if (decrypted_image) { -- r = decrypted_image_relinquish(decrypted_image); -- if (r < 0) -- return log_error_errno(r, "Failed to relinquish DM devices: %m"); -- } -- -- loop_device_relinquish(d); -- -- arg_root = TAKE_PTR(temp); -- -- *ret_mount_dir = TAKE_PTR(mount_dir); -- *ret_decrypted_image = TAKE_PTR(decrypted_image); -- *ret_loop_device = TAKE_PTR(d); -- -- return 1; --} -- - static int help(void) { - _cleanup_free_ char *link = NULL; - int r; -@@ -1353,9 +1297,22 @@ static int run(int argc, char *argv[]) { - return 0; /* disabled */ - } - -- r = setup_image(&unlink_dir, &loop_device, &decrypted_image); -- if (r < 0) -- return r; -+ if (arg_image) { -+ assert(!arg_root); -+ -+ r = mount_image_privately_interactively( -+ arg_image, -+ DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK, -+ &unlink_dir, -+ &loop_device, -+ &decrypted_image); -+ if (r < 0) -+ return r; -+ -+ arg_root = strdup(unlink_dir); -+ if (!arg_root) -+ return log_oom(); -+ } - - r = process_locale(); - if (r < 0) -diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c -index 91581ae..6c560d5 100644 ---- a/src/fstab-generator/fstab-generator.c -+++ b/src/fstab-generator/fstab-generator.c -@@ -425,7 +425,7 @@ static int add_mount( - * the systemd mount-timeout doesn't interfere. - * By placing these options first, they can be over-ridden by - * settings in /etc/fstab. */ -- opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,", opts, ",fg"); -+ opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,nofail,", opts, ",fg"); - SET_FLAG(flags, NOFAIL, true); - } - -diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c -index be38612..04dcacf 100644 ---- a/src/getty-generator/getty-generator.c -+++ b/src/getty-generator/getty-generator.c -@@ -99,89 +99,85 @@ static int verify_tty(const char *name) { - return 0; - } - --static int run(const char *dest, const char *dest_early, const char *dest_late) { -- _cleanup_free_ char *active = NULL; -- const char *j; -+static int run_container(void) { -+ _cleanup_free_ char *container_ttys = NULL; - int r; - -- assert_se(arg_dest = dest); -+ log_debug("Automatically adding console shell."); - -- if (detect_container() > 0) { -- _cleanup_free_ char *container_ttys = NULL; -+ r = add_symlink("console-getty.service", "console-getty.service"); -+ if (r < 0) -+ return r; - -- log_debug("Automatically adding console shell."); -+ /* When $container_ttys is set for PID 1, spawn gettys on all ptys named therein. -+ * Note that despite the variable name we only support ptys here. */ - -- r = add_symlink("console-getty.service", "console-getty.service"); -- if (r < 0) -- return r; -+ (void) getenv_for_pid(1, "container_ttys", &container_ttys); - -- /* When $container_ttys is set for PID 1, spawn -- * gettys on all ptys named therein. Note that despite -- * the variable name we only support ptys here. */ -+ for (const char *p = container_ttys;;) { -+ _cleanup_free_ char *word = NULL; - -- r = getenv_for_pid(1, "container_ttys", &container_ttys); -- if (r > 0) { -- const char *word, *state; -- size_t l; -+ r = extract_first_word(&p, &word, NULL, 0); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse $container_ttys: %m"); -+ if (r == 0) -+ return 0; - -- FOREACH_WORD(word, l, container_ttys, state) { -- const char *t; -- char tty[l + 1]; -+ const char *tty = word; - -- memcpy(tty, word, l); -- tty[l] = 0; -+ /* First strip off /dev/ if it is specified */ -+ tty = path_startswith(tty, "/dev/") ?: tty; - -- /* First strip off /dev/ if it is specified */ -- t = path_startswith(tty, "/dev/"); -- if (!t) -- t = tty; -+ /* Then, make sure it's actually a pty */ -+ tty = path_startswith(tty, "pts/"); -+ if (!tty) -+ continue; - -- /* Then, make sure it's actually a pty */ -- t = path_startswith(t, "pts/"); -- if (!t) -- continue; -+ r = add_container_getty(tty); -+ if (r < 0) -+ return r; -+ } -+} - -- r = add_container_getty(t); -- if (r < 0) -- return r; -- } -- } -+static int run(const char *dest, const char *dest_early, const char *dest_late) { -+ int r; - -- /* Don't add any further magic if we are in a container */ -- return 0; -- } -+ assert_se(arg_dest = dest); - -- if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) { -- const char *word, *state; -- size_t l; -+ if (detect_container() > 0) -+ /* Add console shell and look at $container_ttys, but don't do add any -+ * further magic if we are in a container. */ -+ return run_container(); - -- /* Automatically add in a serial getty on all active -- * kernel consoles */ -- FOREACH_WORD(word, l, active, state) { -- _cleanup_free_ char *tty = NULL; -+ /* Automatically add in a serial getty on all active kernel consoles */ -+ _cleanup_free_ char *active = NULL; -+ (void) read_one_line_file("/sys/class/tty/console/active", &active); -+ for (const char *p = active;;) { -+ _cleanup_free_ char *tty = NULL; - -- tty = strndup(word, l); -- if (!tty) -- return log_oom(); -+ r = extract_first_word(&p, &tty, NULL, 0); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse /sys/class/tty/console/active: %m"); -+ if (r == 0) -+ break; - -- /* We assume that gettys on virtual terminals are -- * started via manual configuration and do this magic -- * only for non-VC terminals. */ -+ /* We assume that gettys on virtual terminals are started via manual configuration and do -+ * this magic only for non-VC terminals. */ - -- if (isempty(tty) || tty_is_vc(tty)) -- continue; -+ if (isempty(tty) || tty_is_vc(tty)) -+ continue; - -- if (verify_tty(tty) < 0) -- continue; -+ if (verify_tty(tty) < 0) -+ continue; - -- r = add_serial_getty(tty); -- if (r < 0) -- return r; -- } -+ r = add_serial_getty(tty); -+ if (r < 0) -+ return r; - } - - /* Automatically add in a serial getty on the first - * virtualizer console */ -+ const char *j; - FOREACH_STRING(j, - "hvc0", - "xvc0", -diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c -index a9478b9..16086c8 100644 ---- a/src/gpt-auto-generator/gpt-auto-generator.c -+++ b/src/gpt-auto-generator/gpt-auto-generator.c -@@ -665,7 +665,7 @@ static int enumerate_partitions(dev_t devnum) { - if (r <= 0) - return r; - -- r = dissect_image(fd, NULL, 0, NULL, DISSECT_IMAGE_GPT_ONLY|DISSECT_IMAGE_NO_UDEV, &m); -+ r = dissect_image(fd, NULL, 0, NULL, NULL, DISSECT_IMAGE_GPT_ONLY|DISSECT_IMAGE_NO_UDEV, &m); - if (r == -ENOPKG) { - log_debug_errno(r, "No suitable partition table found, ignoring."); - return 0; -@@ -729,10 +729,14 @@ static int add_mounts(void) { - int r; - - r = get_block_device_harder("/", &devno); -+ if (r == -EUCLEAN) -+ return btrfs_log_dev_root(LOG_ERR, r, "root file system"); - if (r < 0) - return log_error_errno(r, "Failed to determine block device of root file system: %m"); -- if (r == 0) { -+ if (r == 0) { /* Not backed by block device */ - r = get_block_device_harder("/usr", &devno); -+ if (r == -EUCLEAN) -+ return btrfs_log_dev_root(LOG_ERR, r, "/usr"); - if (r < 0) - return log_error_errno(r, "Failed to determine block device of /usr file system: %m"); - if (r == 0) { -diff --git a/src/home/homectl-fido2.c b/src/home/homectl-fido2.c -index b7b2c1a..0d087c7 100644 ---- a/src/home/homectl-fido2.c -+++ b/src/home/homectl-fido2.c -@@ -534,6 +534,7 @@ finish: - fido_dev_info_free(&di, di_size); - return r; - #else -- return log_error_errno(EOPNOTSUPP, "FIDO2 tokens not supported on this build."); -+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), -+ "FIDO2 tokens not supported on this build."); - #endif - } -diff --git a/src/home/homectl-pkcs11.c b/src/home/homectl-pkcs11.c -index f4253ed..3507841 100644 ---- a/src/home/homectl-pkcs11.c -+++ b/src/home/homectl-pkcs11.c -@@ -475,6 +475,7 @@ int find_pkcs11_token_auto(char **ret) { - - return 0; - #else -- return log_error_errno(EOPNOTSUPP, "PKCS#11 tokens not supported on this build."); -+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), -+ "PKCS#11 tokens not supported on this build."); - #endif - } -diff --git a/src/home/homectl-recovery-key.c b/src/home/homectl-recovery-key.c -new file mode 100644 -index 0000000..9d7f345 ---- /dev/null -+++ b/src/home/homectl-recovery-key.c -@@ -0,0 +1,253 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#if HAVE_QRENCODE -+#include -+#include "qrcode-util.h" -+#endif -+ -+#include "dlfcn-util.h" -+#include "errno-util.h" -+#include "homectl-recovery-key.h" -+#include "libcrypt-util.h" -+#include "locale-util.h" -+#include "memory-util.h" -+#include "modhex.h" -+#include "random-util.h" -+#include "strv.h" -+#include "terminal-util.h" -+ -+static int make_recovery_key(char **ret) { -+ _cleanup_(erase_and_freep) char *formatted = NULL; -+ _cleanup_(erase_and_freep) uint8_t *key = NULL; -+ int r; -+ -+ assert(ret); -+ -+ key = new(uint8_t, MODHEX_RAW_LENGTH); -+ if (!key) -+ return log_oom(); -+ -+ r = genuine_random_bytes(key, MODHEX_RAW_LENGTH, RANDOM_BLOCK); -+ if (r < 0) -+ return log_error_errno(r, "Failed to gather entropy for recovery key: %m"); -+ -+ /* Let's now format it as 64 modhex chars, and after each 8 chars insert a dash */ -+ formatted = new(char, MODHEX_FORMATTED_LENGTH); -+ if (!formatted) -+ return log_oom(); -+ -+ for (size_t i = 0, j = 0; i < MODHEX_RAW_LENGTH; i++) { -+ formatted[j++] = modhex_alphabet[key[i] >> 4]; -+ formatted[j++] = modhex_alphabet[key[i] & 0xF]; -+ -+ if (i % 4 == 3) -+ formatted[j++] = '-'; -+ } -+ -+ formatted[MODHEX_FORMATTED_LENGTH-1] = 0; -+ -+ *ret = TAKE_PTR(formatted); -+ return 0; -+} -+ -+static int add_privileged(JsonVariant **v, const char *hashed) { -+ _cleanup_(json_variant_unrefp) JsonVariant *e = NULL, *w = NULL, *l = NULL; -+ int r; -+ -+ assert(v); -+ assert(hashed); -+ -+ r = json_build(&e, JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR("type", JSON_BUILD_STRING("modhex64")), -+ JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRING(hashed)))); -+ if (r < 0) -+ return log_error_errno(r, "Failed to build recover key JSON object: %m"); -+ -+ json_variant_sensitive(e); -+ -+ w = json_variant_ref(json_variant_by_key(*v, "privileged")); -+ l = json_variant_ref(json_variant_by_key(w, "recoveryKey")); -+ -+ r = json_variant_append_array(&l, e); -+ if (r < 0) -+ return log_error_errno(r, "Failed append recovery key: %m"); -+ -+ r = json_variant_set_field(&w, "recoveryKey", l); -+ if (r < 0) -+ return log_error_errno(r, "Failed to set recovery key array: %m"); -+ -+ r = json_variant_set_field(v, "privileged", w); -+ if (r < 0) -+ return log_error_errno(r, "Failed to update privileged field: %m"); -+ -+ return 0; -+} -+ -+static int add_public(JsonVariant **v) { -+ _cleanup_strv_free_ char **types = NULL; -+ int r; -+ -+ assert(v); -+ -+ r = json_variant_strv(json_variant_by_key(*v, "recoveryKeyType"), &types); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse recovery key type list: %m"); -+ -+ r = strv_extend(&types, "modhex64"); -+ if (r < 0) -+ return log_oom(); -+ -+ r = json_variant_set_field_strv(v, "recoveryKeyType", types); -+ if (r < 0) -+ return log_error_errno(r, "Failed to update recovery key types: %m"); -+ -+ return 0; -+} -+ -+static int add_secret(JsonVariant **v, const char *password) { -+ _cleanup_(json_variant_unrefp) JsonVariant *w = NULL, *l = NULL; -+ _cleanup_(strv_free_erasep) char **passwords = NULL; -+ int r; -+ -+ assert(v); -+ assert(password); -+ -+ w = json_variant_ref(json_variant_by_key(*v, "secret")); -+ l = json_variant_ref(json_variant_by_key(w, "password")); -+ -+ r = json_variant_strv(l, &passwords); -+ if (r < 0) -+ return log_error_errno(r, "Failed to convert password array: %m"); -+ -+ r = strv_extend(&passwords, password); -+ if (r < 0) -+ return log_oom(); -+ -+ r = json_variant_new_array_strv(&l, passwords); -+ if (r < 0) -+ return log_error_errno(r, "Failed to allocate new password array JSON: %m"); -+ -+ json_variant_sensitive(l); -+ -+ r = json_variant_set_field(&w, "password", l); -+ if (r < 0) -+ return log_error_errno(r, "Failed to update password field: %m"); -+ -+ r = json_variant_set_field(v, "secret", w); -+ if (r < 0) -+ return log_error_errno(r, "Failed to update secret object: %m"); -+ -+ return 0; -+} -+ -+static int print_qr_code(const char *secret) { -+#if HAVE_QRENCODE -+ QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); -+ void (*sym_QRcode_free)(QRcode *qrcode); -+ _cleanup_(dlclosep) void *dl = NULL; -+ QRcode* qr; -+ int r; -+ -+ /* If this is not an UTF-8 system or ANSI colors aren't supported/disabled don't print any QR -+ * codes */ -+ if (!is_locale_utf8() || !colors_enabled()) -+ return -EOPNOTSUPP; -+ -+ dl = dlopen("libqrencode.so.4", RTLD_LAZY); -+ if (!dl) -+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), -+ "QRCODE support is not installed: %s", dlerror()); -+ -+ r = dlsym_many_and_warn( -+ dl, -+ LOG_DEBUG, -+ &sym_QRcode_encodeString, "QRcode_encodeString", -+ &sym_QRcode_free, "QRcode_free", -+ NULL); -+ if (r < 0) -+ return r; -+ -+ qr = sym_QRcode_encodeString(secret, 0, QR_ECLEVEL_L, QR_MODE_8, 0); -+ if (!qr) -+ return -ENOMEM; -+ -+ fprintf(stderr, "\nYou may optionally scan the recovery key off screen:\n\n"); -+ -+ write_qrcode(stderr, qr); -+ -+ fputc('\n', stderr); -+ -+ sym_QRcode_free(qr); -+#endif -+ return 0; -+} -+ -+int identity_add_recovery_key(JsonVariant **v) { -+ _cleanup_(erase_and_freep) char *unix_salt = NULL, *password = NULL; -+ struct crypt_data cd = {}; -+ char *k; -+ int r; -+ -+ assert(v); -+ -+ /* First, let's generate a secret key */ -+ r = make_recovery_key(&password); -+ if (r < 0) -+ return r; -+ -+ /* Let's UNIX hash it */ -+ r = make_salt(&unix_salt); -+ if (r < 0) -+ return log_error_errno(r, "Failed to generate salt: %m"); -+ -+ errno = 0; -+ k = crypt_r(password, unix_salt, &cd); -+ if (!k) -+ return log_error_errno(errno_or_else(EINVAL), "Failed to UNIX hash secret key: %m"); -+ -+ /* Let's now add the "privileged" version of the recovery key */ -+ r = add_privileged(v, k); -+ if (r < 0) -+ return r; -+ -+ /* Let's then add the public information about the recovery key */ -+ r = add_public(v); -+ if (r < 0) -+ return r; -+ -+ /* Finally, let's add the new key to the secret part, too */ -+ r = add_secret(v, password); -+ if (r < 0) -+ return r; -+ -+ /* We output the key itself with a trailing newline to stdout and the decoration around it to stderr -+ * instead. */ -+ -+ fflush(stdout); -+ fprintf(stderr, -+ "A secret recovery key has been generated for this account:\n\n" -+ " %s%s%s", -+ emoji_enabled() ? special_glyph(SPECIAL_GLYPH_LOCK_AND_KEY) : "", -+ emoji_enabled() ? " " : "", -+ ansi_highlight()); -+ fflush(stderr); -+ -+ fputs(password, stdout); -+ fflush(stdout); -+ -+ fputs(ansi_normal(), stderr); -+ fflush(stderr); -+ -+ fputc('\n', stdout); -+ fflush(stdout); -+ -+ fputs("\nPlease save this secret recovery key at a secure location. It may be used to\n" -+ "regain access to the account if the other configured access credentials have\n" -+ "been lost or forgotten. The recovery key may be entered in place of a password\n" -+ "whenever authentication is requested.\n", stderr); -+ fflush(stderr); -+ -+ print_qr_code(password); -+ -+ return 0; -+} -diff --git a/src/home/homectl-recovery-key.h b/src/home/homectl-recovery-key.h -new file mode 100644 -index 0000000..489d35f ---- /dev/null -+++ b/src/home/homectl-recovery-key.h -@@ -0,0 +1,6 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#include "json.h" -+ -+int identity_add_recovery_key(JsonVariant **v); -diff --git a/src/home/homectl.c b/src/home/homectl.c -index 33e2627..b83fa83 100644 ---- a/src/home/homectl.c -+++ b/src/home/homectl.c -@@ -17,6 +17,7 @@ - #include "home-util.h" - #include "homectl-fido2.h" - #include "homectl-pkcs11.h" -+#include "homectl-recovery-key.h" - #include "locale-util.h" - #include "main-func.h" - #include "memory-util.h" -@@ -30,6 +31,7 @@ - #include "rlimit-util.h" - #include "spawn-polkit-agent.h" - #include "terminal-util.h" -+#include "user-record-pwquality.h" - #include "user-record-show.h" - #include "user-record-util.h" - #include "user-record.h" -@@ -52,6 +54,7 @@ static uint64_t arg_disk_size = UINT64_MAX; - static uint64_t arg_disk_size_relative = UINT64_MAX; - static char **arg_pkcs11_token_uri = NULL; - static char **arg_fido2_device = NULL; -+static bool arg_recovery_key = false; - static bool arg_json = false; - static JsonFormatFlags arg_json_format_flags = 0; - static bool arg_and_resize = false; -@@ -937,6 +940,12 @@ static int acquire_new_home_record(UserRecord **ret) { - return r; - } - -+ if (arg_recovery_key) { -+ r = identity_add_recovery_key(&v); -+ if (r < 0) -+ return r; -+ } -+ - r = update_last_change(&v, true, false); - if (r < 0) - return r; -@@ -959,7 +968,8 @@ static int acquire_new_home_record(UserRecord **ret) { - static int acquire_new_password( - const char *user_name, - UserRecord *hr, -- bool suggest) { -+ bool suggest, -+ char **ret) { - - unsigned i = 5; - char *e; -@@ -970,9 +980,17 @@ static int acquire_new_password( - - e = getenv("NEWPASSWORD"); - if (e) { -+ _cleanup_(erase_and_freep) char *copy = NULL; -+ - /* As above, this is not for use, just for testing */ - -- r = user_record_set_password(hr, STRV_MAKE(e), /* prepend = */ false); -+ if (ret) { -+ copy = strdup(e); -+ if (!copy) -+ return log_oom(); -+ } -+ -+ r = user_record_set_password(hr, STRV_MAKE(e), /* prepend = */ true); - if (r < 0) - return log_error_errno(r, "Failed to store password: %m"); - -@@ -981,6 +999,9 @@ static int acquire_new_password( - if (unsetenv("NEWPASSWORD") < 0) - return log_error_errno(errno, "Failed to unset $NEWPASSWORD: %m"); - -+ if (ret) -+ *ret = TAKE_PTR(copy); -+ - return 0; - } - -@@ -1010,10 +1031,21 @@ static int acquire_new_password( - return log_error_errno(r, "Failed to acquire password: %m"); - - if (strv_equal(first, second)) { -- r = user_record_set_password(hr, first, /* prepend = */ false); -+ _cleanup_(erase_and_freep) char *copy = NULL; -+ -+ if (ret) { -+ copy = strdup(first[0]); -+ if (!copy) -+ return log_oom(); -+ } -+ -+ r = user_record_set_password(hr, first, /* prepend = */ true); - if (r < 0) - return log_error_errno(r, "Failed to store password: %m"); - -+ if (ret) -+ *ret = TAKE_PTR(copy); -+ - return 0; - } - -@@ -1024,7 +1056,6 @@ static int acquire_new_password( - static int create_home(int argc, char *argv[], void *userdata) { - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_(user_record_unrefp) UserRecord *hr = NULL; -- _cleanup_strv_free_ char **original_hashed_passwords = NULL; - int r; - - r = acquire_bus(&bus); -@@ -1066,27 +1097,24 @@ static int create_home(int argc, char *argv[], void *userdata) { - if (r < 0) - return r; - -- /* Remember the original hashed passwords before we add our own, so that we can return to them later, -- * should the entered password turn out not to be acceptable. */ -- original_hashed_passwords = strv_copy(hr->hashed_password); -- if (!original_hashed_passwords) -- return log_oom(); -- -- /* If the JSON record carries no plain text password, then let's query it manually. */ -- if (!hr->password) { -+ /* If the JSON record carries no plain text password (besides the recovery key), then let's query it -+ * manually. */ -+ if (strv_length(hr->password) <= arg_recovery_key) { - - if (strv_isempty(hr->hashed_password)) { -+ _cleanup_(erase_and_freep) char *new_password = NULL; -+ - /* No regular (i.e. non-PKCS#11) hashed passwords set in the record, let's fix that. */ -- r = acquire_new_password(hr->user_name, hr, /* suggest = */ true); -+ r = acquire_new_password(hr->user_name, hr, /* suggest = */ true, &new_password); - if (r < 0) - return r; - -- r = user_record_make_hashed_password(hr, hr->password, /* extend = */ true); -+ r = user_record_make_hashed_password(hr, STRV_MAKE(new_password), /* extend = */ false); - if (r < 0) - return log_error_errno(r, "Failed to hash password: %m"); - } else { - /* There's a hash password set in the record, acquire the unhashed version of it. */ -- r = acquire_existing_password(hr->user_name, hr, false); -+ r = acquire_existing_password(hr->user_name, hr, /* emphasize_current= */ false); - if (r < 0) - return r; - } -@@ -1097,7 +1125,7 @@ static int create_home(int argc, char *argv[], void *userdata) { - - /* If password quality enforcement is disabled, let's at least warn client side */ - -- r = quality_check_password(hr, hr, &error); -+ r = user_record_quality_check_password(hr, hr, &error); - if (r < 0) - log_warning_errno(r, "Specified password does not pass quality checks (%s), proceeding anyway.", bus_error_message(&error, r)); - } -@@ -1124,18 +1152,16 @@ static int create_home(int argc, char *argv[], void *userdata) { - r = sd_bus_call(bus, m, HOME_SLOW_BUS_CALL_TIMEOUT_USEC, &error, NULL); - if (r < 0) { - if (sd_bus_error_has_name(&error, BUS_ERROR_LOW_PASSWORD_QUALITY)) { -+ _cleanup_(erase_and_freep) char *new_password = NULL; -+ - log_error_errno(r, "%s", bus_error_message(&error, r)); - log_info("(Use --enforce-password-policy=no to turn off password quality checks for this account.)"); - -- r = user_record_set_hashed_password(hr, original_hashed_passwords); -+ r = acquire_new_password(hr->user_name, hr, /* suggest = */ false, &new_password); - if (r < 0) - return r; - -- r = acquire_new_password(hr->user_name, hr, /* suggest = */ false); -- if (r < 0) -- return r; -- -- r = user_record_make_hashed_password(hr, hr->password, /* extend = */ true); -+ r = user_record_make_hashed_password(hr, STRV_MAKE(new_password), /* extend = */ false); - if (r < 0) - return log_error_errno(r, "Failed to hash passwords: %m"); - } else { -@@ -1488,7 +1514,7 @@ static int passwd_home(int argc, char *argv[], void *userdata) { - if (!new_secret) - return log_oom(); - -- r = acquire_new_password(username, new_secret, /* suggest = */ true); -+ r = acquire_new_password(username, new_secret, /* suggest = */ true, NULL); - if (r < 0) - return r; - -@@ -1518,7 +1544,7 @@ static int passwd_home(int argc, char *argv[], void *userdata) { - - log_error_errno(r, "%s", bus_error_message(&error, r)); - -- r = acquire_new_password(username, new_secret, /* suggest = */ false); -+ r = acquire_new_password(username, new_secret, /* suggest = */ false, NULL); - - } else if (sd_bus_error_has_name(&error, BUS_ERROR_BAD_PASSWORD_AND_NO_TOKEN)) - -@@ -1913,6 +1939,7 @@ static int help(int argc, char *argv[], void *userdata) { - " private key and matching X.509 certificate\n" - " --fido2-device=PATH Path to FIDO2 hidraw device with hmac-secret\n" - " extension\n" -+ " --recovery-key=BOOL Add a recovery key\n" - "\n%4$sAccount Management User Record Properties:%5$s\n" - " --locked=BOOL Set locked account state\n" - " --not-before=TIMESTAMP Do not allow logins before\n" -@@ -1955,7 +1982,7 @@ static int help(int argc, char *argv[], void *userdata) { - " --image-path=PATH Path to image file/directory\n" - "\n%4$sLUKS Storage User Record Properties:%5$s\n" - " --fs-type=TYPE File system type to use in case of luks\n" -- " storage (ext4, xfs, btrfs)\n" -+ " storage (btrfs, ext4, xfs)\n" - " --luks-discard=BOOL Whether to use 'discard' feature of file system\n" - " when activated (mounted)\n" - " --luks-offline-discard=BOOL\n" -@@ -2060,6 +2087,7 @@ static int parse_argv(int argc, char *argv[]) { - ARG_AUTO_LOGIN, - ARG_PKCS11_TOKEN_URI, - ARG_FIDO2_DEVICE, -+ ARG_RECOVERY_KEY, - ARG_AND_RESIZE, - ARG_AND_CHANGE_PASSWORD, - }; -@@ -2138,6 +2166,7 @@ static int parse_argv(int argc, char *argv[]) { - { "export-format", required_argument, NULL, ARG_EXPORT_FORMAT }, - { "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI }, - { "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE }, -+ { "recovery-key", required_argument, NULL, ARG_RECOVERY_KEY }, - { "and-resize", required_argument, NULL, ARG_AND_RESIZE }, - { "and-change-password", required_argument, NULL, ARG_AND_CHANGE_PASSWORD }, - {} -@@ -3168,6 +3197,24 @@ static int parse_argv(int argc, char *argv[]) { - break; - } - -+ case ARG_RECOVERY_KEY: { -+ const char *p; -+ -+ r = parse_boolean(optarg); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse --recovery-key= argument: %s", optarg); -+ -+ arg_recovery_key = r; -+ -+ FOREACH_STRING(p, "recoveryKey", "recoveryKeyType") { -+ r = drop_from_identity(p); -+ if (r < 0) -+ return r; -+ } -+ -+ break; -+ } -+ - case 'j': - arg_json = true; - arg_json_format_flags = JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO; -diff --git a/src/home/homed-conf.c b/src/home/homed-conf.c -index df3a173..c6c2e17 100644 ---- a/src/home/homed-conf.c -+++ b/src/home/homed-conf.c -@@ -45,7 +45,7 @@ int config_parse_default_file_system_type( - assert(s); - - if (!isempty(rvalue) && !supported_fstype(rvalue)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Unsupported file system, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Unsupported file system, ignoring: %s", rvalue); - return 0; - } - -diff --git a/src/home/homed-home-bus.c b/src/home/homed-home-bus.c -index 6be361a..08f77b4 100644 ---- a/src/home/homed-home-bus.c -+++ b/src/home/homed-home-bus.c -@@ -669,6 +669,7 @@ int bus_home_method_ref( - return sd_bus_error_setf(error, BUS_ERROR_HOME_ABSENT, "Home %s is currently missing or not plugged in.", h->user_name); - case HOME_UNFIXATED: - case HOME_INACTIVE: -+ case HOME_DIRTY: - return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_ACTIVE, "Home %s not active.", h->user_name); - case HOME_LOCKED: - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name); -@@ -757,7 +758,6 @@ static int bus_home_node_enumerator( - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - size_t k = 0; -- Iterator i; - Home *h; - int r; - -@@ -767,7 +767,7 @@ static int bus_home_node_enumerator( - if (!l) - return -ENOMEM; - -- HASHMAP_FOREACH(h, m->homes_by_uid, i) { -+ HASHMAP_FOREACH(h, m->homes_by_uid) { - r = bus_home_path(h, l + k); - if (r < 0) - return r; -diff --git a/src/home/homed-home.c b/src/home/homed-home.c -index f0c157c..db88d60 100644 ---- a/src/home/homed-home.c -+++ b/src/home/homed-home.c -@@ -33,6 +33,7 @@ - #include "strv.h" - #include "user-record-sign.h" - #include "user-record-util.h" -+#include "user-record-pwquality.h" - #include "user-record.h" - #include "user-util.h" - -@@ -453,6 +454,8 @@ static int convert_worker_errno(Home *h, int e, sd_bus_error *error) { - return sd_bus_error_setf(error, BUS_ERROR_BAD_PASSWORD, "Password for home %s is incorrect or not sufficient for authentication.", h->user_name); - case -EBADSLT: - return sd_bus_error_setf(error, BUS_ERROR_BAD_PASSWORD_AND_NO_TOKEN, "Password for home %s is incorrect or not sufficient, and configured security token not found either.", h->user_name); -+ case -EREMOTEIO: -+ return sd_bus_error_setf(error, BUS_ERROR_BAD_RECOVERY_KEY, "Recovery key for home %s is incorrect or not sufficient for authentication.", h->user_name); - case -ENOANO: - return sd_bus_error_setf(error, BUS_ERROR_TOKEN_PIN_NEEDED, "PIN for security token required."); - case -ERFKILL: -@@ -1042,7 +1045,7 @@ static int home_start_work(Home *h, const char *verb, UserRecord *hr, UserRecord - homework = getenv("SYSTEMD_HOMEWORK_PATH") ?: SYSTEMD_HOMEWORK_PATH; - - execl(homework, homework, verb, NULL); -- log_error_errno(errno, "Failed to invoke " SYSTEMD_HOMEWORK_PATH ": %m"); -+ log_error_errno(errno, "Failed to invoke %s: %m", homework); - _exit(EXIT_FAILURE); - } - -@@ -1112,7 +1115,7 @@ static int home_fixate_internal( - if (r < 0) - return r; - -- if (for_state == HOME_FIXATING_FOR_ACTIVATION) { -+ if (IN_SET(for_state, HOME_FIXATING_FOR_ACTIVATION, HOME_FIXATING_FOR_ACQUIRE)) { - /* Remember the secret data, since we need it for the activation again, later on. */ - user_record_unref(h->secret); - h->secret = user_record_ref(secret); -@@ -1131,6 +1134,7 @@ int home_fixate(Home *h, UserRecord *secret, sd_bus_error *error) { - case HOME_ABSENT: - return sd_bus_error_setf(error, BUS_ERROR_HOME_ABSENT, "Home %s is currently missing or not plugged in.", h->user_name); - case HOME_INACTIVE: -+ case HOME_DIRTY: - case HOME_ACTIVE: - case HOME_LOCKED: - return sd_bus_error_setf(error, BUS_ERROR_HOME_ALREADY_FIXATED, "Home %s is already fixated.", h->user_name); -@@ -1176,6 +1180,7 @@ int home_activate(Home *h, UserRecord *secret, sd_bus_error *error) { - case HOME_LOCKED: - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name); - case HOME_INACTIVE: -+ case HOME_DIRTY: - break; - default: - return sd_bus_error_setf(error, BUS_ERROR_HOME_BUSY, "An operation on home %s is currently being executed.", h->user_name); -@@ -1216,6 +1221,7 @@ int home_authenticate(Home *h, UserRecord *secret, sd_bus_error *error) { - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name); - case HOME_UNFIXATED: - case HOME_INACTIVE: -+ case HOME_DIRTY: - case HOME_ACTIVE: - break; - default: -@@ -1249,6 +1255,7 @@ int home_deactivate(Home *h, bool force, sd_bus_error *error) { - case HOME_UNFIXATED: - case HOME_ABSENT: - case HOME_INACTIVE: -+ case HOME_DIRTY: - return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_ACTIVE, "Home %s not active.", h->user_name); - case HOME_LOCKED: - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name); -@@ -1277,6 +1284,7 @@ int home_create(Home *h, UserRecord *secret, sd_bus_error *error) { - - _fallthrough_; - case HOME_UNFIXATED: -+ case HOME_DIRTY: - return sd_bus_error_setf(error, BUS_ERROR_HOME_EXISTS, "Home of user %s already exists.", h->user_name); - case HOME_ABSENT: - break; -@@ -1289,7 +1297,7 @@ int home_create(Home *h, UserRecord *secret, sd_bus_error *error) { - if (h->record->enforce_password_policy == false) - log_debug("Password quality check turned off for account, skipping."); - else { -- r = quality_check_password(h->record, secret, error); -+ r = user_record_quality_check_password(h->record, secret, error); - if (r < 0) - return r; - } -@@ -1316,6 +1324,7 @@ int home_remove(Home *h, sd_bus_error *error) { - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name); - case HOME_UNFIXATED: - case HOME_INACTIVE: -+ case HOME_DIRTY: - break; - case HOME_ACTIVE: - default: -@@ -1454,6 +1463,7 @@ int home_update(Home *h, UserRecord *hr, sd_bus_error *error) { - case HOME_LOCKED: - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name); - case HOME_INACTIVE: -+ case HOME_DIRTY: - case HOME_ACTIVE: - break; - default: -@@ -1488,6 +1498,7 @@ int home_resize(Home *h, uint64_t disk_size, UserRecord *secret, sd_bus_error *e - case HOME_LOCKED: - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name); - case HOME_INACTIVE: -+ case HOME_DIRTY: - case HOME_ACTIVE: - break; - default: -@@ -1583,6 +1594,7 @@ int home_passwd(Home *h, - case HOME_LOCKED: - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name); - case HOME_INACTIVE: -+ case HOME_DIRTY: - case HOME_ACTIVE: - break; - default: -@@ -1640,7 +1652,7 @@ int home_passwd(Home *h, - if (c->enforce_password_policy == false) - log_debug("Password quality check turned off for account, skipping."); - else { -- r = quality_check_password(c, merged_secret, error); -+ r = user_record_quality_check_password(c, merged_secret, error); - if (r < 0) - return r; - } -@@ -1665,6 +1677,7 @@ int home_unregister(Home *h, sd_bus_error *error) { - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is currently locked.", h->user_name); - case HOME_ABSENT: - case HOME_INACTIVE: -+ case HOME_DIRTY: - break; - case HOME_ACTIVE: - default: -@@ -1689,6 +1702,7 @@ int home_lock(Home *h, sd_bus_error *error) { - case HOME_UNFIXATED: - case HOME_ABSENT: - case HOME_INACTIVE: -+ case HOME_DIRTY: - return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_ACTIVE, "Home %s is not active.", h->user_name); - case HOME_LOCKED: - return sd_bus_error_setf(error, BUS_ERROR_HOME_LOCKED, "Home %s is already locked.", h->user_name); -@@ -1733,6 +1747,7 @@ int home_unlock(Home *h, UserRecord *secret, sd_bus_error *error) { - case HOME_ABSENT: - case HOME_INACTIVE: - case HOME_ACTIVE: -+ case HOME_DIRTY: - return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_LOCKED, "Home %s is not locked.", h->user_name); - case HOME_LOCKED: - break; -@@ -1744,6 +1759,7 @@ int home_unlock(Home *h, UserRecord *secret, sd_bus_error *error) { - } - - HomeState home_get_state(Home *h) { -+ int r; - assert(h); - - /* When the state field is initialized, it counts. */ -@@ -1756,8 +1772,11 @@ HomeState home_get_state(Home *h) { - return HOME_ACTIVE; - - /* And if we see the image being gone, we report this as absent */ -- if (user_record_test_image_path(h->record) == USER_TEST_ABSENT) -+ r = user_record_test_image_path(h->record); -+ if (r == USER_TEST_ABSENT) - return HOME_ABSENT; -+ if (r == USER_TEST_DIRTY) -+ return HOME_DIRTY; - - /* And for all other cases we return "inactive". */ - return HOME_INACTIVE; -@@ -2323,6 +2342,7 @@ static int home_dispatch_acquire(Home *h, Operation *o) { - break; - - case HOME_INACTIVE: -+ case HOME_DIRTY: - for_state = HOME_ACTIVATING_FOR_ACQUIRE; - call = home_activate_internal; - break; -@@ -2376,6 +2396,7 @@ static int home_dispatch_release(Home *h, Operation *o) { - case HOME_UNFIXATED: - case HOME_ABSENT: - case HOME_INACTIVE: -+ case HOME_DIRTY: - r = 1; /* done */ - break; - -@@ -2417,6 +2438,7 @@ static int home_dispatch_lock_all(Home *h, Operation *o) { - case HOME_UNFIXATED: - case HOME_ABSENT: - case HOME_INACTIVE: -+ case HOME_DIRTY: - log_info("Home %s is not active, no locking necessary.", h->user_name); - r = 1; /* done */ - break; -@@ -2463,6 +2485,7 @@ static int home_dispatch_pipe_eof(Home *h, Operation *o) { - case HOME_UNFIXATED: - case HOME_ABSENT: - case HOME_INACTIVE: -+ case HOME_DIRTY: - log_info("Home %s already deactivated, no automatic deactivation needed.", h->user_name); - break; - -@@ -2502,6 +2525,7 @@ static int home_dispatch_deactivate_force(Home *h, Operation *o) { - case HOME_UNFIXATED: - case HOME_ABSENT: - case HOME_INACTIVE: -+ case HOME_DIRTY: - log_debug("Home %s already deactivated, no forced deactivation due to unplug needed.", h->user_name); - break; - -@@ -2713,6 +2737,7 @@ static const char* const home_state_table[_HOME_STATE_MAX] = { - [HOME_UNFIXATED] = "unfixated", - [HOME_ABSENT] = "absent", - [HOME_INACTIVE] = "inactive", -+ [HOME_DIRTY] = "dirty", - [HOME_FIXATING] = "fixating", - [HOME_FIXATING_FOR_ACTIVATION] = "fixating-for-activation", - [HOME_FIXATING_FOR_ACQUIRE] = "fixating-for-acquire", -diff --git a/src/home/homed-home.h b/src/home/homed-home.h -index ec7966f..b638c6c 100644 ---- a/src/home/homed-home.h -+++ b/src/home/homed-home.h -@@ -13,6 +13,7 @@ typedef enum HomeState { - HOME_UNFIXATED, /* home exists, but local record does not */ - HOME_ABSENT, /* local record exists, but home does not */ - HOME_INACTIVE, /* record and home exist, but is not logged in */ -+ HOME_DIRTY, /* like HOME_INACTIVE, but the home directory wasn't cleanly deactivated */ - HOME_FIXATING, /* generating local record from home */ - HOME_FIXATING_FOR_ACTIVATION, /* fixating in order to activate soon */ - HOME_FIXATING_FOR_ACQUIRE, /* fixating because Acquire() was called */ -diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c -index ce6919a..fa3acb5 100644 ---- a/src/home/homed-manager-bus.c -+++ b/src/home/homed-manager-bus.c -@@ -25,7 +25,6 @@ static int property_get_auto_login( - sd_bus_error *error) { - - Manager *m = userdata; -- Iterator i; - Home *h; - int r; - -@@ -37,7 +36,7 @@ static int property_get_auto_login( - if (r < 0) - return r; - -- HASHMAP_FOREACH(h, m->homes_by_name, i) { -+ HASHMAP_FOREACH(h, m->homes_by_name) { - _cleanup_(strv_freep) char **seats = NULL; - _cleanup_free_ char *home_path = NULL; - char **s; -@@ -151,7 +150,6 @@ static int method_list_homes( - - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; -- Iterator i; - Home *h; - int r; - -@@ -166,7 +164,7 @@ static int method_list_homes( - if (r < 0) - return r; - -- HASHMAP_FOREACH(h, m->homes_by_uid, i) { -+ HASHMAP_FOREACH(h, m->homes_by_uid) { - _cleanup_free_ char *path = NULL; - - r = bus_home_path(h, &path); -@@ -560,7 +558,6 @@ static int method_lock_all_homes(sd_bus_message *message, void *userdata, sd_bus - _cleanup_(operation_unrefp) Operation *o = NULL; - bool waiting = false; - Manager *m = userdata; -- Iterator i; - Home *h; - int r; - -@@ -570,7 +567,7 @@ static int method_lock_all_homes(sd_bus_message *message, void *userdata, sd_bus - * for every suitable home we have and only when all of them completed we send a reply indicating - * completion. */ - -- HASHMAP_FOREACH(h, m->homes_by_name, i) { -+ HASHMAP_FOREACH(h, m->homes_by_name) { - - /* Automatically suspend all homes that have at least one client referencing it that asked - * for "please suspend", and no client that asked for "please do not suspend". */ -diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c -index 7d951be..9ac375a 100644 ---- a/src/home/homed-manager.c -+++ b/src/home/homed-manager.c -@@ -267,7 +267,6 @@ Manager* manager_free(Manager *m) { - - int manager_verify_user_record(Manager *m, UserRecord *hr) { - EVP_PKEY *pkey; -- Iterator i; - int r; - - assert(m); -@@ -298,7 +297,7 @@ int manager_verify_user_record(Manager *m, UserRecord *hr) { - } - } - -- HASHMAP_FOREACH(pkey, m->public_keys, i) { -+ HASHMAP_FOREACH(pkey, m->public_keys) { - r = user_record_verify(hr, pkey); - switch (r) { - -@@ -512,6 +511,8 @@ static int search_quota(uid_t uid, const char *exclude_quota_path) { - if (r < 0) { - if (ERRNO_IS_NOT_SUPPORTED(r)) - log_debug_errno(r, "No UID quota support on %s, ignoring.", where); -+ else if (ERRNO_IS_PRIVILEGE(r)) -+ log_debug_errno(r, "UID quota support for %s prohibited, ignoring.", where); - else - log_warning_errno(r, "Failed to query quota on %s, ignoring: %m", where); - -@@ -1604,9 +1605,8 @@ int manager_gc_images(Manager *m) { - manager_revalidate_image(m, h); - } else { - /* Gc all */ -- Iterator i; - -- HASHMAP_FOREACH(h, m->homes_by_name, i) -+ HASHMAP_FOREACH(h, m->homes_by_name) - manager_revalidate_image(m, h); - } - -diff --git a/src/home/homed-varlink.c b/src/home/homed-varlink.c -index c5bbba6..8131a16 100644 ---- a/src/home/homed-varlink.c -+++ b/src/home/homed-varlink.c -@@ -103,13 +103,12 @@ int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, VarlinkMet - else if (p.user_name) - h = hashmap_get(m->homes_by_name, p.user_name); - else { -- Iterator i; - - /* If neither UID nor name was specified, then dump all homes. Do so with varlink_notify() - * for all entries but the last, so that clients can stream the results, and easily process - * them piecemeal. */ - -- HASHMAP_FOREACH(h, m->homes_by_name, i) { -+ HASHMAP_FOREACH(h, m->homes_by_name) { - - if (!home_user_match_lookup_parameters(&p, h)) - continue; -@@ -219,9 +218,8 @@ int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, VarlinkMe - else if (p.group_name) - h = hashmap_get(m->homes_by_name, p.group_name); - else { -- Iterator i; - -- HASHMAP_FOREACH(h, m->homes_by_name, i) { -+ HASHMAP_FOREACH(h, m->homes_by_name) { - - if (!home_group_match_lookup_parameters(&p, h)) - continue; -@@ -315,9 +313,8 @@ int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, VarlinkMet - - } else if (p.group_name) { - const char *last = NULL; -- Iterator i; - -- HASHMAP_FOREACH(h, m->homes_by_name, i) { -+ HASHMAP_FOREACH(h, m->homes_by_name) { - - if (!strv_contains(h->record->member_of, p.group_name)) - continue; -@@ -337,9 +334,8 @@ int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, VarlinkMet - JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(p.group_name)))); - } else { - const char *last_user_name = NULL, *last_group_name = NULL; -- Iterator i; - -- HASHMAP_FOREACH(h, m->homes_by_name, i) { -+ HASHMAP_FOREACH(h, m->homes_by_name) { - char **j; - - STRV_FOREACH(j, h->record->member_of) { -diff --git a/src/home/homed.conf b/src/home/homed.conf -index 6de75fc..1b5dbed 100644 ---- a/src/home/homed.conf -+++ b/src/home/homed.conf -@@ -13,4 +13,4 @@ - - [Home] - #DefaultStorage= --#DefaultFileSystemType=ext4 -+#DefaultFileSystemType=btrfs -diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c -index ba47688..b9e696f 100644 ---- a/src/home/homework-luks.c -+++ b/src/home/homework-luks.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - - #include "blkid-util.h" - #include "blockdev-util.h" -@@ -24,6 +25,7 @@ - #include "memory-util.h" - #include "missing_magic.h" - #include "mkdir.h" -+#include "mkfs-util.h" - #include "mount-util.h" - #include "openssl-util.h" - #include "parse-util.h" -@@ -40,6 +42,53 @@ - * strictly round disk sizes down to the next 1K boundary.*/ - #define DISK_SIZE_ROUND_DOWN(x) ((x) & ~UINT64_C(1023)) - -+int run_mark_dirty(int fd, bool b) { -+ char x = '1'; -+ int r, ret; -+ -+ /* Sets or removes the 'user.home-dirty' xattr on the specified file. We use this to detect when a -+ * home directory was not properly unmounted. */ -+ -+ assert(fd >= 0); -+ -+ r = fd_verify_regular(fd); -+ if (r < 0) -+ return r; -+ -+ if (b) { -+ ret = fsetxattr(fd, "user.home-dirty", &x, 1, XATTR_CREATE); -+ if (ret < 0 && errno != EEXIST) -+ return log_debug_errno(errno, "Could not mark home directory as dirty: %m"); -+ -+ } else { -+ r = fsync_full(fd); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to synchronize image before marking it clean: %m"); -+ -+ ret = fremovexattr(fd, "user.home-dirty"); -+ if (ret < 0 && errno != ENODATA) -+ return log_debug_errno(errno, "Could not mark home directory as clean: %m"); -+ } -+ -+ r = fsync_full(fd); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to synchronize dirty flag to disk: %m"); -+ -+ return ret >= 0; -+} -+ -+int run_mark_dirty_by_path(const char *path, bool b) { -+ _cleanup_close_ int fd = -1; -+ -+ assert(path); -+ -+ fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY); -+ if (fd < 0) -+ return log_debug_errno(errno, "Failed to open %s to mark dirty or clean: %m", path); -+ -+ return run_mark_dirty(fd, b); -+} -+ - static int probe_file_system_by_fd( - int fd, - char **ret_fstype, -@@ -238,7 +287,7 @@ static int luks_setup( - if (r < 0) - return log_error_errno(r, "Failed to allocate libcryptsetup context: %m"); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - r = crypt_load(cd, CRYPT_LUKS2, NULL); - if (r < 0) -@@ -338,7 +387,7 @@ static int luks_open( - if (r < 0) - return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", dm_name); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - r = crypt_load(cd, CRYPT_LUKS2, NULL); - if (r < 0) -@@ -997,9 +1046,10 @@ int home_prepare_luks( - _cleanup_(loop_device_unrefp) LoopDevice *loop = NULL; - _cleanup_(crypt_freep) struct crypt_device *cd = NULL; - _cleanup_(erase_and_freep) void *volume_key = NULL; -+ _cleanup_close_ int root_fd = -1, image_fd = -1; - bool dm_activated = false, mounted = false; -- _cleanup_close_ int root_fd = -1; - size_t volume_key_size = 0; -+ bool marked_dirty = false; - uint64_t offset, size; - int r; - -@@ -1093,7 +1143,6 @@ int home_prepare_luks( - } - } else { - _cleanup_free_ char *fstype = NULL, *subdir = NULL; -- _cleanup_close_ int fd = -1; - const char *ip; - struct stat st; - -@@ -1103,26 +1152,32 @@ int home_prepare_luks( - if (!subdir) - return log_oom(); - -- fd = open(ip, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); -- if (fd < 0) -+ image_fd = open(ip, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); -+ if (image_fd < 0) - return log_error_errno(errno, "Failed to open image file %s: %m", ip); - -- if (fstat(fd, &st) < 0) -+ if (fstat(image_fd, &st) < 0) - return log_error_errno(errno, "Failed to fstat() image file: %m"); - if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode)) -- return log_error_errno(errno, "Image file %s is not a regular file or block device: %m", ip); -+ return log_error_errno( -+ S_ISDIR(st.st_mode) ? SYNTHETIC_ERRNO(EISDIR) : SYNTHETIC_ERRNO(EBADFD), -+ "Image file %s is not a regular file or block device: %m", ip); - -- r = luks_validate(fd, user_record_user_name_and_realm(h), h->partition_uuid, &found_partition_uuid, &offset, &size); -+ r = luks_validate(image_fd, user_record_user_name_and_realm(h), h->partition_uuid, &found_partition_uuid, &offset, &size); - if (r < 0) - return log_error_errno(r, "Failed to validate disk label: %m"); - -+ /* Everything before this point left the image untouched. We are now starting to make -+ * changes, hence mark the image dirty */ -+ marked_dirty = run_mark_dirty(image_fd, true) > 0; -+ - if (!user_record_luks_discard(h)) { -- r = run_fallocate(fd, &st); -+ r = run_fallocate(image_fd, &st); - if (r < 0) - return r; - } - -- r = loop_device_make(fd, O_RDWR, offset, size, 0, &loop); -+ r = loop_device_make(image_fd, O_RDWR, offset, size, 0, &loop); - if (r == -ENOENT) { - log_error_errno(r, "Loopback block device support is not available on this system."); - return -ENOLINK; /* make recognizable */ -@@ -1177,8 +1232,9 @@ int home_prepare_luks( - if (user_record_luks_discard(h)) - (void) run_fitrim(root_fd); - -- setup->image_fd = TAKE_FD(fd); -+ setup->image_fd = TAKE_FD(image_fd); - setup->do_offline_fallocate = !(setup->do_offline_fitrim = user_record_luks_offline_discard(h)); -+ setup->do_mark_clean = marked_dirty; - } - - setup->loop = TAKE_PTR(loop); -@@ -1207,6 +1263,9 @@ fail: - if (dm_activated) - (void) crypt_deactivate(cd, setup->dm_name); - -+ if (image_fd >= 0 && marked_dirty) -+ (void) run_mark_dirty(image_fd, false); -+ - return r; - } - -@@ -1301,6 +1360,7 @@ int home_activate_luks( - - setup.undo_dm = false; - setup.do_offline_fallocate = false; -+ setup.do_mark_clean = false; - - log_info("Everything completed."); - -@@ -1335,7 +1395,7 @@ int home_deactivate_luks(UserRecord *h) { - else { - log_info("Discovered used LUKS device %s.", dm_node); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - r = crypt_deactivate(cd, dm_name); - if (IN_SET(r, -ENODEV, -EINVAL, -ENOENT)) { -@@ -1354,6 +1414,7 @@ int home_deactivate_luks(UserRecord *h) { - else - (void) run_fallocate_by_path(user_record_image_path(h)); - -+ run_mark_dirty_by_path(user_record_image_path(h), false); - return we_detached; - } - -@@ -1369,71 +1430,6 @@ int home_trim_luks(UserRecord *h) { - return 0; - } - --static int run_mkfs( -- const char *node, -- const char *fstype, -- const char *label, -- sd_id128_t uuid, -- bool discard) { -- -- int r; -- -- assert(node); -- assert(fstype); -- assert(label); -- -- r = mkfs_exists(fstype); -- if (r < 0) -- return log_error_errno(r, "Failed to check if mkfs for file system %s exists: %m", fstype); -- if (r == 0) -- return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "No mkfs for file system %s installed.", fstype); -- -- r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL); -- if (r < 0) -- return r; -- if (r == 0) { -- const char *mkfs; -- char suuid[37]; -- -- /* Child */ -- -- mkfs = strjoina("mkfs.", fstype); -- id128_to_uuid_string(uuid, suuid); -- -- if (streq(fstype, "ext4")) -- execlp(mkfs, mkfs, -- "-L", label, -- "-U", suuid, -- "-I", "256", -- "-O", "has_journal", -- "-m", "0", -- "-E", discard ? "lazy_itable_init=1,discard" : "lazy_itable_init=1,nodiscard", -- node, NULL); -- else if (streq(fstype, "btrfs")) { -- if (discard) -- execlp(mkfs, mkfs, "-L", label, "-U", suuid, node, NULL); -- else -- execlp(mkfs, mkfs, "-L", label, "-U", suuid, "--nodiscard", node, NULL); -- } else if (streq(fstype, "xfs")) { -- const char *j; -- -- j = strjoina("uuid=", suuid); -- if (discard) -- execlp(mkfs, mkfs, "-L", label, "-m", j, "-m", "reflink=1", node, NULL); -- else -- execlp(mkfs, mkfs, "-L", label, "-m", j, "-m", "reflink=1", "-K", node, NULL); -- } else { -- log_error("Cannot make file system: %s", fstype); -- _exit(EXIT_FAILURE); -- } -- -- log_error_errno(errno, "Failed to execute %s: %m", mkfs); -- _exit(EXIT_FAILURE); -- } -- -- return 0; --} -- - static struct crypt_pbkdf_type* build_good_pbkdf(struct crypt_pbkdf_type *buffer, UserRecord *hr) { - assert(buffer); - assert(hr); -@@ -1480,9 +1476,9 @@ static int luks_format( - _cleanup_(crypt_freep) struct crypt_device *cd = NULL; - _cleanup_(erase_and_freep) void *volume_key = NULL; - struct crypt_pbkdf_type good_pbkdf, minimal_pbkdf; -+ char suuid[ID128_UUID_STRING_MAX], **pp; - _cleanup_free_ char *text = NULL; - size_t volume_key_size; -- char suuid[37], **pp; - int slot = 0, r; - - assert(node); -@@ -1494,7 +1490,7 @@ static int luks_format( - if (r < 0) - return log_error_errno(r, "Failed to allocate libcryptsetup context: %m"); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - /* Normally we'd, just leave volume key generation to libcryptsetup. However, we can't, since we - * can't extract the volume key from the library again, but we need it in order to encrypt the JSON -@@ -1614,7 +1610,7 @@ static int make_partition_table( - _cleanup_free_ char *path = NULL, *disk_uuid_as_string = NULL; - uint64_t offset, size; - sd_id128_t disk_uuid; -- char uuids[37]; -+ char uuids[ID128_UUID_STRING_MAX]; - int r; - - assert(fd >= 0); -@@ -2015,7 +2011,8 @@ int home_create_luks( - - r = chattr_fd(image_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); - if (r < 0) -- log_warning_errno(r, "Failed to set file attributes on %s, ignoring: %m", temporary_image_path); -+ log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) ? LOG_DEBUG : LOG_WARNING, r, -+ "Failed to set file attributes on %s, ignoring: %m", temporary_image_path); - - r = home_truncate(h, image_fd, temporary_image_path, host_size); - if (r < 0) -@@ -2080,7 +2077,7 @@ int home_create_luks( - - log_info("Setting up LUKS device %s completed.", dm_node); - -- r = run_mkfs(dm_node, fstype, user_record_user_name_and_realm(h), fs_uuid, user_record_luks_discard(h)); -+ r = make_filesystem(dm_node, fstype, user_record_user_name_and_realm(h), fs_uuid, user_record_luks_discard(h)); - if (r < 0) - goto fail; - -@@ -2164,6 +2161,9 @@ int home_create_luks( - goto fail; - } - -+ crypt_free(cd); -+ cd = NULL; -+ - dm_activated = false; - - loop = loop_device_unref(loop); -@@ -2174,8 +2174,22 @@ int home_create_luks( - goto fail; - } - -+ /* Sync everything to disk before we move things into place under the final name. */ -+ if (fsync(image_fd) < 0) { -+ r = log_error_errno(r, "Failed to synchronize image to disk: %m"); -+ goto fail; -+ } -+ - if (disk_uuid_path) - (void) ioctl(image_fd, BLKRRPART, 0); -+ else { -+ /* If we operate on a file, sync the containing directory too. */ -+ r = fsync_directory_of_file(image_fd); -+ if (r < 0) { -+ log_error_errno(r, "Failed to synchronize directory of image file to disk: %m"); -+ goto fail; -+ } -+ } - - /* Let's close the image fd now. If we are operating on a real block device this will release the BSD - * lock that ensures udev doesn't interfere with what we are doing */ -@@ -2971,7 +2985,7 @@ int home_lock_luks(UserRecord *h) { - return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", dm_name); - - log_info("Discovered used LUKS device %s.", dm_node); -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - if (syncfs(root_fd) < 0) /* Snake oil, but let's better be safe than sorry */ - return log_error_errno(errno, "Failed to synchronize file system %s: %m", p); -@@ -3036,7 +3050,7 @@ int home_unlock_luks(UserRecord *h, PasswordCache *cache) { - return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", dm_name); - - log_info("Discovered used LUKS device %s.", dm_node); -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - r = -ENOKEY; - FOREACH_POINTER(list, cache->pkcs11_passwords, cache->fido2_passwords, h->password) { -diff --git a/src/home/homework-luks.h b/src/home/homework-luks.h -index b51f1ad..af0ad4b 100644 ---- a/src/home/homework-luks.h -+++ b/src/home/homework-luks.h -@@ -1,7 +1,7 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - #pragma once - --#include "crypt-util.h" -+#include "cryptsetup-util.h" - #include "homework.h" - #include "user-record.h" - -@@ -42,3 +42,5 @@ int run_fitrim(int root_fd); - int run_fitrim_by_path(const char *root_path); - int run_fallocate(int backing_fd, const struct stat *st); - int run_fallocate_by_path(const char *backing_path); -+int run_mark_dirty(int fd, bool b); -+int run_mark_dirty_by_path(const char *path, bool b); -diff --git a/src/home/homework.c b/src/home/homework.c -index 83bd875..594c4a0 100644 ---- a/src/home/homework.c -+++ b/src/home/homework.c -@@ -20,6 +20,7 @@ - #include "main-func.h" - #include "memory-util.h" - #include "missing_magic.h" -+#include "modhex.h" - #include "mount-util.h" - #include "path-util.h" - #include "rm-rf.h" -@@ -46,7 +47,7 @@ int user_record_authenticate( - PasswordCache *cache, - bool strict_verify) { - -- bool need_password = false, need_token = false, need_pin = false, need_protected_authentication_path_permitted = false, need_user_presence_permitted = false, -+ bool need_password = false, need_recovery_key = false, need_token = false, need_pin = false, need_protected_authentication_path_permitted = false, need_user_presence_permitted = false, - pin_locked = false, pin_incorrect = false, pin_incorrect_few_tries_left = false, pin_incorrect_one_try_left = false, token_action_timeout = false; - int r; - -@@ -65,11 +66,10 @@ int user_record_authenticate( - * PKCS#11/FIDO2 dance for the relevant token again and again. */ - - /* First, let's see if the supplied plain-text passwords work? */ -- r = user_record_test_secret(h, secret); -- if (r == -ENOKEY) { -- log_info_errno(r, "None of the supplied plaintext passwords unlocks the user record's hashed passwords."); -+ r = user_record_test_password(h, secret); -+ if (r == -ENOKEY) - need_password = true; -- } else if (r == -ENXIO) -+ else if (r == -ENXIO) - log_debug_errno(r, "User record has no hashed passwords, plaintext passwords not tested."); - else if (r < 0) - return log_error_errno(r, "Failed to validate password of record: %m"); -@@ -78,6 +78,26 @@ int user_record_authenticate( - return 1; - } - -+ /* Similar, but test against the recovery keys */ -+ r = user_record_test_recovery_key(h, secret); -+ if (r == -ENOKEY) -+ need_recovery_key = true; -+ else if (r == -ENXIO) -+ log_debug_errno(r, "User record has no recovery keys, plaintext passwords not tested against it."); -+ else if (r < 0) -+ return log_error_errno(r, "Failed to validate the recovery key of the record: %m"); -+ else { -+ log_info("Provided password is a recovery key that unlocks the user record."); -+ return 1; -+ } -+ -+ if (need_password && need_recovery_key) -+ log_info("None of the supplied plaintext passwords unlock the user record's hashed passwords or recovery keys."); -+ else if (need_password) -+ log_info("None of the supplied plaintext passwords unlock the user record's hashed passwords."); -+ else -+ log_info("None of the supplied plaintext passwords unlock the user record's hashed recovery keys."); -+ - /* Second, test cached PKCS#11 passwords */ - for (size_t n = 0; n < h->n_pkcs11_encrypted_key; n++) { - char **pp; -@@ -235,19 +255,21 @@ int user_record_authenticate( - return -EBADSLT; - if (need_password) - return -ENOKEY; -+ if (need_recovery_key) -+ return -EREMOTEIO; - -- /* Hmm, this means neither PCKS#11/FIDO2 nor classic hashed passwords were supplied, we cannot -- * authenticate this reasonably */ -+ /* Hmm, this means neither PCKS#11/FIDO2 nor classic hashed passwords or recovery keys were supplied, -+ * we cannot authenticate this reasonably */ - if (strict_verify) - return log_debug_errno(SYNTHETIC_ERRNO(EKEYREVOKED), -- "No hashed passwords and no PKCS#11/FIDO2 tokens defined, cannot authenticate user record, refusing."); -+ "No hashed passwords, no recovery keys and no PKCS#11/FIDO2 tokens defined, cannot authenticate user record, refusing."); - - /* If strict verification is off this means we are possibly in the case where we encountered an - * unfixated record, i.e. a synthetic one that accordingly lacks any authentication data. In this - * case, allow the authentication to pass for now, so that the second (or third) authentication level - * (the ones of the user record in the LUKS header or inside the home directory) will then catch - * invalid passwords. The second/third authentication always runs in strict verification mode. */ -- log_debug("No hashed passwords and no PKCS#11 tokens defined in record, cannot authenticate user record. " -+ log_debug("No hashed passwords, not recovery keys and no PKCS#11 tokens defined in record, cannot authenticate user record. " - "Deferring to embedded user record."); - return 0; - } -@@ -286,6 +308,12 @@ int home_setup_undo(HomeSetup *setup) { - r = q; - } - -+ if (setup->do_mark_clean) { -+ q = run_mark_dirty(setup->image_fd, false); -+ if (q < 0) -+ r = q; -+ } -+ - setup->image_fd = safe_close(setup->image_fd); - } - -@@ -293,6 +321,7 @@ int home_setup_undo(HomeSetup *setup) { - setup->undo_dm = false; - setup->do_offline_fitrim = false; - setup->do_offline_fallocate = false; -+ setup->do_mark_clean = false; - - setup->dm_name = mfree(setup->dm_name); - setup->dm_node = mfree(setup->dm_node); -@@ -896,7 +925,7 @@ static int user_record_compile_effective_passwords( - STRV_FOREACH(j, h->password) { - r = test_password_one(*i, *j); - if (r < 0) -- return log_error_errno(r, "Failed to test plain text password: %m"); -+ return log_error_errno(r, "Failed to test plaintext password: %m"); - if (r > 0) { - if (ret_effective_passwords) { - r = strv_extend(&effective, *j); -@@ -914,6 +943,48 @@ static int user_record_compile_effective_passwords( - return log_error_errno(SYNTHETIC_ERRNO(ENOKEY), "Missing plaintext password for defined hashed password"); - } - -+ for (n = 0; n < h->n_recovery_key; n++) { -+ bool found = false; -+ char **j; -+ -+ log_debug("Looking for plaintext recovery key for: %s", h->recovery_key[n].hashed_password); -+ -+ STRV_FOREACH(j, h->password) { -+ _cleanup_(erase_and_freep) char *mangled = NULL; -+ const char *p; -+ -+ if (streq(h->recovery_key[n].type, "modhex64")) { -+ -+ r = normalize_recovery_key(*j, &mangled); -+ if (r == -EINVAL) /* Not properly formatted, probably a regular password. */ -+ continue; -+ if (r < 0) -+ return log_error_errno(r, "Failed to normalize recovery key: %m"); -+ -+ p = mangled; -+ } else -+ p = *j; -+ -+ r = test_password_one(h->recovery_key[n].hashed_password, p); -+ if (r < 0) -+ return log_error_errno(r, "Failed to test plaintext recovery key: %m"); -+ if (r > 0) { -+ if (ret_effective_passwords) { -+ r = strv_extend(&effective, p); -+ if (r < 0) -+ return log_oom(); -+ } -+ -+ log_debug("Found plaintext recovery key."); -+ found = true; -+ break; -+ } -+ } -+ -+ if (!found) -+ return log_error_errno(SYNTHETIC_ERRNO(EREMOTEIO), "Missing plaintext recovery key for defined recovery key"); -+ } -+ - for (n = 0; n < h->n_pkcs11_encrypted_key; n++) { - #if HAVE_P11KIT - _cleanup_(pkcs11_callback_data_release) struct pkcs11_callback_data data = { -@@ -1602,6 +1673,7 @@ static int run(int argc, char *argv[]) { - * ENOTTY → operation not support on this storage - * ESOCKTNOSUPPORT → operation not support on this file system - * ENOKEY → password incorrect (or not sufficient, or not supplied) -+ * EREMOTEIO → recovery key incorrect (or not sufficeint, or not supplied — only if no passwords defined) - * EBADSLT → similar, but PKCS#11 device is defined and might be able to provide password, if it was plugged in which it is not - * ENOANO → suitable PKCS#11/FIDO2 device found, but PIN is missing to unlock it - * ERFKILL → suitable PKCS#11 device found, but OK to ask for on-device interactive authentication not given -@@ -1641,7 +1713,7 @@ static int run(int argc, char *argv[]) { - r = home_unlock(home); - else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb '%s'.", argv[1]); -- if (r == -ENOKEY && !strv_isempty(home->password)) { /* There were passwords specified but they were incorrect */ -+ if (IN_SET(r, -ENOKEY, -EREMOTEIO) && !strv_isempty(home->password) ) { /* There were passwords specified but they were incorrect */ - usec_t end, n, d; - - /* Make sure bad password replies always take at least 3s, and if longer multiples of 3s, so -diff --git a/src/home/homework.h b/src/home/homework.h -index ce8f2a4..c9b0d3b 100644 ---- a/src/home/homework.h -+++ b/src/home/homework.h -@@ -31,6 +31,7 @@ typedef struct HomeSetup { - bool undo_mount; - bool do_offline_fitrim; - bool do_offline_fallocate; -+ bool do_mark_clean; - - uint64_t partition_offset; - uint64_t partition_size; -diff --git a/src/home/meson.build b/src/home/meson.build -index 797f3a3..69bacac 100644 ---- a/src/home/meson.build -+++ b/src/home/meson.build -@@ -7,6 +7,7 @@ systemd_homework_sources = files(''' - homework-cifs.h - homework-directory.c - homework-directory.h -+ homework-fido2.h - homework-fscrypt.c - homework-fscrypt.h - homework-luks.c -@@ -14,11 +15,12 @@ systemd_homework_sources = files(''' - homework-mount.c - homework-mount.h - homework-pkcs11.h -- homework-fido2.h - homework-quota.c - homework-quota.h - homework.c - homework.h -+ modhex.c -+ modhex.h - user-record-util.c - user-record-util.h - '''.split()) -@@ -50,8 +52,10 @@ systemd_homed_sources = files(''' - homed-varlink.c - homed-varlink.h - homed.c -- pwquality-util.c -- pwquality-util.h -+ modhex.c -+ modhex.h -+ user-record-pwquality.c -+ user-record-pwquality.h - user-record-sign.c - user-record-sign.h - user-record-util.c -@@ -73,9 +77,13 @@ homectl_sources = files(''' - homectl-fido2.h - homectl-pkcs11.c - homectl-pkcs11.h -+ homectl-recovery-key.c -+ homectl-recovery-key.h - homectl.c -- pwquality-util.c -- pwquality-util.h -+ modhex.c -+ modhex.h -+ user-record-pwquality.c -+ user-record-pwquality.h - user-record-util.c - user-record-util.h - '''.split()) -@@ -84,6 +92,8 @@ pam_systemd_home_sym = 'src/home/pam_systemd_home.sym' - pam_systemd_home_c = files(''' - home-util.c - home-util.h -+ modhex.c -+ modhex.h - pam_systemd_home.c - user-record-util.c - user-record-util.h -@@ -100,3 +110,11 @@ if conf.get('ENABLE_HOMED') == 1 - install_data('homed.conf', - install_dir : pkgsysconfdir) - endif -+ -+tests += [ -+ [['src/home/test-modhex.c', -+ 'src/home/modhex.c', -+ 'src/home/modhex.h'], -+ [], -+ []], -+] -diff --git a/src/home/modhex.c b/src/home/modhex.c -new file mode 100644 -index 0000000..82a5b20 ---- /dev/null -+++ b/src/home/modhex.c -@@ -0,0 +1,74 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include -+ -+#include "modhex.h" -+#include "macro.h" -+#include "memory-util.h" -+ -+const char modhex_alphabet[16] = { -+ 'c', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'r', 't', 'u', 'v' -+}; -+ -+int decode_modhex_char(char x) { -+ -+ for (size_t i = 0; i < ELEMENTSOF(modhex_alphabet); i++) -+ /* Check both upper and lowercase */ -+ if (modhex_alphabet[i] == x || (modhex_alphabet[i] - 32) == x) -+ return i; -+ -+ return -EINVAL; -+} -+ -+int normalize_recovery_key(const char *password, char **ret) { -+ _cleanup_(erase_and_freep) char *mangled = NULL; -+ size_t l; -+ -+ assert(password); -+ assert(ret); -+ -+ l = strlen(password); -+ if (!IN_SET(l, -+ MODHEX_RAW_LENGTH*2, /* syntax without dashes */ -+ MODHEX_FORMATTED_LENGTH-1)) /* syntax with dashes */ -+ return -EINVAL; -+ -+ mangled = new(char, MODHEX_FORMATTED_LENGTH); -+ if (!mangled) -+ return -ENOMEM; -+ -+ for (size_t i = 0, j = 0; i < MODHEX_RAW_LENGTH; i++) { -+ size_t k; -+ int a, b; -+ -+ if (l == MODHEX_RAW_LENGTH*2) -+ /* Syntax without dashes */ -+ k = i * 2; -+ else { -+ /* Syntax with dashes */ -+ assert(l == MODHEX_FORMATTED_LENGTH-1); -+ k = i * 2 + i / 4; -+ -+ if (i > 0 && i % 4 == 0 && password[k-1] != '-') -+ return -EINVAL; -+ } -+ -+ a = decode_modhex_char(password[k]); -+ if (a < 0) -+ return -EINVAL; -+ b = decode_modhex_char(password[k+1]); -+ if (b < 0) -+ return -EINVAL; -+ -+ mangled[j++] = modhex_alphabet[a]; -+ mangled[j++] = modhex_alphabet[b]; -+ -+ if (i % 4 == 3) -+ mangled[j++] = '-'; -+ } -+ -+ mangled[MODHEX_FORMATTED_LENGTH-1] = 0; -+ -+ *ret = TAKE_PTR(mangled); -+ return 0; -+} -diff --git a/src/home/modhex.h b/src/home/modhex.h -new file mode 100644 -index 0000000..e0067ae ---- /dev/null -+++ b/src/home/modhex.h -@@ -0,0 +1,14 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+/* 256 bit keys = 32 bytes */ -+#define MODHEX_RAW_LENGTH 32 -+ -+/* Formatted as sequences of 64 modhex characters, with dashes inserted after multiples of 8 chars (incl. trailing NUL) */ -+#define MODHEX_FORMATTED_LENGTH (MODHEX_RAW_LENGTH*2/8*9) -+ -+extern const char modhex_alphabet[16]; -+ -+int decode_modhex_char(char x); -+ -+int normalize_recovery_key(const char *password, char **ret); -diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c -index 2c2c7a0..13b164e 100644 ---- a/src/home/pam_systemd_home.c -+++ b/src/home/pam_systemd_home.c -@@ -7,6 +7,7 @@ - - #include "bus-common-errors.h" - #include "bus-locator.h" -+#include "bus-util.h" - #include "errno-util.h" - #include "fd-util.h" - #include "home-util.h" -@@ -153,8 +154,7 @@ static int acquire_user_record( - - r = bus_call_method(bus, bus_home_mgr, "GetUserRecordByName", &error, &reply, "s", username); - if (r < 0) { -- if (sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN) || -- sd_bus_error_has_name(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER)) { -+ if (bus_error_is_unknown_service(&error)) { - pam_syslog(handle, LOG_DEBUG, "systemd-homed is not available: %s", bus_error_message(&error, r)); - goto user_unknown; - } -diff --git a/src/home/pwquality-util.c b/src/home/pwquality-util.c -deleted file mode 100644 -index fbf6f6c..0000000 ---- a/src/home/pwquality-util.c -+++ /dev/null -@@ -1,186 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ -- --#include -- --#if HAVE_PWQUALITY --/* pwquality.h uses size_t but doesn't include sys/types.h on its own */ --#include --#include --#endif -- --#include "bus-common-errors.h" --#include "home-util.h" --#include "memory-util.h" --#include "pwquality-util.h" --#include "strv.h" -- --#if HAVE_PWQUALITY --DEFINE_TRIVIAL_CLEANUP_FUNC(pwquality_settings_t*, pwquality_free_settings); -- --static void pwquality_maybe_disable_dictionary( -- pwquality_settings_t *pwq) { -- -- char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; -- const char *path; -- int r; -- -- r = pwquality_get_str_value(pwq, PWQ_SETTING_DICT_PATH, &path); -- if (r < 0) { -- log_warning("Failed to read libpwquality dictionary path, ignoring: %s", pwquality_strerror(buf, sizeof(buf), r, NULL)); -- return; -- } -- -- // REMOVE THIS AS SOON AS https://github.com/libpwquality/libpwquality/pull/21 IS MERGED AND RELEASED -- if (isempty(path)) -- path = "/usr/share/cracklib/pw_dict.pwd.gz"; -- -- if (isempty(path)) { -- log_warning("Weird, no dictionary file configured, ignoring."); -- return; -- } -- -- if (access(path, F_OK) >= 0) -- return; -- -- if (errno != ENOENT) { -- log_warning_errno(errno, "Failed to check if dictionary file %s exists, ignoring: %m", path); -- return; -- } -- -- r = pwquality_set_int_value(pwq, PWQ_SETTING_DICT_CHECK, 0); -- if (r < 0) { -- log_warning("Failed to disable libpwquality dictionary check, ignoring: %s", pwquality_strerror(buf, sizeof(buf), r, NULL)); -- return; -- } --} -- --int quality_check_password( -- UserRecord *hr, -- UserRecord *secret, -- sd_bus_error *error) { -- -- _cleanup_(pwquality_free_settingsp) pwquality_settings_t *pwq = NULL; -- char buf[PWQ_MAX_ERROR_MESSAGE_LEN], **pp; -- void *auxerror; -- int r; -- -- assert(hr); -- assert(secret); -- -- pwq = pwquality_default_settings(); -- if (!pwq) -- return log_oom(); -- -- r = pwquality_read_config(pwq, NULL, &auxerror); -- if (r < 0) -- log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to read libpwquality configuration, ignoring: %s", -- pwquality_strerror(buf, sizeof(buf), r, auxerror)); -- -- pwquality_maybe_disable_dictionary(pwq); -- -- /* This is a bit more complex than one might think at first. pwquality_check() would like to know the -- * old password to make security checks. We support arbitrary numbers of passwords however, hence we -- * call the function once for each combination of old and new password. */ -- -- /* Iterate through all new passwords */ -- STRV_FOREACH(pp, secret->password) { -- bool called = false; -- char **old; -- -- r = test_password_many(hr->hashed_password, *pp); -- if (r < 0) -- return r; -- if (r == 0) /* This is an old password as it isn't listed in the hashedPassword field, skip it */ -- continue; -- -- /* Check this password against all old passwords */ -- STRV_FOREACH(old, secret->password) { -- -- if (streq(*pp, *old)) -- continue; -- -- r = test_password_many(hr->hashed_password, *old); -- if (r < 0) -- return r; -- if (r > 0) /* This is a new password, not suitable as old password */ -- continue; -- -- r = pwquality_check(pwq, *pp, *old, hr->user_name, &auxerror); -- if (r < 0) -- return sd_bus_error_setf(error, BUS_ERROR_LOW_PASSWORD_QUALITY, "Password too weak: %s", -- pwquality_strerror(buf, sizeof(buf), r, auxerror)); -- -- called = true; -- } -- -- if (called) -- continue; -- -- /* If there are no old passwords, let's call pwquality_check() without any. */ -- r = pwquality_check(pwq, *pp, NULL, hr->user_name, &auxerror); -- if (r < 0) -- return sd_bus_error_setf(error, BUS_ERROR_LOW_PASSWORD_QUALITY, "Password too weak: %s", -- pwquality_strerror(buf, sizeof(buf), r, auxerror)); -- } -- -- return 0; --} -- --#define N_SUGGESTIONS 6 -- --int suggest_passwords(void) { -- _cleanup_(pwquality_free_settingsp) pwquality_settings_t *pwq = NULL; -- _cleanup_strv_free_erase_ char **suggestions = NULL; -- _cleanup_(erase_and_freep) char *joined = NULL; -- char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; -- void *auxerror; -- size_t i; -- int r; -- -- pwq = pwquality_default_settings(); -- if (!pwq) -- return log_oom(); -- -- r = pwquality_read_config(pwq, NULL, &auxerror); -- if (r < 0) -- log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to read libpwquality configuration, ignoring: %s", -- pwquality_strerror(buf, sizeof(buf), r, auxerror)); -- -- pwquality_maybe_disable_dictionary(pwq); -- -- suggestions = new0(char*, N_SUGGESTIONS+1); -- if (!suggestions) -- return log_oom(); -- -- for (i = 0; i < N_SUGGESTIONS; i++) { -- r = pwquality_generate(pwq, 64, suggestions + i); -- if (r < 0) -- return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate password, ignoring: %s", -- pwquality_strerror(buf, sizeof(buf), r, NULL)); -- } -- -- joined = strv_join(suggestions, " "); -- if (!joined) -- return log_oom(); -- -- log_info("Password suggestions: %s", joined); -- return 0; --} -- --#else -- --int quality_check_password( -- UserRecord *hr, -- UserRecord *secret, -- sd_bus_error *error) { -- -- assert(hr); -- assert(secret); -- -- return 0; --} -- --int suggest_passwords(void) { -- return 0; --} --#endif -diff --git a/src/home/pwquality-util.h b/src/home/pwquality-util.h -deleted file mode 100644 -index d61c04c..0000000 ---- a/src/home/pwquality-util.h -+++ /dev/null -@@ -1,9 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ --#pragma once -- --#include "sd-bus.h" --#include "user-record.h" -- --int quality_check_password(UserRecord *hr, UserRecord *secret, sd_bus_error *error); -- --int suggest_passwords(void); -diff --git a/src/home/test-modhex.c b/src/home/test-modhex.c -new file mode 100644 -index 0000000..4eebeea ---- /dev/null -+++ b/src/home/test-modhex.c -@@ -0,0 +1,51 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include "modhex.h" -+#include "alloc-util.h" -+#include "string-util.h" -+ -+static void test_normalize_recovery_key(const char *t, const char *expected) { -+ _cleanup_free_ char *z = NULL; -+ int r; -+ -+ assert(t); -+ -+ r = normalize_recovery_key(t, &z); -+ assert_se(expected ? -+ (r >= 0 && streq(z, expected)) : -+ (r == -EINVAL && z == NULL)); -+} -+ -+int main(int argc, char *arv[]) { -+ -+ test_normalize_recovery_key("iefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj", -+ "iefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj"); -+ -+ test_normalize_recovery_key("iefgcelhbiduvkjvcjvuncnkvlfchdidjhtuhhdeurkllkegilkjgbrthjkbgktj", -+ "iefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj"); -+ -+ test_normalize_recovery_key("IEFGCELH-BIDUVKJV-CJVUNCNK-VLFCHDID-JHTUHHDE-URKLLKEG-ILKJGBRT-HJKBGKTJ", -+ "iefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj"); -+ -+ test_normalize_recovery_key("IEFGCELHBIDUVKJVCJVUNCNKVLFCHDIDJHTUHHDEURKLLKEGILKJGBRTHJKBGKTJ", -+ "iefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj"); -+ -+ test_normalize_recovery_key("Iefgcelh-Biduvkjv-Cjvuncnk-Vlfchdid-Jhtuhhde-Urkllkeg-Ilkjgbrt-Hjkbgktj", -+ "iefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj"); -+ -+ test_normalize_recovery_key("Iefgcelhbiduvkjvcjvuncnkvlfchdidjhtuhhdeurkllkegilkjgbrthjkbgktj", -+ "iefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj"); -+ -+ test_normalize_recovery_key("iefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgkt", NULL); -+ test_normalize_recovery_key("iefgcelhbiduvkjvcjvuncnkvlfchdidjhtuhhdeurkllkegilkjgbrthjkbgkt", NULL); -+ test_normalize_recovery_key("IEFGCELHBIDUVKJVCJVUNCNKVLFCHDIDJHTUHHDEURKLLKEGILKJGBRTHJKBGKT", NULL); -+ -+ test_normalize_recovery_key("xefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj", NULL); -+ test_normalize_recovery_key("Xefgcelh-biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj", NULL); -+ test_normalize_recovery_key("iefgcelh+biduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj", NULL); -+ test_normalize_recovery_key("iefgcelhebiduvkjv-cjvuncnk-vlfchdid-jhtuhhde-urkllkeg-ilkjgbrt-hjkbgktj", NULL); -+ -+ test_normalize_recovery_key("", NULL); -+ -+ return 0; -+} -diff --git a/src/home/user-record-pwquality.c b/src/home/user-record-pwquality.c -new file mode 100644 -index 0000000..a5d632c ---- /dev/null -+++ b/src/home/user-record-pwquality.c -@@ -0,0 +1,90 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include "bus-common-errors.h" -+#include "errno-util.h" -+#include "home-util.h" -+#include "pwquality-util.h" -+#include "strv.h" -+#include "user-record-pwquality.h" -+#include "user-record-util.h" -+ -+#if HAVE_PWQUALITY -+ -+int user_record_quality_check_password( -+ UserRecord *hr, -+ UserRecord *secret, -+ sd_bus_error *error) { -+ -+ _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL; -+ char buf[PWQ_MAX_ERROR_MESSAGE_LEN], **pp; -+ void *auxerror; -+ int r; -+ -+ assert(hr); -+ assert(secret); -+ -+ r = pwq_allocate_context(&pwq); -+ if (ERRNO_IS_NOT_SUPPORTED(r)) -+ return 0; -+ if (r < 0) -+ return log_debug_errno(r, "Failed to allocate libpwquality context: %m"); -+ -+ /* This is a bit more complex than one might think at first. pwquality_check() would like to know the -+ * old password to make security checks. We support arbitrary numbers of passwords however, hence we -+ * call the function once for each combination of old and new password. */ -+ -+ /* Iterate through all new passwords */ -+ STRV_FOREACH(pp, secret->password) { -+ bool called = false; -+ char **old; -+ -+ r = test_password_many(hr->hashed_password, *pp); -+ if (r < 0) -+ return r; -+ if (r == 0) /* This is an old password as it isn't listed in the hashedPassword field, skip it */ -+ continue; -+ -+ /* Check this password against all old passwords */ -+ STRV_FOREACH(old, secret->password) { -+ -+ if (streq(*pp, *old)) -+ continue; -+ -+ r = test_password_many(hr->hashed_password, *old); -+ if (r < 0) -+ return r; -+ if (r > 0) /* This is a new password, not suitable as old password */ -+ continue; -+ -+ r = sym_pwquality_check(pwq, *pp, *old, hr->user_name, &auxerror); -+ if (r < 0) -+ return sd_bus_error_setf(error, BUS_ERROR_LOW_PASSWORD_QUALITY, "Password too weak: %s", -+ sym_pwquality_strerror(buf, sizeof(buf), r, auxerror)); -+ -+ called = true; -+ } -+ -+ if (called) -+ continue; -+ -+ /* If there are no old passwords, let's call pwquality_check() without any. */ -+ r = sym_pwquality_check(pwq, *pp, NULL, hr->user_name, &auxerror); -+ if (r < 0) -+ return sd_bus_error_setf(error, BUS_ERROR_LOW_PASSWORD_QUALITY, "Password too weak: %s", -+ sym_pwquality_strerror(buf, sizeof(buf), r, auxerror)); -+ } -+ -+ return 1; -+} -+ -+#else -+ -+int user_record_quality_check_password( -+ UserRecord *hr, -+ UserRecord *secret, -+ sd_bus_error *error) { -+ -+ return 0; -+} -+ -+#endif -diff --git a/src/home/user-record-pwquality.h b/src/home/user-record-pwquality.h -new file mode 100644 -index 0000000..a37d369 ---- /dev/null -+++ b/src/home/user-record-pwquality.h -@@ -0,0 +1,7 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#include "sd-bus.h" -+#include "user-record.h" -+ -+int user_record_quality_check_password(UserRecord *hr, UserRecord *secret, sd_bus_error *error); -diff --git a/src/home/user-record-util.c b/src/home/user-record-util.c -index 5d0ac86..0bbe44c 100644 ---- a/src/home/user-record-util.c -+++ b/src/home/user-record-util.c -@@ -1,9 +1,13 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - -+#include -+ - #include "errno-util.h" - #include "home-util.h" - #include "id128-util.h" - #include "libcrypt-util.h" -+#include "memory-util.h" -+#include "modhex.h" - #include "mountpoint-util.h" - #include "path-util.h" - #include "stat-util.h" -@@ -104,7 +108,7 @@ int user_record_synthesize( - } - - int group_record_synthesize(GroupRecord *g, UserRecord *h) { -- _cleanup_free_ char *un = NULL, *rr = NULL, *group_name_and_realm = NULL; -+ _cleanup_free_ char *un = NULL, *rr = NULL, *group_name_and_realm = NULL, *description = NULL; - char smid[SD_ID128_STRING_MAX]; - sd_id128_t mid; - int r; -@@ -133,10 +137,15 @@ int group_record_synthesize(GroupRecord *g, UserRecord *h) { - return -ENOMEM; - } - -+ description = strjoin("Primary Group of User ", un); -+ if (!description) -+ return -ENOMEM; -+ - r = json_build(&g->json, - JSON_BUILD_OBJECT( - JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(un)), - JSON_BUILD_PAIR_CONDITION(!!rr, "realm", JSON_BUILD_STRING(rr)), -+ JSON_BUILD_PAIR("description", JSON_BUILD_STRING(description)), - JSON_BUILD_PAIR("binding", JSON_BUILD_OBJECT( - JSON_BUILD_PAIR(sd_id128_to_string(mid, smid), JSON_BUILD_OBJECT( - JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(user_record_gid(h))))))), -@@ -275,7 +284,7 @@ int user_record_add_binding( - gid_t gid) { - - _cleanup_(json_variant_unrefp) JsonVariant *new_binding_entry = NULL, *binding = NULL; -- char smid[SD_ID128_STRING_MAX], partition_uuids[37], luks_uuids[37], fs_uuids[37]; -+ char smid[SD_ID128_STRING_MAX], partition_uuids[ID128_UUID_STRING_MAX], luks_uuids[ID128_UUID_STRING_MAX], fs_uuids[ID128_UUID_STRING_MAX]; - _cleanup_free_ char *ip = NULL, *hd = NULL, *ip_auto = NULL, *lc = NULL, *lcm = NULL, *fst = NULL; - sd_id128_t mid; - int r; -@@ -490,8 +499,21 @@ int user_record_test_image_path(UserRecord *h) { - switch (user_record_storage(h)) { - - case USER_LUKS: -- if (S_ISREG(st.st_mode)) -+ if (S_ISREG(st.st_mode)) { -+ ssize_t n; -+ char x[2]; -+ -+ n = getxattr(ip, "user.home-dirty", x, sizeof(x)); -+ if (n < 0) { -+ if (errno != ENODATA) -+ log_debug_errno(errno, "Unable to read dirty xattr off image file, ignoring: %m"); -+ -+ } else if (n == 1 && x[0] == '1') -+ return USER_TEST_DIRTY; -+ - return USER_TEST_EXISTS; -+ } -+ - if (S_ISBLK(st.st_mode)) { - /* For block devices we can't really be sure if the device referenced actually is the - * fs we look for or some other file system (think: what does /dev/sdb1 refer -@@ -544,7 +566,7 @@ int user_record_test_image_path_and_warn(UserRecord *h) { - return r; - } - --int user_record_test_secret(UserRecord *h, UserRecord *secret) { -+int user_record_test_password(UserRecord *h, UserRecord *secret) { - char **i; - int r; - -@@ -566,6 +588,48 @@ int user_record_test_secret(UserRecord *h, UserRecord *secret) { - return -ENOKEY; - } - -+int user_record_test_recovery_key(UserRecord *h, UserRecord *secret) { -+ char **i; -+ int r; -+ -+ assert(h); -+ -+ /* Checks whether any of the specified passwords matches any of the hashed recovery keys of the entry */ -+ -+ if (h->n_recovery_key == 0) -+ return -ENXIO; -+ -+ STRV_FOREACH(i, secret->password) { -+ for (size_t j = 0; j < h->n_recovery_key; j++) { -+ _cleanup_(erase_and_freep) char *mangled = NULL; -+ const char *p; -+ -+ if (streq(h->recovery_key[j].type, "modhex64")) { -+ /* If this key is for a modhex64 recovery key, then try to normalize the -+ * passphrase to make things more robust: that way the password becomes case -+ * insensitive and the dashes become optional. */ -+ -+ r = normalize_recovery_key(*i, &mangled); -+ if (r == -EINVAL) /* Not a valid modhex64 passphrase, don't bother */ -+ continue; -+ if (r < 0) -+ return r; -+ -+ p = mangled; -+ } else -+ p = *i; /* Unknown recovery key types process as is */ -+ -+ r = test_password_one(h->recovery_key[j].hashed_password, p); -+ if (r < 0) -+ return r; -+ if (r > 0) -+ return 0; -+ } -+ } -+ -+ return -ENOKEY; -+} -+ - int user_record_set_disk_size(UserRecord *h, uint64_t disk_size) { - _cleanup_(json_variant_unrefp) JsonVariant *new_per_machine = NULL, *midv = NULL, *midav = NULL, *ne = NULL; - _cleanup_free_ JsonVariant **array = NULL; -diff --git a/src/home/user-record-util.h b/src/home/user-record-util.h -index 2458298..f8bae70 100644 ---- a/src/home/user-record-util.h -+++ b/src/home/user-record-util.h -@@ -31,6 +31,7 @@ enum { - USER_TEST_UNDEFINED, /* Returned by user_record_test_image_path() if the storage type knows no image paths */ - USER_TEST_ABSENT, - USER_TEST_EXISTS, -+ USER_TEST_DIRTY, /* Only applies to user_record_test_image_path(), when the image exists but is marked dirty */ - USER_TEST_MOUNTED, /* Only applies to user_record_test_home_directory(), when the home directory exists. */ - USER_TEST_MAYBE, /* Only applies to LUKS devices: block device exists, but we don't know if it's the right one */ - }; -@@ -40,7 +41,8 @@ int user_record_test_home_directory_and_warn(UserRecord *h); - int user_record_test_image_path(UserRecord *h); - int user_record_test_image_path_and_warn(UserRecord *h); - --int user_record_test_secret(UserRecord *h, UserRecord *secret); -+int user_record_test_password(UserRecord *h, UserRecord *secret); -+int user_record_test_recovery_key(UserRecord *h, UserRecord *secret); - - int user_record_update_last_changed(UserRecord *h, bool with_password); - int user_record_set_disk_size(UserRecord *h, uint64_t disk_size); -diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c -index 2d6b2da..c6d8b8d 100644 ---- a/src/hostname/hostnamectl.c -+++ b/src/hostname/hostnamectl.c -@@ -229,7 +229,7 @@ static int set_simple_string(sd_bus *bus, const char *method, const char *value) - &error, NULL, - "sb", value, arg_ask_password); - if (r < 0) -- return log_error_errno(r, "Could not set property: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not set property: %s", bus_error_message(&error, r)); - - return 0; - } -diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c -index 7f6607a..44c2b9a 100644 ---- a/src/hostname/hostnamed.c -+++ b/src/hostname/hostnamed.c -@@ -189,19 +189,25 @@ static const char* fallback_chassis(void) { - int v, r; - - v = detect_virtualization(); -- if (VIRTUALIZATION_IS_VM(v)) -+ if (v < 0) -+ log_debug_errno(v, "Failed to detect virtualization, ignoring: %m"); -+ else if (VIRTUALIZATION_IS_VM(v)) - return "vm"; -- if (VIRTUALIZATION_IS_CONTAINER(v)) -+ else if (VIRTUALIZATION_IS_CONTAINER(v)) - return "container"; - - r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type); -- if (r < 0) -+ if (r < 0) { -+ log_debug_errno(v, "Failed to read DMI chassis type, ignoring: %m"); - goto try_acpi; -+ } - - r = safe_atou(type, &t); - free(type); -- if (r < 0) -+ if (r < 0) { -+ log_debug_errno(v, "Failed to parse DMI chassis type, ignoring: %m"); - goto try_acpi; -+ } - - /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any - additional guesswork on top of that. -@@ -217,6 +223,7 @@ static const char* fallback_chassis(void) { - case 0x4: /* Low Profile Desktop */ - case 0x6: /* Mini Tower */ - case 0x7: /* Tower */ -+ case 0xD: /* All in one (i.e. PC built into monitor) */ - return "desktop"; - - case 0x8: /* Portable */ -@@ -239,17 +246,24 @@ static const char* fallback_chassis(void) { - case 0x1F: /* Convertible */ - case 0x20: /* Detachable */ - return "convertible"; -+ -+ default: -+ log_debug("Unhandled DMI chassis type 0x%02x, ignoring.", t); - } - - try_acpi: - r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type); -- if (r < 0) -+ if (r < 0) { -+ log_debug_errno(v, "Failed read ACPI PM profile, ignoring: %m"); - return NULL; -+ } - - r = safe_atou(type, &t); - free(type); -- if (r < 0) -+ if (r < 0) { -+ log_debug_errno(v, "Failed parse ACPI PM profile, ignoring: %m"); - return NULL; -+ } - - /* We only list the really obvious cases here as the ACPI data is not really super reliable. - * -@@ -275,6 +289,9 @@ try_acpi: - - case 8: /* Tablet */ - return "tablet"; -+ -+ default: -+ log_debug("Unhandled ACPI PM profile 0x%02x, ignoring.", t); - } - - return NULL; -@@ -910,13 +927,13 @@ static const BusObjectImplementation manager_object = { - .vtables = BUS_VTABLES(hostname_vtable), - }; - --static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { -+static int connect_bus(Context *c, sd_event *event, sd_bus **ret) { - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - int r; - - assert(c); - assert(event); -- assert(_bus); -+ assert(ret); - - r = sd_bus_default_system(&bus); - if (r < 0) -@@ -938,8 +955,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { - if (r < 0) - return log_error_errno(r, "Failed to attach bus to event loop: %m"); - -- *_bus = TAKE_PTR(bus); -- -+ *ret = TAKE_PTR(bus); - return 0; - } - -diff --git a/src/import/curl-util.c b/src/import/curl-util.c -index 261fbec..a1b3147 100644 ---- a/src/import/curl-util.c -+++ b/src/import/curl-util.c -@@ -139,16 +139,16 @@ static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata - return 0; - } - -- usec = now(clock_boottime_or_monotonic()) + (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1; -+ usec = (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1; - - if (g->timer) { -- if (sd_event_source_set_time(g->timer, usec) < 0) -+ if (sd_event_source_set_time_relative(g->timer, usec) < 0) - return -1; - - if (sd_event_source_set_enabled(g->timer, SD_EVENT_ONESHOT) < 0) - return -1; - } else { -- if (sd_event_add_time(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0) -+ if (sd_event_add_time_relative(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0) - return -1; - - (void) sd_event_source_set_description(g->timer, "curl-timer"); -diff --git a/src/import/import-common.c b/src/import/import-common.c -index ca96f07..ebd7472 100644 ---- a/src/import/import-common.c -+++ b/src/import/import-common.c -@@ -81,6 +81,7 @@ int import_fork_tar_x(const char *path, pid_t *ret) { - if (r == 0) { - const char *cmdline[] = { - "tar", -+ "--ignore-zeros", - "--numeric-owner", - "-C", path, - "-px", -diff --git a/src/import/importd.c b/src/import/importd.c -index 038dd3a..17944b8 100644 ---- a/src/import/importd.c -+++ b/src/import/importd.c -@@ -562,7 +562,6 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void - Manager *m = userdata; - char *p, *e; - Transfer *t; -- Iterator i; - ssize_t n; - int r; - -@@ -585,7 +584,7 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void - return 0; - } - -- HASHMAP_FOREACH(t, m->transfers, i) -+ HASHMAP_FOREACH(t, m->transfers) - if (ucred->pid == t->pid) - break; - -@@ -670,13 +669,12 @@ static int manager_new(Manager **ret) { - - static Transfer *manager_find(Manager *m, TransferType type, const char *remote) { - Transfer *t; -- Iterator i; - - assert(m); - assert(type >= 0); - assert(type < _TRANSFER_TYPE_MAX); - -- HASHMAP_FOREACH(t, m->transfers, i) -+ HASHMAP_FOREACH(t, m->transfers) - if (t->type == type && streq_ptr(t->remote, remote)) - return t; - -@@ -990,7 +988,6 @@ static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_err - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; - Transfer *t; -- Iterator i; - int r; - - assert(msg); -@@ -1004,7 +1001,7 @@ static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_err - if (r < 0) - return r; - -- HASHMAP_FOREACH(t, m->transfers, i) { -+ HASHMAP_FOREACH(t, m->transfers) { - - r = sd_bus_message_append( - reply, -@@ -1162,13 +1159,12 @@ static int transfer_node_enumerator( - Manager *m = userdata; - Transfer *t; - unsigned k = 0; -- Iterator i; - - l = new0(char*, hashmap_size(m->transfers) + 1); - if (!l) - return -ENOMEM; - -- HASHMAP_FOREACH(t, m->transfers, i) { -+ HASHMAP_FOREACH(t, m->transfers) { - - l[k] = strdup(t->object_path); - if (!l[k]) -diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c -index 7eee197..050424e 100644 ---- a/src/initctl/initctl.c -+++ b/src/initctl/initctl.c -@@ -115,7 +115,7 @@ static int change_runlevel(Server *s, int runlevel) { - NULL, - "ss", target, mode); - if (r < 0) -- return log_error_errno(r, "Failed to change runlevel: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to change runlevel: %s", bus_error_message(&error, r)); - - return 0; - } -diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c -index 77dfdef..0e028a9 100644 ---- a/src/journal-remote/journal-remote-main.c -+++ b/src/journal-remote/journal-remote-main.c -@@ -124,7 +124,7 @@ static int spawn_getter(const char *getter) { - _cleanup_strv_free_ char **words = NULL; - - assert(getter); -- r = strv_split_extract(&words, getter, WHITESPACE, EXTRACT_UNQUOTE); -+ r = strv_split_full(&words, getter, WHITESPACE, EXTRACT_UNQUOTE); - if (r < 0) - return log_error_errno(r, "Failed to split getter option: %m"); - -diff --git a/src/journal/catalog.c b/src/journal/catalog.c -index b258927..b0416da 100644 ---- a/src/journal/catalog.c -+++ b/src/journal/catalog.c -@@ -450,7 +450,6 @@ int catalog_update(const char* database, const char* root, const char* const* di - ssize_t offset; - char *payload; - CatalogItem *i; -- Iterator j; - unsigned n; - int r; - int64_t sz; -@@ -482,7 +481,7 @@ int catalog_update(const char* database, const char* root, const char* const* di - return log_oom(); - - n = 0; -- ORDERED_HASHMAP_FOREACH_KEY(payload, i, h, j) { -+ ORDERED_HASHMAP_FOREACH_KEY(payload, i, h) { - log_debug("Found " SD_ID128_FORMAT_STR ", language %s", - SD_ID128_FORMAT_VAL(i->id), - isempty(i->language) ? "C" : i->language); -diff --git a/src/journal/compress.c b/src/journal/compress.c -index a59c2b7..852f9e0 100644 ---- a/src/journal/compress.c -+++ b/src/journal/compress.c -@@ -927,11 +927,12 @@ int compress_stream_zstd(int fdf, int fdt, uint64_t max_bytes) { - break; - } - -- log_debug( -- "ZSTD compression finished (%" PRIu64 " -> %" PRIu64 " bytes, %.1f%%)", -- in_bytes, -- max_bytes - left, -- (double) (max_bytes - left) / in_bytes * 100); -+ if (in_bytes > 0) -+ log_debug("ZSTD compression finished (%" PRIu64 " -> %" PRIu64 " bytes, %.1f%%)", -+ in_bytes, max_bytes - left, (double) (max_bytes - left) / in_bytes * 100); -+ else -+ log_debug("ZSTD compression finished (%" PRIu64 " -> %" PRIu64 " bytes)", -+ in_bytes, max_bytes - left); - - return 0; - #else -diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c -index cdcded2..feff3bd 100644 ---- a/src/journal/journal-file.c -+++ b/src/journal/journal-file.c -@@ -1978,7 +1978,6 @@ static int post_change_thunk(sd_event_source *timer, uint64_t usec, void *userda - } - - static void schedule_post_change(JournalFile *f) { -- uint64_t now; - int r; - - assert(f); -@@ -1992,13 +1991,7 @@ static void schedule_post_change(JournalFile *f) { - if (r > 0) - return; - -- r = sd_event_now(sd_event_source_get_event(f->post_change_timer), CLOCK_MONOTONIC, &now); -- if (r < 0) { -- log_debug_errno(r, "Failed to get clock's now for scheduling ftruncate: %m"); -- goto fail; -- } -- -- r = sd_event_source_set_time(f->post_change_timer, now + f->post_change_timer_period); -+ r = sd_event_source_set_time_relative(f->post_change_timer, f->post_change_timer_period); - if (r < 0) { - log_debug_errno(r, "Failed to set time for scheduling ftruncate: %m"); - goto fail; -diff --git a/src/journal/journal-qrcode.c b/src/journal/journal-qrcode.c -index 678654f..e8a7655 100644 ---- a/src/journal/journal-qrcode.c -+++ b/src/journal/journal-qrcode.c -@@ -6,29 +6,19 @@ - #include - #include - -+#include "alloc-util.h" -+#include "dlfcn-util.h" -+#include "fd-util.h" - #include "fileio.h" - #include "journal-qrcode.h" -+#include "locale-util.h" - #include "macro.h" -- --#define WHITE_ON_BLACK "\033[40;37;1m" --#define NORMAL "\033[0m" -- --static void print_border(FILE *output, unsigned width) { -- unsigned x, y; -- -- /* Four rows of border */ -- for (y = 0; y < 4; y += 2) { -- fputs(WHITE_ON_BLACK, output); -- -- for (x = 0; x < 4 + width + 4; x++) -- fputs("\342\226\210", output); -- -- fputs(NORMAL "\n", output); -- } --} -+#include "qrcode-util.h" -+#include "terminal-util.h" - - int print_qr_code( - FILE *output, -+ const char *prefix_text, - const void *seed, - size_t seed_size, - uint64_t start, -@@ -36,22 +26,44 @@ int print_qr_code( - const char *hn, - sd_id128_t machine) { - -- FILE *f; -- char *url = NULL; -- size_t url_size = 0, i; -+ QRcode* (*sym_QRcode_encodeString)(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); -+ void (*sym_QRcode_free)(QRcode *qrcode); -+ _cleanup_(dlclosep) void *dl = NULL; -+ _cleanup_free_ char *url = NULL; -+ _cleanup_fclose_ FILE *f = NULL; -+ size_t url_size = 0; - QRcode* qr; -- unsigned x, y; -+ int r; - - assert(seed); - assert(seed_size > 0); - -+ /* If this is not an UTF-8 system or ANSI colors aren't supported/disabled don't print any QR -+ * codes */ -+ if (!is_locale_utf8() || !colors_enabled()) -+ return -EOPNOTSUPP; -+ -+ dl = dlopen("libqrencode.so.4", RTLD_LAZY); -+ if (!dl) -+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), -+ "QRCODE support is not installed: %s", dlerror()); -+ -+ r = dlsym_many_and_warn( -+ dl, -+ LOG_DEBUG, -+ &sym_QRcode_encodeString, "QRcode_encodeString", -+ &sym_QRcode_free, "QRcode_free", -+ NULL); -+ if (r < 0) -+ return r; -+ - f = open_memstream_unlocked(&url, &url_size); - if (!f) - return -ENOMEM; - - fputs("fss://", f); - -- for (i = 0; i < seed_size; i++) { -+ for (size_t i = 0; i < seed_size; i++) { - if (i > 0 && i % 3 == 0) - fputc('-', f); - fprintf(f, "%02x", ((uint8_t*) seed)[i]); -@@ -65,55 +77,21 @@ int print_qr_code( - if (hn) - fprintf(f, ";hostname=%s", hn); - -- if (ferror(f)) { -- fclose(f); -- free(url); -- return -ENOMEM; -- } -+ r = fflush_and_check(f); -+ if (r < 0) -+ return r; - -- fclose(f); -- -- qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1); -- free(url); -+ f = safe_fclose(f); - -+ qr = sym_QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1); - if (!qr) - return -ENOMEM; - -- print_border(output, qr->width); -- -- for (y = 0; y < (unsigned) qr->width; y += 2) { -- const uint8_t *row1, *row2; -- -- row1 = qr->data + qr->width * y; -- row2 = row1 + qr->width; -- -- fputs(WHITE_ON_BLACK, output); -- for (x = 0; x < 4; x++) -- fputs("\342\226\210", output); -- -- for (x = 0; x < (unsigned) qr->width; x ++) { -- bool a, b; -- -- a = row1[x] & 1; -- b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false; -- -- if (a && b) -- fputc(' ', output); -- else if (a) -- fputs("\342\226\204", output); -- else if (b) -- fputs("\342\226\200", output); -- else -- fputs("\342\226\210", output); -- } -- -- for (x = 0; x < 4; x++) -- fputs("\342\226\210", output); -- fputs(NORMAL "\n", output); -- } -+ if (prefix_text) -+ fputs(prefix_text, output); - -- print_border(output, qr->width); -+ write_qrcode(output, qr); - -- QRcode_free(qr); -+ sym_QRcode_free(qr); - return 0; - } -diff --git a/src/journal/journal-qrcode.h b/src/journal/journal-qrcode.h -index 0774608..24ae9d3 100644 ---- a/src/journal/journal-qrcode.h -+++ b/src/journal/journal-qrcode.h -@@ -6,4 +6,4 @@ - - #include "sd-id128.h" - --int print_qr_code(FILE *f, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine); -+int print_qr_code(FILE *f, const char *prefix_text, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine); -diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c -index 8d4897b..52e204e 100644 ---- a/src/journal/journalctl.c -+++ b/src/journal/journalctl.c -@@ -31,6 +31,7 @@ - #include "chattr-util.h" - #include "def.h" - #include "device-private.h" -+#include "dissect-image.h" - #include "fd-util.h" - #include "fileio.h" - #include "format-util.h" -@@ -51,18 +52,21 @@ - #include "logs-show.h" - #include "memory-util.h" - #include "mkdir.h" -+#include "mount-util.h" - #include "mountpoint-util.h" - #include "nulstr-util.h" - #include "pager.h" - #include "parse-util.h" - #include "path-util.h" -+#include "pcre2-dlopen.h" - #include "pretty-print.h" -+#include "random-util.h" - #include "rlimit-util.h" - #include "set.h" - #include "sigbus.h" -+#include "stdio-util.h" - #include "string-table.h" - #include "strv.h" --#include "stdio-util.h" - #include "syslog-util.h" - #include "terminal-util.h" - #include "tmpfile-util.h" -@@ -119,6 +123,7 @@ static bool arg_reverse = false; - static int arg_journal_type = 0; - static int arg_namespace_flags = 0; - static char *arg_root = NULL; -+static char *arg_image = NULL; - static const char *arg_machine = NULL; - static const char *arg_namespace = NULL; - static uint64_t arg_vacuum_size = 0; -@@ -160,20 +165,20 @@ typedef struct BootId { - } BootId; - - #if HAVE_PCRE2 --DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, pcre2_match_data_free); --DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, pcre2_code_free); -+DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, sym_pcre2_match_data_free); -+DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, sym_pcre2_code_free); - - static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) { - int errorcode, r; - PCRE2_SIZE erroroffset; - pcre2_code *p; - -- p = pcre2_compile((PCRE2_SPTR8) pattern, -- PCRE2_ZERO_TERMINATED, flags, &errorcode, &erroroffset, NULL); -+ p = sym_pcre2_compile((PCRE2_SPTR8) pattern, -+ PCRE2_ZERO_TERMINATED, flags, &errorcode, &erroroffset, NULL); - if (!p) { - unsigned char buf[LINE_MAX]; - -- r = pcre2_get_error_message(errorcode, buf, sizeof buf); -+ r = sym_pcre2_get_error_message(errorcode, buf, sizeof buf); - - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Bad pattern \"%s\": %s", pattern, -@@ -183,7 +188,6 @@ static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out - *out = p; - return 0; - } -- - #endif - - static int add_matches_for_device(sd_journal *j, const char *devpath) { -@@ -261,7 +265,7 @@ get_parent: - static char *format_timestamp_maybe_utc(char *buf, size_t l, usec_t t) { - - if (arg_utc) -- return format_timestamp_utc(buf, l, t); -+ return format_timestamp_style(buf, l, t, TIMESTAMP_UTC); - - return format_timestamp(buf, l, t); - } -@@ -374,6 +378,7 @@ static int help(void) { - " -D --directory=PATH Show journal files from directory\n" - " --file=PATH Show journal file\n" - " --root=ROOT Operate on files below a root directory\n" -+ " --image=IMAGE Operate on files in filesystem image\n" - " --namespace=NAMESPACE Show journal data from specified namespace\n" - " --interval=TIME Time interval for changing the FSS sealing key\n" - " --verify-key=KEY Specify FSS verification key\n" -@@ -421,6 +426,7 @@ static int parse_argv(int argc, char *argv[]) { - ARG_USER, - ARG_SYSTEM, - ARG_ROOT, -+ ARG_IMAGE, - ARG_HEADER, - ARG_FACILITY, - ARG_SETUP_KEYS, -@@ -477,6 +483,7 @@ static int parse_argv(int argc, char *argv[]) { - { "directory", required_argument, NULL, 'D' }, - { "file", required_argument, NULL, ARG_FILE }, - { "root", required_argument, NULL, ARG_ROOT }, -+ { "image", required_argument, NULL, ARG_IMAGE }, - { "header", no_argument, NULL, ARG_HEADER }, - { "identifier", required_argument, NULL, 't' }, - { "priority", required_argument, NULL, 'p' }, -@@ -712,7 +719,13 @@ static int parse_argv(int argc, char *argv[]) { - break; - - case ARG_ROOT: -- r = parse_path_argument_and_warn(optarg, true, &arg_root); -+ r = parse_path_argument_and_warn(optarg, /* suppress_root= */ true, &arg_root); -+ if (r < 0) -+ return r; -+ break; -+ -+ case ARG_IMAGE: -+ r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_image); - if (r < 0) - return r; - break; -@@ -1042,8 +1055,8 @@ static int parse_argv(int argc, char *argv[]) { - if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT) - arg_lines = 10; - -- if (!!arg_directory + !!arg_file + !!arg_machine + !!arg_root > 1) { -- log_error("Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root."); -+ if (!!arg_directory + !!arg_file + !!arg_machine + !!arg_root + !!arg_image > 1) { -+ log_error("Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root=, --image=."); - return -EINVAL; - } - -@@ -1087,14 +1100,18 @@ static int parse_argv(int argc, char *argv[]) { - if (arg_pattern) { - unsigned flags; - -+ r = dlopen_pcre2(); -+ if (r < 0) -+ return r; -+ - if (arg_case_sensitive >= 0) - flags = !arg_case_sensitive * PCRE2_CASELESS; - else { -- _cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL; -+ _cleanup_(sym_pcre2_match_data_freep) pcre2_match_data *md = NULL; - bool has_case; -- _cleanup_(pcre2_code_freep) pcre2_code *cs = NULL; -+ _cleanup_(sym_pcre2_code_freep) pcre2_code *cs = NULL; - -- md = pcre2_match_data_create(1, NULL); -+ md = sym_pcre2_match_data_create(1, NULL); - if (!md) - return log_oom(); - -@@ -1102,7 +1119,7 @@ static int parse_argv(int argc, char *argv[]) { - if (r < 0) - return r; - -- r = pcre2_match(cs, (PCRE2_SPTR8) arg_pattern, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL); -+ r = sym_pcre2_match(cs, (PCRE2_SPTR8) arg_pattern, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL); - has_case = r >= 0; - - flags = !has_case * PCRE2_CASELESS; -@@ -1627,14 +1644,13 @@ static int add_units(sd_journal *j) { - - if (!strv_isempty(patterns)) { - _cleanup_set_free_free_ Set *units = NULL; -- Iterator it; - char *u; - - r = get_possible_units(j, SYSTEM_UNITS, patterns, &units); - if (r < 0) - return r; - -- SET_FOREACH(u, units, it) { -+ SET_FOREACH(u, units) { - r = add_matches_for_unit(j, u); - if (r < 0) - return r; -@@ -1672,14 +1688,13 @@ static int add_units(sd_journal *j) { - - if (!strv_isempty(patterns)) { - _cleanup_set_free_free_ Set *units = NULL; -- Iterator it; - char *u; - - r = get_possible_units(j, USER_UNITS, patterns, &units); - if (r < 0) - return r; - -- SET_FOREACH(u, units, it) { -+ SET_FOREACH(u, units) { - r = add_matches_for_user_unit(j, u, getuid()); - if (r < 0) - return r; -@@ -1728,10 +1743,9 @@ static int add_priorities(sd_journal *j) { - - static int add_facilities(sd_journal *j) { - void *p; -- Iterator it; - int r; - -- SET_FOREACH(p, arg_facilities, it) { -+ SET_FOREACH(p, arg_facilities) { - char match[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)]; - - xsprintf(match, "SYSLOG_FACILITY=%d", PTR_TO_INT(p)); -@@ -1773,13 +1787,15 @@ static int add_syslog_identifier(sd_journal *j) { - - static int setup_keys(void) { - #if HAVE_GCRYPT -- size_t mpk_size, seed_size, state_size, i; -+ size_t mpk_size, seed_size, state_size; -+ _cleanup_(unlink_and_freep) char *k = NULL; -+ _cleanup_free_ char *p = NULL; - uint8_t *mpk, *seed, *state; -- int fd = -1, r; -+ _cleanup_close_ int fd = -1; - sd_id128_t machine, boot; -- char *p = NULL, *k = NULL; -- uint64_t n; - struct stat st; -+ uint64_t n; -+ int r; - - r = stat("/var/log/journal", &st); - if (r < 0 && !IN_SET(errno, ENOENT, ENOTDIR)) -@@ -1805,21 +1821,15 @@ static int setup_keys(void) { - - if (arg_force) { - r = unlink(p); -- if (r < 0 && errno != ENOENT) { -- r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p); -- goto finish; -- } -- } else if (access(p, F_OK) >= 0) { -- log_error("Sealing key file %s exists already. Use --force to recreate.", p); -- r = -EEXIST; -- goto finish; -- } -+ if (r < 0 && errno != ENOENT) -+ return log_error_errno(errno, "unlink(\"%s\") failed: %m", p); -+ } else if (access(p, F_OK) >= 0) -+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST), -+ "Sealing key file %s exists already. Use --force to recreate.", p); - - if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX", -- SD_ID128_FORMAT_VAL(machine)) < 0) { -- r = log_oom(); -- goto finish; -- } -+ SD_ID128_FORMAT_VAL(machine)) < 0) -+ return log_oom(); - - mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR); - mpk = alloca(mpk_size); -@@ -1830,18 +1840,10 @@ static int setup_keys(void) { - state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR); - state = alloca(state_size); - -- fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY); -- if (fd < 0) { -- r = log_error_errno(errno, "Failed to open /dev/random: %m"); -- goto finish; -- } -- - log_info("Generating seed..."); -- r = loop_read_exact(fd, seed, seed_size, true); -- if (r < 0) { -- log_error_errno(r, "Failed to read random seed: %m"); -- goto finish; -- } -+ r = genuine_random_bytes(seed, seed_size, RANDOM_BLOCK); -+ if (r < 0) -+ return log_error_errno(r, "Failed to acquire random seed: %m"); - - log_info("Generating key pair..."); - FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR); -@@ -1856,18 +1858,25 @@ static int setup_keys(void) { - - safe_close(fd); - fd = mkostemp_safe(k); -- if (fd < 0) { -- r = log_error_errno(fd, "Failed to open %s: %m", k); -- goto finish; -+ if (fd < 0) -+ return log_error_errno(fd, "Failed to open %s: %m", k); -+ -+ /* Enable secure remove, exclusion from dump, synchronous writing and in-place updating */ -+ static const unsigned chattr_flags[] = { -+ FS_SECRM_FL, -+ FS_NODUMP_FL, -+ FS_SYNC_FL, -+ FS_NOCOW_FL, -+ }; -+ for (size_t j = 0; j < ELEMENTSOF(chattr_flags); j++) { -+ r = chattr_fd(fd, chattr_flags[j], chattr_flags[j], NULL); -+ if (r < 0) -+ log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) ? LOG_DEBUG : LOG_WARNING, r, -+ "Failed to set file attribute 0x%x: %m", chattr_flags[j]); - } - -- /* Enable secure remove, exclusion from dump, synchronous -- * writing and in-place updating */ -- r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, NULL); -- if (r < 0) -- log_warning_errno(r, "Failed to set file attributes: %m"); -- - struct FSSHeader h = { -+ .signature = { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' }, - .machine_id = machine, - .boot_id = boot, - .header_size = htole64(sizeof(h)), -@@ -1877,91 +1886,69 @@ static int setup_keys(void) { - .fsprg_state_size = htole64(state_size), - }; - -- memcpy(h.signature, "KSHHRHLP", 8); -- - r = loop_write(fd, &h, sizeof(h), false); -- if (r < 0) { -- log_error_errno(r, "Failed to write header: %m"); -- goto finish; -- } -+ if (r < 0) -+ return log_error_errno(r, "Failed to write header: %m"); - - r = loop_write(fd, state, state_size, false); -- if (r < 0) { -- log_error_errno(r, "Failed to write state: %m"); -- goto finish; -- } -+ if (r < 0) -+ return log_error_errno(r, "Failed to write state: %m"); - -- if (link(k, p) < 0) { -- r = log_error_errno(errno, "Failed to link file: %m"); -- goto finish; -- } -+ if (rename(k, p) < 0) -+ return log_error_errno(errno, "Failed to link file: %m"); -+ -+ k = mfree(k); -+ -+ _cleanup_free_ char *hn = NULL; - - if (on_tty()) { -+ hn = gethostname_malloc(); -+ if (hn) -+ hostname_cleanup(hn); -+ -+ char tsb[FORMAT_TIMESPAN_MAX]; - fprintf(stderr, -+ "\nNew keys have been generated for host %s%s" SD_ID128_FORMAT_STR ".\n" - "\n" -- "The new key pair has been generated. The %ssecret sealing key%s has been written to\n" -- "the following local file. This key file is automatically updated when the\n" -- "sealing key is advanced. It should not be used on multiple hosts.\n" -+ "The %ssecret sealing key%s has been written to the following local file.\n" -+ "This key file is automatically updated when the sealing key is advanced.\n" -+ "It should not be used on multiple hosts.\n" - "\n" - "\t%s\n" - "\n" -+ "The sealing key is automatically changed every %s.\n" -+ "\n" - "Please write down the following %ssecret verification key%s. It should be stored\n" -- "at a safe location and should not be saved locally on disk.\n" -+ "in a safe location and should not be saved locally on disk.\n" - "\n\t%s", -+ hn ?: "", hn ? "/" : "", SD_ID128_FORMAT_VAL(machine), - ansi_highlight(), ansi_normal(), - p, -+ format_timespan(tsb, sizeof(tsb), arg_interval, 0), - ansi_highlight(), ansi_normal(), - ansi_highlight_red()); - fflush(stderr); - } -- for (i = 0; i < seed_size; i++) { -+ -+ for (size_t i = 0; i < seed_size; i++) { - if (i > 0 && i % 3 == 0) - putchar('-'); - printf("%02x", ((uint8_t*) seed)[i]); - } -- - printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval); - - if (on_tty()) { -- char tsb[FORMAT_TIMESPAN_MAX], *hn; -- -- fprintf(stderr, -- "%s\n" -- "The sealing key is automatically changed every %s.\n", -- ansi_normal(), -- format_timespan(tsb, sizeof(tsb), arg_interval, 0)); -- -- hn = gethostname_malloc(); -- -- if (hn) { -- hostname_cleanup(hn); -- fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine)); -- } else -- fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine)); -- -+ fprintf(stderr, "%s", ansi_normal()); - #if HAVE_QRENCODE -- /* If this is not an UTF-8 system don't print any QR codes */ -- if (is_locale_utf8()) { -- fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr); -- print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); -- } -+ (void) print_qr_code(stderr, -+ "\nTo transfer the verification key to your phone scan the QR code below:\n", -+ seed, seed_size, -+ n, arg_interval, -+ hn, machine); - #endif -- free(hn); -- } -- -- r = 0; -- --finish: -- safe_close(fd); -- -- if (k) { -- (void) unlink(k); -- free(k); - } - -- free(p); -- -- return r; -+ return 0; - #else - return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "Forward-secure sealing not available."); -@@ -1970,14 +1957,13 @@ finish: - - static int verify(sd_journal *j) { - int r = 0; -- Iterator i; - JournalFile *f; - - assert(j); - - log_show_color(true); - -- ORDERED_HASHMAP_FOREACH(f, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(f, j->files) { - int k; - usec_t first = 0, validated = 0, last = 0; - -@@ -2103,6 +2089,9 @@ static int wait_for_change(sd_journal *j, int poll_fd) { - } - - int main(int argc, char *argv[]) { -+ _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; -+ _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL; -+ _cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL; - bool previous_boot_id_valid = false, first_line = true, ellipsized = false, need_seek = false; - bool use_cursor = false, after_cursor = false; - _cleanup_(sd_journal_closep) sd_journal *j = NULL; -@@ -2120,6 +2109,24 @@ int main(int argc, char *argv[]) { - if (r <= 0) - goto finish; - -+ if (arg_image) { -+ assert(!arg_root); -+ -+ r = mount_image_privately_interactively( -+ arg_image, -+ DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK| -+ (arg_action == ACTION_UPDATE_CATALOG ? DISSECT_IMAGE_FSCK : DISSECT_IMAGE_READ_ONLY), -+ &unlink_dir, -+ &loop_device, -+ &decrypted_image); -+ if (r < 0) -+ return r; -+ -+ arg_root = strdup(unlink_dir); -+ if (!arg_root) -+ return log_oom(); -+ } -+ - signal(SIGWINCH, columns_lines_cache_reset); - sigbus_install(); - -@@ -2316,9 +2323,8 @@ int main(int argc, char *argv[]) { - - case ACTION_VACUUM: { - Directory *d; -- Iterator i; - -- HASHMAP_FOREACH(d, j->directories_by_path, i) { -+ HASHMAP_FOREACH(d, j->directories_by_path) { - int q; - - q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_n_files, arg_vacuum_time, NULL, !arg_quiet); -@@ -2562,10 +2568,10 @@ int main(int argc, char *argv[]) { - - if (r > 0) { - if (arg_follow) -- printf("-- Logs begin at %s. --\n", -+ printf("-- Journal begins at %s. --\n", - format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start)); - else -- printf("-- Logs begin at %s, end at %s. --\n", -+ printf("-- Journal begins at %s, ends at %s. --\n", - format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start), - format_timestamp_maybe_utc(end_buf, sizeof(end_buf), end)); - } -@@ -2630,12 +2636,12 @@ int main(int argc, char *argv[]) { - - #if HAVE_PCRE2 - if (arg_compiled_pattern) { -- _cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL; -+ _cleanup_(sym_pcre2_match_data_freep) pcre2_match_data *md = NULL; - const void *message; - size_t len; - PCRE2_SIZE *ovec; - -- md = pcre2_match_data_create(1, NULL); -+ md = sym_pcre2_match_data_create(1, NULL); - if (!md) - return log_oom(); - -@@ -2652,13 +2658,13 @@ int main(int argc, char *argv[]) { - - assert_se(message = startswith(message, "MESSAGE=")); - -- r = pcre2_match(arg_compiled_pattern, -- message, -- len - strlen("MESSAGE="), -- 0, /* start at offset 0 in the subject */ -- 0, /* default options */ -- md, -- NULL); -+ r = sym_pcre2_match(arg_compiled_pattern, -+ message, -+ len - strlen("MESSAGE="), -+ 0, /* start at offset 0 in the subject */ -+ 0, /* default options */ -+ md, -+ NULL); - if (r == PCRE2_ERROR_NOMATCH) { - need_seek = true; - continue; -@@ -2667,14 +2673,14 @@ int main(int argc, char *argv[]) { - unsigned char buf[LINE_MAX]; - int r2; - -- r2 = pcre2_get_error_message(r, buf, sizeof buf); -+ r2 = sym_pcre2_get_error_message(r, buf, sizeof buf); - log_error("Pattern matching failed: %s", - r2 < 0 ? "unknown error" : (char*) buf); - r = -EINVAL; - goto finish; - } - -- ovec = pcre2_get_ovector_pointer(md); -+ ovec = sym_pcre2_get_ovector_pointer(md); - highlight[0] = ovec[0]; - highlight[1] = ovec[1]; - } -@@ -2766,7 +2772,7 @@ finish: - - #if HAVE_PCRE2 - if (arg_compiled_pattern) { -- pcre2_code_free(arg_compiled_pattern); -+ sym_pcre2_code_free(arg_compiled_pattern); - - /* --grep was used, no error was thrown, but the pattern didn't - * match anything. Let's mimic grep's behavior here and return -diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c -index 5865bf9..34ba24d 100644 ---- a/src/journal/journald-server.c -+++ b/src/journal/journald-server.c -@@ -247,16 +247,15 @@ static bool uid_for_system_journal(uid_t uid) { - } - - static void server_add_acls(JournalFile *f, uid_t uid) { --#if HAVE_ACL -- int r; --#endif - assert(f); - - #if HAVE_ACL -+ int r; -+ - if (uid_for_system_journal(uid)) - return; - -- r = add_acls_for_user(f->fd, uid); -+ r = fd_add_uid_acl_permission(f->fd, uid, ACL_READ); - if (r < 0) - log_warning_errno(r, "Failed to set ACL on %s, ignoring: %m", f->path); - #endif -@@ -474,10 +473,9 @@ static int do_rotate( - - static void server_process_deferred_closes(Server *s) { - JournalFile *f; -- Iterator i; - - /* Perform any deferred closes which aren't still offlining. */ -- SET_FOREACH(f, s->deferred_closes, i) { -+ SET_FOREACH(f, s->deferred_closes) { - if (journal_file_is_offlining(f)) - continue; - -@@ -610,7 +608,6 @@ static int vacuum_offline_user_journals(Server *s) { - - void server_rotate(Server *s) { - JournalFile *f; -- Iterator i; - void *k; - int r; - -@@ -621,7 +618,7 @@ void server_rotate(Server *s) { - (void) do_rotate(s, &s->system_journal, "system", s->seal, 0); - - /* Then, rotate all user journals we have open (keeping them open) */ -- ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) { -+ ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals) { - r = do_rotate(s, &f, "user", s->seal, PTR_TO_UID(k)); - if (r >= 0) - ordered_hashmap_replace(s->user_journals, k, f); -@@ -640,7 +637,6 @@ void server_rotate(Server *s) { - - void server_sync(Server *s) { - JournalFile *f; -- Iterator i; - int r; - - if (s->system_journal) { -@@ -649,7 +645,7 @@ void server_sync(Server *s) { - log_warning_errno(r, "Failed to sync system journal, ignoring: %m"); - } - -- ORDERED_HASHMAP_FOREACH(f, s->user_journals, i) { -+ ORDERED_HASHMAP_FOREACH(f, s->user_journals) { - r = journal_file_set_offline(f, false); - if (r < 0) - log_warning_errno(r, "Failed to sync user journal, ignoring: %m"); -@@ -1677,27 +1673,20 @@ int server_schedule_sync(Server *s, int priority) { - return 0; - - if (s->sync_interval_usec > 0) { -- usec_t when; -- -- r = sd_event_now(s->event, CLOCK_MONOTONIC, &when); -- if (r < 0) -- return r; -- -- when += s->sync_interval_usec; - - if (!s->sync_event_source) { -- r = sd_event_add_time( -+ r = sd_event_add_time_relative( - s->event, - &s->sync_event_source, - CLOCK_MONOTONIC, -- when, 0, -+ s->sync_interval_usec, 0, - server_dispatch_sync, s); - if (r < 0) - return r; - - r = sd_event_source_set_priority(s->sync_event_source, SD_EVENT_PRIORITY_IMPORTANT); - } else { -- r = sd_event_source_set_time(s->sync_event_source, when); -+ r = sd_event_source_set_time_relative(s->sync_event_source, s->sync_interval_usec); - if (r < 0) - return r; - -@@ -1888,7 +1877,7 @@ static int server_connect_notify(Server *s) { - if (sd_watchdog_enabled(false, &s->watchdog_usec) > 0) { - s->send_watchdog = true; - -- r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec/4, dispatch_watchdog, s); -+ r = sd_event_add_time_relative(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, s->watchdog_usec/2, s->watchdog_usec/4, dispatch_watchdog, s); - if (r < 0) - return log_error_errno(r, "Failed to add watchdog time event: %m"); - } -@@ -2116,7 +2105,6 @@ static int server_idle_handler(sd_event_source *source, uint64_t usec, void *use - - int server_start_or_stop_idle_timer(Server *s) { - _cleanup_(sd_event_source_unrefp) sd_event_source *source = NULL; -- usec_t when; - int r; - - assert(s); -@@ -2129,11 +2117,7 @@ int server_start_or_stop_idle_timer(Server *s) { - if (s->idle_event_source) - return 1; - -- r = sd_event_now(s->event, CLOCK_MONOTONIC, &when); -- if (r < 0) -- return log_error_errno(r, "Failed to determine current time: %m"); -- -- r = sd_event_add_time(s->event, &source, CLOCK_MONOTONIC, usec_add(when, IDLE_TIMEOUT_USEC), 0, server_idle_handler, s); -+ r = sd_event_add_time_relative(s->event, &source, CLOCK_MONOTONIC, IDLE_TIMEOUT_USEC, 0, server_idle_handler, s); - if (r < 0) - return log_error_errno(r, "Failed to allocate idle timer: %m"); - -@@ -2148,7 +2132,6 @@ int server_start_or_stop_idle_timer(Server *s) { - } - - int server_refresh_idle_timer(Server *s) { -- usec_t when; - int r; - - assert(s); -@@ -2156,11 +2139,7 @@ int server_refresh_idle_timer(Server *s) { - if (!s->idle_event_source) - return 0; - -- r = sd_event_now(s->event, CLOCK_MONOTONIC, &when); -- if (r < 0) -- return log_error_errno(r, "Failed to determine current time: %m"); -- -- r = sd_event_source_set_time(s->idle_event_source, usec_add(when, IDLE_TIMEOUT_USEC)); -+ r = sd_event_source_set_time_relative(s->idle_event_source, IDLE_TIMEOUT_USEC); - if (r < 0) - return log_error_errno(r, "Failed to refresh idle timer: %m"); - -@@ -2451,7 +2430,6 @@ int server_init(Server *s, const char *namespace) { - void server_maybe_append_tags(Server *s) { - #if HAVE_GCRYPT - JournalFile *f; -- Iterator i; - usec_t n; - - n = now(CLOCK_REALTIME); -@@ -2459,7 +2437,7 @@ void server_maybe_append_tags(Server *s) { - if (s->system_journal) - journal_file_maybe_append_tag(s->system_journal, n); - -- ORDERED_HASHMAP_FOREACH(f, s->user_journals, i) -+ ORDERED_HASHMAP_FOREACH(f, s->user_journals) - journal_file_maybe_append_tag(f, n); - #endif - } -@@ -2573,7 +2551,7 @@ int config_parse_line_max( - - r = parse_size(rvalue, 1024, &v); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse LineMax= value, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse LineMax= value, ignoring: %s", rvalue); - return 0; - } - -@@ -2628,7 +2606,7 @@ int config_parse_compress( - if (r < 0) { - r = parse_size(rvalue, 1024, &compress->threshold_bytes); - if (r < 0) -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to parse Compress= value, ignoring: %s", rvalue); - else - compress->enabled = true; -diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c -index 241e257..b1c35a1 100644 ---- a/src/journal/journald-stream.c -+++ b/src/journal/journald-stream.c -@@ -834,13 +834,12 @@ int server_restore_streams(Server *s, FDSet *fds) { - FOREACH_DIRENT(de, d, goto fail) { - unsigned long st_dev, st_ino; - bool found = false; -- Iterator i; - int fd; - - if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2) - continue; - -- FDSET_FOREACH(fd, fds, i) { -+ FDSET_FOREACH(fd, fds) { - struct stat st; - - if (fstat(fd, &st) < 0) -diff --git a/src/journal/meson.build b/src/journal/meson.build -index 5796f77..3a590bd 100644 ---- a/src/journal/meson.build -+++ b/src/journal/meson.build -@@ -101,7 +101,11 @@ journald_gperf_c = custom_target( - - systemd_cat_sources = files('cat.c') - --journalctl_sources = files('journalctl.c') -+journalctl_sources = files(''' -+ journalctl.c -+ pcre2-dlopen.c -+ pcre2-dlopen.h -+'''.split()) - - if conf.get('HAVE_QRENCODE') == 1 - journalctl_sources += files('journal-qrcode.c', -diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c -index 9eb3e1a..f627630 100644 ---- a/src/journal/mmap-cache.c -+++ b/src/journal/mmap-cache.c -@@ -552,7 +552,6 @@ unsigned mmap_cache_get_missed(MMapCache *m) { - static void mmap_cache_process_sigbus(MMapCache *m) { - bool found = false; - MMapFileDescriptor *f; -- Iterator i; - int r; - - assert(m); -@@ -572,7 +571,7 @@ static void mmap_cache_process_sigbus(MMapCache *m) { - } - - ours = false; -- HASHMAP_FOREACH(f, m->fds, i) { -+ HASHMAP_FOREACH(f, m->fds) { - Window *w; - - LIST_FOREACH(by_fd, w, f->windows) { -@@ -601,7 +600,7 @@ static void mmap_cache_process_sigbus(MMapCache *m) { - if (_likely_(!found)) - return; - -- HASHMAP_FOREACH(f, m->fds, i) { -+ HASHMAP_FOREACH(f, m->fds) { - Window *w; - - if (!f->sigbus) -diff --git a/src/journal/pcre2-dlopen.c b/src/journal/pcre2-dlopen.c -new file mode 100644 -index 0000000..1e1108c ---- /dev/null -+++ b/src/journal/pcre2-dlopen.c -@@ -0,0 +1,57 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include "alloc-util.h" -+#include "dlfcn-util.h" -+#include "pcre2-dlopen.h" -+ -+#if HAVE_PCRE2 -+static void *pcre2_dl = NULL; -+ -+pcre2_match_data* (*sym_pcre2_match_data_create)(uint32_t, pcre2_general_context *); -+void (*sym_pcre2_match_data_free)(pcre2_match_data *); -+void (*sym_pcre2_code_free)(pcre2_code *); -+pcre2_code* (*sym_pcre2_compile)(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, pcre2_compile_context *); -+int (*sym_pcre2_get_error_message)(int, PCRE2_UCHAR *, PCRE2_SIZE); -+int (*sym_pcre2_match)(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, pcre2_match_data *, pcre2_match_context *); -+PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *); -+ -+int dlopen_pcre2(void) { -+ _cleanup_(dlclosep) void *dl = NULL; -+ int r; -+ -+ if (pcre2_dl) -+ return 0; /* Already loaded */ -+ -+ dl = dlopen("libpcre2-8.so.0", RTLD_LAZY); -+ if (!dl) -+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), -+ "PCRE2 support is not installed: %s", dlerror()); -+ -+ r = dlsym_many_and_warn( -+ dl, -+ LOG_ERR, -+ &sym_pcre2_match_data_create, "pcre2_match_data_create_8", -+ &sym_pcre2_match_data_free, "pcre2_match_data_free_8", -+ &sym_pcre2_code_free, "pcre2_code_free_8", -+ &sym_pcre2_compile, "pcre2_compile_8", -+ &sym_pcre2_get_error_message, "pcre2_get_error_message_8", -+ &sym_pcre2_match, "pcre2_match_8", -+ &sym_pcre2_get_ovector_pointer, "pcre2_get_ovector_pointer_8", -+ NULL); -+ if (r < 0) -+ return r; -+ -+ /* Note that we never release the reference here, because there's no real reason to, after all this -+ * was traditionally a regular shared library dependency which lives forever too. */ -+ pcre2_dl = TAKE_PTR(dl); -+ -+ return 1; -+} -+ -+#else -+ -+int dlopen_pcre2(void) { -+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), -+ "PCRE2 support is not compiled in."); -+} -+#endif -diff --git a/src/journal/pcre2-dlopen.h b/src/journal/pcre2-dlopen.h -new file mode 100644 -index 0000000..e7cb0a5 ---- /dev/null -+++ b/src/journal/pcre2-dlopen.h -@@ -0,0 +1,18 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#if HAVE_PCRE2 -+ -+#define PCRE2_CODE_UNIT_WIDTH 8 -+#include -+ -+extern pcre2_match_data* (*sym_pcre2_match_data_create)(uint32_t, pcre2_general_context *); -+extern void (*sym_pcre2_match_data_free)(pcre2_match_data *); -+extern void (*sym_pcre2_code_free)(pcre2_code *); -+extern pcre2_code* (*sym_pcre2_compile)(PCRE2_SPTR, PCRE2_SIZE, uint32_t, int *, PCRE2_SIZE *, pcre2_compile_context *); -+extern int (*sym_pcre2_get_error_message)(int, PCRE2_UCHAR *, PCRE2_SIZE); -+extern int (*sym_pcre2_match)(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, pcre2_match_data *, pcre2_match_context *); -+extern PCRE2_SIZE* (*sym_pcre2_get_ovector_pointer)(pcre2_match_data *); -+#endif -+ -+int dlopen_pcre2(void); -diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c -index 6fb0abb..731fc51 100644 ---- a/src/journal/sd-journal.c -+++ b/src/journal/sd-journal.c -@@ -105,7 +105,6 @@ static int journal_put_error(sd_journal *j, int r, const char *path) { - } - - static void detach_location(sd_journal *j) { -- Iterator i; - JournalFile *f; - - assert(j); -@@ -113,7 +112,7 @@ static void detach_location(sd_journal *j) { - j->current_file = NULL; - j->current_field = 0; - -- ORDERED_HASHMAP_FOREACH(f, j->files, i) -+ ORDERED_HASHMAP_FOREACH(f, j->files) - journal_file_reset_location(f); - } - -@@ -951,74 +950,69 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) { - } - - _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) { -- const char *word, *state; -- size_t l; - unsigned long long seqnum, monotonic, realtime, xor_hash; -- bool -- seqnum_id_set = false, -- seqnum_set = false, -- boot_id_set = false, -- monotonic_set = false, -- realtime_set = false, -- xor_hash_set = false; -+ bool seqnum_id_set = false, -+ seqnum_set = false, -+ boot_id_set = false, -+ monotonic_set = false, -+ realtime_set = false, -+ xor_hash_set = false; - sd_id128_t seqnum_id, boot_id; -+ int r; - - assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); - assert_return(!isempty(cursor), -EINVAL); - -- FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) { -- char *item; -- int k = 0; -+ for (const char *p = cursor;;) { -+ _cleanup_free_ char *word = NULL; - -- if (l < 2 || word[1] != '=') -- return -EINVAL; -+ r = extract_first_word(&p, &word, ";", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; - -- item = strndup(word, l); -- if (!item) -- return -ENOMEM; -+ if (word[0] == '\0' || word[1] != '=') -+ return -EINVAL; - - switch (word[0]) { -- - case 's': - seqnum_id_set = true; -- k = sd_id128_from_string(item+2, &seqnum_id); -+ r = sd_id128_from_string(word + 2, &seqnum_id); -+ if (r < 0) -+ return r; - break; - - case 'i': - seqnum_set = true; -- if (sscanf(item+2, "%llx", &seqnum) != 1) -- k = -EINVAL; -+ if (sscanf(word + 2, "%llx", &seqnum) != 1) -+ return -EINVAL; - break; - - case 'b': - boot_id_set = true; -- k = sd_id128_from_string(item+2, &boot_id); -+ r = sd_id128_from_string(word + 2, &boot_id); - break; - - case 'm': - monotonic_set = true; -- if (sscanf(item+2, "%llx", &monotonic) != 1) -- k = -EINVAL; -+ if (sscanf(word + 2, "%llx", &monotonic) != 1) -+ return -EINVAL; - break; - - case 't': - realtime_set = true; -- if (sscanf(item+2, "%llx", &realtime) != 1) -- k = -EINVAL; -+ if (sscanf(word + 2, "%llx", &realtime) != 1) -+ return -EINVAL; - break; - - case 'x': - xor_hash_set = true; -- if (sscanf(item+2, "%llx", &xor_hash) != 1) -- k = -EINVAL; -+ if (sscanf(word + 2, "%llx", &xor_hash) != 1) -+ return -EINVAL; - break; - } -- -- free(item); -- -- if (k < 0) -- return k; - } - - if ((!seqnum_set || !seqnum_id_set) && -@@ -1859,7 +1853,6 @@ static int add_search_paths(sd_journal *j) { - } - - static int add_current_paths(sd_journal *j) { -- Iterator i; - JournalFile *f; - - assert(j); -@@ -1868,7 +1861,7 @@ static int add_current_paths(sd_journal *j) { - /* Simply adds all directories for files we have open as directories. We don't expect errors here, so we - * treat them as fatal. */ - -- ORDERED_HASHMAP_FOREACH(f, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(f, j->files) { - _cleanup_free_ char *dir; - int r; - -@@ -2103,7 +2096,6 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) { - } - - _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) { -- Iterator iterator; - JournalFile *f; - _cleanup_(sd_journal_closep) sd_journal *j = NULL; - unsigned i; -@@ -2148,7 +2140,7 @@ _public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fd - fail: - /* If we fail, make sure we don't take possession of the files we managed to make use of successfully, and they - * remain open */ -- ORDERED_HASHMAP_FOREACH(f, j->files, iterator) -+ ORDERED_HASHMAP_FOREACH(f, j->files) - f->close_fd = false; - - return r; -@@ -2219,7 +2211,6 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12 - Object *o; - JournalFile *f; - int r; -- sd_id128_t id; - - assert_return(j, -EINVAL); - assert_return(!journal_pid_changed(j), -ECHILD); -@@ -2238,6 +2229,8 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12 - if (ret_boot_id) - *ret_boot_id = o->entry.boot_id; - else { -+ sd_id128_t id; -+ - r = sd_id128_get_boot(&id); - if (r < 0) - return r; -@@ -2565,7 +2558,6 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) { - static void process_q_overflow(sd_journal *j) { - JournalFile *f; - Directory *m; -- Iterator i; - - assert(j); - -@@ -2579,7 +2571,7 @@ static void process_q_overflow(sd_journal *j) { - j->generation++; - (void) reiterate_all_paths(j); - -- ORDERED_HASHMAP_FOREACH(f, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(f, j->files) { - - if (f->last_seen_generation == j->generation) - continue; -@@ -2588,7 +2580,7 @@ static void process_q_overflow(sd_journal *j) { - remove_file_real(j, f); - } - -- HASHMAP_FOREACH(m, j->directories_by_path, i) { -+ HASHMAP_FOREACH(m, j->directories_by_path) { - - if (m->last_seen_generation == j->generation) - continue; -@@ -2703,7 +2695,6 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { - assert_return(!journal_pid_changed(j), -ECHILD); - - if (j->inotify_fd < 0) { -- Iterator i; - JournalFile *f; - - /* This is the first invocation, hence create the -@@ -2714,7 +2705,7 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { - - /* Server might have done some vacuuming while we weren't watching. - Get rid of the deleted files now so they don't stay around indefinitely. */ -- ORDERED_HASHMAP_FOREACH(f, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(f, j->files) { - r = journal_file_fstat(f); - if (r == -EIDRM) - remove_file_real(j, f); -@@ -2756,7 +2747,6 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { - } - - _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) { -- Iterator i; - JournalFile *f; - bool first = true; - uint64_t fmin = 0, tmax = 0; -@@ -2767,7 +2757,7 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, - assert_return(from || to, -EINVAL); - assert_return(from != to, -EINVAL); - -- ORDERED_HASHMAP_FOREACH(f, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(f, j->files) { - usec_t fr, t; - - r = journal_file_get_cutoff_realtime_usec(f, &fr, &t); -@@ -2797,7 +2787,6 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, - } - - _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) { -- Iterator i; - JournalFile *f; - bool found = false; - int r; -@@ -2807,7 +2796,7 @@ _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot - assert_return(from || to, -EINVAL); - assert_return(from != to, -EINVAL); - -- ORDERED_HASHMAP_FOREACH(f, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(f, j->files) { - usec_t fr, t; - - r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t); -@@ -2836,13 +2825,12 @@ _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot - } - - void journal_print_header(sd_journal *j) { -- Iterator i; - JournalFile *f; - bool newline = false; - - assert(j); - -- ORDERED_HASHMAP_FOREACH(f, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(f, j->files) { - if (newline) - putchar('\n'); - else -@@ -2853,7 +2841,6 @@ void journal_print_header(sd_journal *j) { - } - - _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { -- Iterator i; - JournalFile *f; - uint64_t sum = 0; - -@@ -2861,7 +2848,7 @@ _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { - assert_return(!journal_pid_changed(j), -ECHILD); - assert_return(bytes, -EINVAL); - -- ORDERED_HASHMAP_FOREACH(f, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(f, j->files) { - struct stat st; - - if (fstat(f->fd, &st) < 0) -@@ -2919,7 +2906,6 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ - - for (;;) { - JournalFile *of; -- Iterator i; - Object *o; - const void *odata; - size_t ol; -@@ -2987,7 +2973,7 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ - * object by checking if it exists in the earlier - * traversed files. */ - found = false; -- ORDERED_HASHMAP_FOREACH(of, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(of, j->files) { - if (of == j->unique_file) - break; - -@@ -3059,7 +3045,6 @@ _public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) { - - for (;;) { - JournalFile *f, *of; -- Iterator i; - uint64_t m; - Object *o; - size_t sz; -@@ -3136,7 +3121,7 @@ _public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) { - - /* Let's see if we already returned this field name before. */ - found = false; -- ORDERED_HASHMAP_FOREACH(of, j->files, i) { -+ ORDERED_HASHMAP_FOREACH(of, j->files) { - if (of == f) - break; - -diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c -index 158847f..0f1447a 100644 ---- a/src/journal/test-catalog.c -+++ b/src/journal/test-catalog.c -@@ -65,7 +65,6 @@ static void test_catalog_import_badid(void) { - static void test_catalog_import_one(void) { - _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; - char *payload; -- Iterator j; - - const char *input = - "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ -@@ -80,7 +79,7 @@ static void test_catalog_import_one(void) { - h = test_import(input, -1, 0); - assert_se(ordered_hashmap_size(h) == 1); - -- ORDERED_HASHMAP_FOREACH(payload, h, j) { -+ ORDERED_HASHMAP_FOREACH(payload, h) { - printf("expect: %s\n", expect); - printf("actual: %s\n", payload); - assert_se(streq(expect, payload)); -@@ -90,7 +89,6 @@ static void test_catalog_import_one(void) { - static void test_catalog_import_merge(void) { - _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; - char *payload; -- Iterator j; - - const char *input = - "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ -@@ -116,14 +114,13 @@ static void test_catalog_import_merge(void) { - h = test_import(input, -1, 0); - assert_se(ordered_hashmap_size(h) == 1); - -- ORDERED_HASHMAP_FOREACH(payload, h, j) -+ ORDERED_HASHMAP_FOREACH(payload, h) - assert_se(streq(combined, payload)); - } - - static void test_catalog_import_merge_no_body(void) { - _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; - char *payload; -- Iterator j; - - const char *input = - "-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ -@@ -148,7 +145,7 @@ static void test_catalog_import_merge_no_body(void) { - h = test_import(input, -1, 0); - assert_se(ordered_hashmap_size(h) == 1); - -- ORDERED_HASHMAP_FOREACH(payload, h, j) -+ ORDERED_HASHMAP_FOREACH(payload, h) - assert_se(streq(combined, payload)); - } - -diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install -index 6c0e27b..567d2b9 100644 ---- a/src/kernel-install/90-loaderentry.install -+++ b/src/kernel-install/90-loaderentry.install -@@ -18,8 +18,9 @@ fi - - MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID - --ENTRY_DIR="/$MACHINE_ID/$KERNEL_VERSION" --BOOT_ROOT=${ENTRY_DIR_ABS%$ENTRY_DIR} -+BOOT_ROOT=${ENTRY_DIR_ABS%/$MACHINE_ID/$KERNEL_VERSION} -+BOOT_MNT=$(stat -c %m $BOOT_ROOT) -+ENTRY_DIR=/${ENTRY_DIR_ABS#$BOOT_MNT} - - if [[ $COMMAND == remove ]]; then - rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf" -@@ -94,7 +95,7 @@ for initrd in "${INITRD_OPTIONS[@]}"; do - fi - done - --# If no initrd option is supplied, fallback to "initrd" which is -+# If no initrd option is supplied, fall back to "initrd" which is - # the name used by dracut when generating it in its kernel-install hook - [[ ${#INITRD_OPTIONS[@]} == 0 ]] && INITRD_OPTIONS=( initrd ) - -diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install -index e2590c4..0ae07fc 100755 ---- a/src/kernel-install/kernel-install -+++ b/src/kernel-install/kernel-install -@@ -85,8 +85,13 @@ fi - KERNEL_VERSION="$1" - KERNEL_IMAGE="$2" - --if [[ -f /etc/machine-id ]]; then -+# Reuse directory created without a machine ID present if it exists. -+if [[ -d /efi/Default ]] || [[ -d /boot/Default ]] || [[ -d /boot/efi/Default ]]; then -+ MACHINE_ID="Default" -+elif [[ -f /etc/machine-id ]]; then - read MACHINE_ID < /etc/machine-id -+else -+ MACHINE_ID="Default" - fi - - if [[ ! $COMMAND ]] || [[ ! $KERNEL_VERSION ]]; then -@@ -94,10 +99,7 @@ if [[ ! $COMMAND ]] || [[ ! $KERNEL_VERSION ]]; then - exit 1 - fi - --if ! [[ $MACHINE_ID ]]; then -- ENTRY_DIR_ABS=$(mktemp -d /tmp/kernel-install.XXXXX) || exit 1 -- trap "rm -rf '$ENTRY_DIR_ABS'" EXIT INT QUIT PIPE --elif [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then -+if [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then - ENTRY_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION" - elif [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then - ENTRY_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION" -@@ -146,14 +148,6 @@ case $COMMAND in - ((ret+=$x)) - fi - done -- -- if ! [[ $MACHINE_ID ]] && ! rmdir "$ENTRY_DIR_ABS"; then -- echo "Warning: In kernel-install plugins, requiring ENTRY_DIR_ABS to be preset is deprecated." >&2 -- echo " All plugins should not put anything in ENTRY_DIR_ABS if the environment" >&2 -- echo " variable KERNEL_INSTALL_MACHINE_ID is empty." >&2 -- rm -rf "$ENTRY_DIR_ABS" -- ((ret+=$?)) -- fi - ;; - - remove) -diff --git a/src/libsystemd-network/arp-util.c b/src/libsystemd-network/arp-util.c -index ac601a4..4fbf2bb 100644 ---- a/src/libsystemd-network/arp-util.c -+++ b/src/libsystemd-network/arp-util.c -@@ -76,7 +76,7 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_ - - assert(ifindex > 0); - -- s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); -+ s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (s < 0) - return -errno; - -diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c -index e03c1a8..6fe8a37 100644 ---- a/src/libsystemd-network/dhcp-option.c -+++ b/src/libsystemd-network/dhcp-option.c -@@ -81,9 +81,8 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, - OrderedHashmap *s = (OrderedHashmap *) optval; - struct sd_dhcp_option *p; - size_t l = 0; -- Iterator i; - -- ORDERED_HASHMAP_FOREACH(p, s, i) -+ ORDERED_HASHMAP_FOREACH(p, s) - l += p->length + 2; - - if (*offset + l + 2 > size) -@@ -94,7 +93,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, - - *offset += 2; - -- ORDERED_HASHMAP_FOREACH(p, s, i) { -+ ORDERED_HASHMAP_FOREACH(p, s) { - options[*offset] = p->option; - options[*offset + 1] = p->length; - memcpy(&options[*offset + 2], p->data, p->length); -diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h -index baf7bb2..9ce6dcd 100644 ---- a/src/libsystemd-network/dhcp6-internal.h -+++ b/src/libsystemd-network/dhcp6-internal.h -@@ -109,8 +109,9 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat - int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, - struct in6_addr **addrs, size_t count, - size_t *allocated); --int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, -- char ***str_arr); -+int dhcp6_option_parse_domainname_list(const uint8_t *optval, uint16_t optlen, -+ char ***str_arr); -+int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char **str); - - int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *address); - int dhcp6_network_send_udp_socket(int s, struct in6_addr *address, -diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h -index e004f48..df6c95e 100644 ---- a/src/libsystemd-network/dhcp6-lease-internal.h -+++ b/src/libsystemd-network/dhcp6-lease-internal.h -@@ -35,6 +35,7 @@ struct sd_dhcp6_lease { - size_t ntp_allocated; - char **ntp_fqdn; - size_t ntp_fqdn_count; -+ char *fqdn; - }; - - int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire); -@@ -57,5 +58,6 @@ int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, - int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); - int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, - size_t optlen) ; -+int dhcp6_lease_set_fqdn(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); - - int dhcp6_lease_new(sd_dhcp6_lease **ret); -diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c -index fa43587..030173a 100644 ---- a/src/libsystemd-network/dhcp6-option.c -+++ b/src/libsystemd-network/dhcp6-option.c -@@ -81,7 +81,6 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, - - int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options) { - sd_dhcp6_option *options; -- Iterator i; - int r; - - assert(buf); -@@ -89,7 +88,7 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash - assert(buflen); - assert(vendor_options); - -- ORDERED_HASHMAP_FOREACH(options, vendor_options, i) { -+ ORDERED_HASHMAP_FOREACH(options, vendor_options) { - _cleanup_free_ uint8_t *p = NULL; - size_t total; - -@@ -642,59 +641,103 @@ int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, - return count; - } - --int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char ***str_arr) { -- size_t pos = 0, idx = 0; -- _cleanup_strv_free_ char **names = NULL; -+static int parse_domain(const uint8_t **data, uint16_t *len, char **out_domain) { -+ _cleanup_free_ char *ret = NULL; -+ size_t n = 0, allocated = 0; -+ const uint8_t *optval = *data; -+ uint16_t optlen = *len; -+ bool first = true; - int r; - -- assert_return(optlen > 1, -ENODATA); -- assert_return(optval[optlen - 1] == '\0', -EINVAL); -- -- while (pos < optlen) { -- _cleanup_free_ char *ret = NULL; -- size_t n = 0, allocated = 0; -- bool first = true; -+ if (optlen <= 1) -+ return -ENODATA; - -- for (;;) { -- const char *label; -- uint8_t c; -+ for (;;) { -+ const char *label; -+ uint8_t c; - -- c = optval[pos++]; -+ if (optlen == 0) -+ break; - -- if (c == 0) -- /* End of name */ -- break; -- if (c > 63) -- return -EBADMSG; -+ c = *optval; -+ optval++; -+ optlen--; - -- /* Literal label */ -- label = (const char *)&optval[pos]; -- pos += c; -- if (pos >= optlen) -- return -EMSGSIZE; -+ if (c == 0) -+ /* End label */ -+ break; -+ if (c > 63) -+ return -EBADMSG; -+ if (c > optlen) -+ return -EMSGSIZE; - -- if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) -- return -ENOMEM; -+ /* Literal label */ -+ label = (const char *)optval; -+ optval += c; -+ optlen -= c; - -- if (first) -- first = false; -- else -- ret[n++] = '.'; -+ if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) -+ return -ENOMEM; - -- r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX); -- if (r < 0) -- return r; -+ if (first) -+ first = false; -+ else -+ ret[n++] = '.'; - -- n += r; -- } -+ r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX); -+ if (r < 0) -+ return r; - -- if (n == 0) -- continue; -+ n += r; -+ } - -+ if (n) { - if (!GREEDY_REALLOC(ret, allocated, n + 1)) - return -ENOMEM; -- - ret[n] = 0; -+ } -+ -+ *out_domain = TAKE_PTR(ret); -+ *data = optval; -+ *len = optlen; -+ -+ return n; -+} -+ -+int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char **str) { -+ _cleanup_free_ char *domain = NULL; -+ int r; -+ -+ r = parse_domain(&optval, &optlen, &domain); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return -ENODATA; -+ if (optlen != 0) -+ return -EINVAL; -+ -+ *str = TAKE_PTR(domain); -+ return 0; -+} -+ -+int dhcp6_option_parse_domainname_list(const uint8_t *optval, uint16_t optlen, char ***str_arr) { -+ size_t idx = 0; -+ _cleanup_strv_free_ char **names = NULL; -+ int r; -+ -+ if (optlen <= 1) -+ return -ENODATA; -+ if (optval[optlen - 1] != '\0') -+ return -EINVAL; -+ -+ while (optlen > 0) { -+ _cleanup_free_ char *ret = NULL; -+ -+ r = parse_domain(&optval, &optlen, &ret); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ continue; - - r = strv_extend(&names, ret); - if (r < 0) -diff --git a/src/libsystemd-network/lldp-network.c b/src/libsystemd-network/lldp-network.c -index 53e3297..de7e2bf 100644 ---- a/src/libsystemd-network/lldp-network.c -+++ b/src/libsystemd-network/lldp-network.c -@@ -47,7 +47,7 @@ int lldp_network_bind_raw_socket(int ifindex) { - - assert(ifindex > 0); - -- fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, -+ fd = socket(AF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, - htobe16(ETHERTYPE_LLDP)); - if (fd < 0) - return -errno; -diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c -index a83ffc3..265b6ea 100644 ---- a/src/libsystemd-network/sd-dhcp-client.c -+++ b/src/libsystemd-network/sd-dhcp-client.c -@@ -919,7 +919,6 @@ static int dhcp_client_send_raw( - - static int client_append_common_discover_request_options(sd_dhcp_client *client, DHCPPacket *packet, size_t *optoffset, size_t optlen) { - sd_dhcp_option *j; -- Iterator i; - int r; - - assert(client); -@@ -970,7 +969,7 @@ static int client_append_common_discover_request_options(sd_dhcp_client *client, - return r; - } - -- ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) { -+ ORDERED_HASHMAP_FOREACH(j, client->extra_options) { - r = dhcp_option_append(&packet->dhcp, optlen, optoffset, 0, - j->option, j->length, j->data); - if (r < 0) -diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c -index ec20b93..a34a559 100644 ---- a/src/libsystemd-network/sd-dhcp-server.c -+++ b/src/libsystemd-network/sd-dhcp-server.c -@@ -479,7 +479,6 @@ static int server_send_ack( - _cleanup_free_ DHCPPacket *packet = NULL; - be32_t lease_time; - sd_dhcp_option *j; -- Iterator i; - size_t offset; - int r; - -@@ -531,7 +530,7 @@ static int server_send_ack( - return r; - } - -- ORDERED_HASHMAP_FOREACH(j, server->extra_options, i) { -+ ORDERED_HASHMAP_FOREACH(j, server->extra_options) { - r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, - j->option, j->length, j->data); - if (r < 0) -diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c -index 5cdb82b..7b5b96b 100644 ---- a/src/libsystemd-network/sd-dhcp6-client.c -+++ b/src/libsystemd-network/sd-dhcp6-client.c -@@ -624,7 +624,6 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { - IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; - struct sd_dhcp6_option *j; - size_t len, optlen = 512; -- Iterator i; - uint8_t *opt; - int r; - usec_t elapsed_usec; -@@ -859,7 +858,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { - if (r < 0) - return r; - -- ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) { -+ ORDERED_HASHMAP_FOREACH(j, client->extra_options) { - r = dhcp6_option_append(&opt, &optlen, j->option, j->length, j->data); - if (r < 0) - return r; -@@ -1282,6 +1281,13 @@ static int client_parse_message( - - break; - -+ case SD_DHCP6_OPTION_FQDN: -+ r = dhcp6_lease_set_fqdn(lease, optval, optlen); -+ if (r < 0) -+ return r; -+ -+ break; -+ - case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME: - if (optlen != 4) - return -EINVAL; -@@ -1688,7 +1694,7 @@ int sd_dhcp6_client_is_running(sd_dhcp6_client *client) { - - int sd_dhcp6_client_start(sd_dhcp6_client *client) { - enum DHCP6State state = DHCP6_STATE_SOLICITATION; -- int r = 0; -+ int r; - - assert_return(client, -EINVAL); - assert_return(client->event, -EINVAL); -diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c -index 4eee10e..9aad221 100644 ---- a/src/libsystemd-network/sd-dhcp6-lease.c -+++ b/src/libsystemd-network/sd-dhcp6-lease.c -@@ -236,7 +236,7 @@ int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, - if (!optlen) - return 0; - -- r = dhcp6_option_parse_domainname(optval, optlen, &domains); -+ r = dhcp6_option_parse_domainname_list(optval, optlen, &domains); - if (r < 0) - return 0; - -@@ -294,8 +294,8 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { - break; - - case DHCP6_NTP_SUBOPTION_SRV_FQDN: -- r = dhcp6_option_parse_domainname(subval, sublen, -- &servers); -+ r = dhcp6_option_parse_domainname_list(subval, sublen, -+ &servers); - if (r < 0) - return 0; - -@@ -365,6 +365,38 @@ int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) { - return -ENOENT; - } - -+int dhcp6_lease_set_fqdn(sd_dhcp6_lease *lease, const uint8_t *optval, -+ size_t optlen) { -+ int r; -+ char *fqdn; -+ -+ assert_return(lease, -EINVAL); -+ assert_return(optval, -EINVAL); -+ -+ if (optlen < 2) -+ return -ENODATA; -+ -+ /* Ignore the flags field, it doesn't carry any useful -+ information for clients. */ -+ r = dhcp6_option_parse_domainname(optval + 1, optlen - 1, &fqdn); -+ if (r < 0) -+ return r; -+ -+ return free_and_replace(lease->fqdn, fqdn); -+} -+ -+int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **fqdn) { -+ assert_return(lease, -EINVAL); -+ assert_return(fqdn, -EINVAL); -+ -+ if (lease->fqdn) { -+ *fqdn = lease->fqdn; -+ return 0; -+ } -+ -+ return -ENOENT; -+} -+ - static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) { - assert(lease); - -@@ -373,6 +405,7 @@ static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) { - dhcp6_lease_free_ia(&lease->pd); - - free(lease->dns); -+ free(lease->fqdn); - - lease->domains = strv_free(lease->domains); - -diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c -index d957202..af2b98f 100644 ---- a/src/libsystemd-network/sd-ipv4acd.c -+++ b/src/libsystemd-network/sd-ipv4acd.c -@@ -142,10 +142,17 @@ static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) { - } - - int sd_ipv4acd_stop(sd_ipv4acd *acd) { -+ IPv4ACDState old_state; -+ - assert_return(acd, -EINVAL); - -+ old_state = acd->state; -+ - ipv4acd_reset(acd); - -+ if (old_state == IPV4ACD_STATE_INIT) -+ return 0; -+ - log_ipv4acd(acd, "STOPPED"); - - ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP); -@@ -435,6 +442,15 @@ int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) { - return 0; - } - -+int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address) { -+ assert_return(acd, -EINVAL); -+ assert_return(address, -EINVAL); -+ -+ address->s_addr = acd->address; -+ -+ return 0; -+} -+ - int sd_ipv4acd_is_running(sd_ipv4acd *acd) { - assert_return(acd, false); - -diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c -index d3606cf..b0a11fe 100644 ---- a/src/libsystemd-network/sd-lldp.c -+++ b/src/libsystemd-network/sd-lldp.c -@@ -431,7 +431,6 @@ static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) { - - _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { - sd_lldp_neighbor **l = NULL, *n; -- Iterator i; - int k = 0, r; - - assert_return(lldp, -EINVAL); -@@ -452,7 +451,7 @@ _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { - return r; - } - -- HASHMAP_FOREACH(n, lldp->neighbor_by_id, i) -+ HASHMAP_FOREACH(n, lldp->neighbor_by_id) - l[k++] = sd_lldp_neighbor_ref(n); - - assert((size_t) k == hashmap_size(lldp->neighbor_by_id)); -diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c -index 8f2f446..4a0b71b 100644 ---- a/src/libsystemd-network/test-dhcp-client.c -+++ b/src/libsystemd-network/test-dhcp-client.c -@@ -514,7 +514,6 @@ static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) { - } - - static void test_addr_acq(sd_event *e) { -- usec_t time_now = now(clock_boottime_or_monotonic()); - sd_dhcp_client *client; - int res, r; - -@@ -535,10 +534,11 @@ static void test_addr_acq(sd_event *e) { - - callback_recv = test_addr_acq_recv_discover; - -- assert_se(sd_event_add_time(e, &test_hangcheck, -- clock_boottime_or_monotonic(), -- time_now + 2 * USEC_PER_SEC, 0, -- test_dhcp_hangcheck, NULL) >= 0); -+ assert_se(sd_event_add_time_relative( -+ e, &test_hangcheck, -+ clock_boottime_or_monotonic(), -+ 2 * USEC_PER_SEC, 0, -+ test_dhcp_hangcheck, NULL) >= 0); - - res = sd_dhcp_client_start(client); - assert_se(IN_SET(res, 0, -EINPROGRESS)); -diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c -index 7af7d67..e198814 100644 ---- a/src/libsystemd-network/test-dhcp6-client.c -+++ b/src/libsystemd-network/test-dhcp6-client.c -@@ -20,6 +20,8 @@ - #include "macro.h" - #include "memory-util.h" - #include "socket-util.h" -+#include "string-util.h" -+#include "strv.h" - #include "tests.h" - #include "time-util.h" - #include "virt.h" -@@ -106,6 +108,52 @@ static int test_client_basic(sd_event *e) { - return 0; - } - -+static int test_parse_domain(sd_event *e) { -+ uint8_t *data; -+ char *domain; -+ char **list; -+ int r; -+ -+ log_debug("/* %s */", __func__); -+ -+ data = (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0 }; -+ r = dhcp6_option_parse_domainname(data, 13, &domain); -+ assert_se(r == 0); -+ assert_se(domain); -+ assert_se(streq(domain, "example.com")); -+ free(domain); -+ -+ data = (uint8_t []) { 4, 't', 'e', 's', 't' }; -+ r = dhcp6_option_parse_domainname(data, 5, &domain); -+ assert_se(r == 0); -+ assert_se(domain); -+ assert_se(streq(domain, "test")); -+ free(domain); -+ -+ data = (uint8_t []) { 0 }; -+ r = dhcp6_option_parse_domainname(data, 1, &domain); -+ assert_se(r < 0); -+ -+ data = (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, -+ 6, 'f', 'o', 'o', 'b', 'a', 'r', 0 }; -+ r = dhcp6_option_parse_domainname_list(data, 21, &list); -+ assert_se(r == 2); -+ assert_se(list); -+ assert_se(streq(list[0], "example.com")); -+ assert_se(streq(list[1], "foobar")); -+ strv_free(list); -+ -+ data = (uint8_t []) { 1, 'a', 0, 20, 'b', 'c' }; -+ r = dhcp6_option_parse_domainname_list(data, 6, &list); -+ assert_se(r < 0); -+ -+ data = (uint8_t []) { 0 , 0 }; -+ r = dhcp6_option_parse_domainname_list(data, 2, &list); -+ assert_se(r < 0); -+ -+ return 0; -+} -+ - static int test_option(sd_event *e) { - uint8_t packet[] = { - 'F', 'O', 'O', -@@ -330,7 +378,7 @@ static uint8_t msg_advertise[198] = { - 0x53, 0x00, 0x07, 0x00, 0x01, 0x00 - }; - --static uint8_t msg_reply[173] = { -+static uint8_t msg_reply[191] = { - 0x07, 0xf7, 0x4e, 0x57, 0x00, 0x02, 0x00, 0x0e, - 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, - 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, 0x00, 0x01, -@@ -352,7 +400,9 @@ static uint8_t msg_reply[173] = { - 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, - 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, 0x01, 0x0d, - 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, -- 0x00, 0x00, 0x00, 0x00, 0x01 -+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x27, 0x00, -+ 0x0e, 0x01, 0x06, 0x63, 0x6c, 0x69, 0x65, 0x6e, -+ 0x74, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61 - }; - - static uint8_t fqdn_wire[16] = { -@@ -747,6 +797,7 @@ static void test_client_information_cb(sd_dhcp6_client *client, int event, - const struct in6_addr *addrs; - struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; - char **domains; -+ const char *fqdn; - - log_debug("/* %s */", __func__); - -@@ -759,6 +810,9 @@ static void test_client_information_cb(sd_dhcp6_client *client, int event, - assert_se(!strcmp("lab.intra", domains[0])); - assert_se(domains[1] == NULL); - -+ assert_se(sd_dhcp6_lease_get_fqdn(lease, &fqdn) >= 0); -+ assert_se(streq(fqdn, "client.intra")); -+ - assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1); - assert_se(!memcmp(addrs, &msg_advertise[124], 16)); - -@@ -888,7 +942,6 @@ int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *local_address) { - - static int test_client_solicit(sd_event *e) { - sd_dhcp6_client *client; -- usec_t time_now = now(clock_boottime_or_monotonic()); - struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; - int val; - -@@ -914,9 +967,9 @@ static int test_client_solicit(sd_event *e) { - assert_se(sd_dhcp6_client_set_callback(client, - test_client_information_cb, e) >= 0); - -- assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(), -- time_now + 2 * USEC_PER_SEC, 0, -- test_hangcheck, NULL) >= 0); -+ assert_se(sd_event_add_time_relative(e, &hangcheck, clock_boottime_or_monotonic(), -+ 2 * USEC_PER_SEC, 0, -+ test_hangcheck, NULL) >= 0); - - assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); - -@@ -945,6 +998,7 @@ int main(int argc, char *argv[]) { - test_option_status(e); - test_advertise_option(e); - test_client_solicit(e); -+ test_parse_domain(e); - - return 0; - } -diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c -index d759ec0..942a128 100644 ---- a/src/libsystemd-network/test-ndisc-ra.c -+++ b/src/libsystemd-network/test-ndisc-ra.c -@@ -293,7 +293,6 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat - static void test_ra(void) { - sd_event *e; - sd_radv *ra; -- usec_t time_now = now(clock_boottime_or_monotonic()); - unsigned i; - - printf("* %s\n", __FUNCTION__); -@@ -339,9 +338,10 @@ static void test_ra(void) { - assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0], - EPOLLIN, radv_recv, ra) >= 0); - -- assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), -- time_now + 2 *USEC_PER_SEC, 0, -- test_rs_hangcheck, NULL) >= 0); -+ assert_se(sd_event_add_time_relative( -+ e, &test_hangcheck, clock_boottime_or_monotonic(), -+ 2 *USEC_PER_SEC, 0, -+ test_rs_hangcheck, NULL) >= 0); - - assert_se(sd_radv_start(ra) >= 0); - -diff --git a/src/libsystemd-network/test-ndisc-rs.c b/src/libsystemd-network/test-ndisc-rs.c -index 3f46c8d..2c4ffb9 100644 ---- a/src/libsystemd-network/test-ndisc-rs.c -+++ b/src/libsystemd-network/test-ndisc-rs.c -@@ -272,7 +272,6 @@ static void test_callback(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *r - static void test_rs(void) { - sd_event *e; - sd_ndisc *nd; -- usec_t time_now = now(clock_boottime_or_monotonic()); - - if (verbose) - printf("* %s\n", __FUNCTION__); -@@ -290,9 +289,10 @@ static void test_rs(void) { - assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); - assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0); - -- assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), -- time_now + 30 * USEC_PER_SEC, 0, -- test_rs_hangcheck, NULL) >= 0); -+ assert_se(sd_event_add_time_relative( -+ e, &test_hangcheck, clock_boottime_or_monotonic(), -+ 30 * USEC_PER_SEC, 0, -+ test_rs_hangcheck, NULL) >= 0); - - assert_se(sd_ndisc_stop(nd) >= 0); - assert_se(sd_ndisc_start(nd) >= 0); -@@ -373,7 +373,6 @@ static int test_timeout_value(uint8_t flags) { - static void test_timeout(void) { - sd_event *e; - sd_ndisc *nd; -- usec_t time_now = now(clock_boottime_or_monotonic()); - - if (verbose) - printf("* %s\n", __FUNCTION__); -@@ -392,9 +391,10 @@ static void test_timeout(void) { - assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0); - assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); - -- assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), -- time_now + 30 * USEC_PER_SEC, 0, -- test_rs_hangcheck, NULL) >= 0); -+ assert_se(sd_event_add_time_relative( -+ e, &test_hangcheck, clock_boottime_or_monotonic(), -+ 30 * USEC_PER_SEC, 0, -+ test_rs_hangcheck, NULL) >= 0); - - assert_se(sd_ndisc_start(nd) >= 0); - -diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym -index 1e654b4..c6dfcd6 100644 ---- a/src/libsystemd/libsystemd.sym -+++ b/src/libsystemd/libsystemd.sym -@@ -721,3 +721,16 @@ global: - sd_journal_enumerate_available_data; - sd_journal_enumerate_available_unique; - } LIBSYSTEMD_245; -+ -+LIBSYSTEMD_247 { -+global: -+ sd_event_add_time_relative; -+ sd_event_source_set_time_relative; -+ -+ sd_bus_error_has_names_sentinel; -+ -+ sd_device_get_current_tag_first; -+ sd_device_get_current_tag_next; -+ sd_device_has_current_tag; -+ sd_device_set_sysattr_valuef; -+} LIBSYSTEMD_246; -diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h -index ae80543..965f6dd 100644 ---- a/src/libsystemd/sd-bus/bus-common-errors.h -+++ b/src/libsystemd/sd-bus/bus-common-errors.h -@@ -96,6 +96,7 @@ - #define BUS_ERROR_HOME_ABSENT "org.freedesktop.home1.HomeAbsent" - #define BUS_ERROR_HOME_BUSY "org.freedesktop.home1.HomeBusy" - #define BUS_ERROR_BAD_PASSWORD "org.freedesktop.home1.BadPassword" -+#define BUS_ERROR_BAD_RECOVERY_KEY "org.freedesktop.home1.BadRecoveryKey" - #define BUS_ERROR_LOW_PASSWORD_QUALITY "org.freedesktop.home1.LowPasswordQuality" - #define BUS_ERROR_BAD_PASSWORD_AND_NO_TOKEN "org.freedesktop.home1.BadPasswordAndNoToken" - #define BUS_ERROR_TOKEN_PIN_NEEDED "org.freedesktop.home1.TokenPinNeeded" -diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c -index f760f0f..83de996 100644 ---- a/src/libsystemd/sd-bus/bus-error.c -+++ b/src/libsystemd/sd-bus/bus-error.c -@@ -13,6 +13,7 @@ - #include "errno-list.h" - #include "errno-util.h" - #include "string-util.h" -+#include "strv.h" - #include "util.h" - - BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = { -@@ -355,11 +356,23 @@ _public_ int sd_bus_error_has_name(const sd_bus_error *e, const char *name) { - return streq_ptr(e->name, name); - } - --_public_ int sd_bus_error_get_errno(const sd_bus_error* e) { -- if (!e) -+_public_ int sd_bus_error_has_names_sentinel(const sd_bus_error *e, ...) { -+ if (!e || !e->name) - return 0; - -- if (!e->name) -+ va_list ap; -+ const char *p; -+ -+ va_start(ap, e); -+ while ((p = va_arg(ap, const char *))) -+ if (streq(p, e->name)) -+ break; -+ va_end(ap); -+ return !!p; -+} -+ -+_public_ int sd_bus_error_get_errno(const sd_bus_error* e) { -+ if (!e || !e->name) - return 0; - - return bus_error_name_to_errno(e->name); -@@ -471,7 +484,6 @@ _public_ int sd_bus_error_set_errno(sd_bus_error *e, int error) { - - _public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) { - PROTECT_ERRNO; -- int r; - - if (error < 0) - error = -error; -@@ -502,34 +514,30 @@ _public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *fo - } - - if (format) { -- char *m; -+ _cleanup_free_ char *m = NULL; - - /* Then, let's try to fill in the supplied message */ - - errno = error; /* Make sure that %m resolves to the specified error */ -- r = vasprintf(&m, format, ap); -- if (r >= 0) { -+ if (vasprintf(&m, format, ap) < 0) -+ goto fail; - -- if (e->_need_free <= 0) { -- char *t; -+ if (e->_need_free <= 0) { -+ char *t; - -- t = strdup(e->name); -- if (t) { -- e->_need_free = 1; -- e->name = t; -- e->message = m; -- return -error; -- } -+ t = strdup(e->name); -+ if (!t) -+ goto fail; - -- free(m); -- } else { -- free((char*) e->message); -- e->message = m; -- return -error; -- } -+ e->_need_free = 1; -+ e->name = t; - } -+ -+ e->message = TAKE_PTR(m); -+ return -error; - } - -+fail: - /* If that didn't work, use strerror() for the message */ - bus_error_strerror(e, error); - return -error; -@@ -573,10 +581,7 @@ const char *bus_error_message(const sd_bus_error *e, int error) { - return e->message; - } - -- if (error < 0) -- error = -error; -- -- return strerror_safe(error); -+ return strerror_safe(abs(error)); - } - - static bool map_ok(const sd_bus_error_map *map) { -diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c -index 57ce8cc..20a4b46 100644 ---- a/src/libsystemd/sd-bus/bus-match.c -+++ b/src/libsystemd/sd-bus/bus-match.c -@@ -961,9 +961,8 @@ void bus_match_free(struct bus_match_node *node) { - return; - - if (BUS_MATCH_CAN_HASH(node->type)) { -- Iterator i; - -- HASHMAP_FOREACH(c, node->compare.children, i) -+ HASHMAP_FOREACH(c, node->compare.children) - bus_match_free(c); - - assert(hashmap_isempty(node->compare.children)); -@@ -1054,9 +1053,8 @@ void bus_match_dump(struct bus_match_node *node, unsigned level) { - putchar('\n'); - - if (BUS_MATCH_CAN_HASH(node->type)) { -- Iterator i; - -- HASHMAP_FOREACH(c, node->compare.children, i) -+ HASHMAP_FOREACH(c, node->compare.children) - bus_match_dump(c, level + 1); - } - -diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c -index 6abac88..33284d7 100644 ---- a/src/libsystemd/sd-bus/bus-objects.c -+++ b/src/libsystemd/sd-bus/bus-objects.c -@@ -1235,7 +1235,6 @@ static int process_get_managed_objects( - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_set_free_free_ Set *s = NULL; -- Iterator i; - char *path; - int r; - -@@ -1265,7 +1264,7 @@ static int process_get_managed_objects( - if (r < 0) - return r; - -- SET_FOREACH(path, s, i) { -+ SET_FOREACH(path, s) { - r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error); - if (r < 0) - return bus_maybe_reply_error(m, r, &error); -diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c -index fc7e8e8..de36a1f 100644 ---- a/src/libsystemd/sd-bus/bus-socket.c -+++ b/src/libsystemd/sd-bus/bus-socket.c -@@ -544,9 +544,11 @@ static int bus_socket_read_auth(sd_bus *b) { - - iov = IOVEC_MAKE((uint8_t *)b->rbuffer + b->rbuffer_size, n - b->rbuffer_size); - -- if (b->prefer_readv) -+ if (b->prefer_readv) { - k = readv(b->input_fd, &iov, 1); -- else { -+ if (k < 0) -+ k = -errno; -+ } else { - mh = (struct msghdr) { - .msg_iov = &iov, - .msg_iovlen = 1, -@@ -1187,9 +1189,11 @@ int bus_socket_read_message(sd_bus *bus) { - - iov = IOVEC_MAKE((uint8_t *)bus->rbuffer + bus->rbuffer_size, need - bus->rbuffer_size); - -- if (bus->prefer_readv) -+ if (bus->prefer_readv) { - k = readv(bus->input_fd, &iov, 1); -- else { -+ if (k < 0) -+ k = -errno; -+ } else { - mh = (struct msghdr) { - .msg_iov = &iov, - .msg_iovlen = 1, -diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c -index 9de5e45..015a215 100644 ---- a/src/libsystemd/sd-bus/sd-bus.c -+++ b/src/libsystemd/sd-bus/sd-bus.c -@@ -597,7 +597,6 @@ static int bus_send_hello(sd_bus *bus) { - - int bus_start_running(sd_bus *bus) { - struct reply_callback *c; -- Iterator i; - usec_t n; - int r; - -@@ -609,7 +608,7 @@ int bus_start_running(sd_bus *bus) { - * adding a fixed value to all entries should not alter the internal order. */ - - n = now(CLOCK_MONOTONIC); -- ORDERED_HASHMAP_FOREACH(c, bus->reply_callbacks, i) { -+ ORDERED_HASHMAP_FOREACH(c, bus->reply_callbacks) { - if (c->timeout_usec == 0) - continue; - -@@ -783,7 +782,6 @@ static int parse_tcp_address(sd_bus *b, const char **p, char **guid) { - int r; - struct addrinfo *result, hints = { - .ai_socktype = SOCK_STREAM, -- .ai_flags = AI_ADDRCONFIG, - }; - - assert(b); -diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c -index 2c1fbbe..7a35d91 100644 ---- a/src/libsystemd/sd-bus/test-bus-chat.c -+++ b/src/libsystemd/sd-bus/test-bus-chat.c -@@ -373,7 +373,7 @@ static void* client2(void *p) { - - r = sd_bus_send(bus, m, NULL); - if (r < 0) { -- log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); -+ log_error("Failed to issue method call: %s", bus_error_message(&error, r)); - goto finish; - } - -@@ -392,7 +392,7 @@ static void* client2(void *p) { - - r = sd_bus_send(bus, m, NULL); - if (r < 0) { -- log_error("Failed to issue signal: %s", bus_error_message(&error, -r)); -+ log_error("Failed to issue signal: %s", bus_error_message(&error, r)); - goto finish; - } - -@@ -412,7 +412,7 @@ static void* client2(void *p) { - - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) { -- log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); -+ log_error("Failed to issue method call: %s", bus_error_message(&error, r)); - goto finish; - } - -@@ -442,7 +442,7 @@ static void* client2(void *p) { - - r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply); - if (r < 0) -- log_info("Failed to issue method call: %s", bus_error_message(&error, -r)); -+ log_info("Failed to issue method call: %s", bus_error_message(&error, r)); - else - log_info("Slow call succeed."); - -@@ -462,7 +462,7 @@ static void* client2(void *p) { - - r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC); - if (r < 0) { -- log_info("Failed to issue method call: %s", bus_error_message(&error, -r)); -+ log_info("Failed to issue method call: %s", bus_error_message(&error, r)); - goto finish; - } - -diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c -index cb5d620..14e3c9c 100644 ---- a/src/libsystemd/sd-bus/test-bus-error.c -+++ b/src/libsystemd/sd-bus/test-bus-error.c -@@ -22,6 +22,11 @@ static void test_error(void) { - assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED)); - assert_se(streq(error.message, "xxx")); - assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED)); -+ assert_se(sd_bus_error_has_names_sentinel(&error, SD_BUS_ERROR_NOT_SUPPORTED, NULL)); -+ assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_NOT_SUPPORTED)); -+ assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_NOT_SUPPORTED, SD_BUS_ERROR_FILE_NOT_FOUND)); -+ assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND, SD_BUS_ERROR_NOT_SUPPORTED, NULL)); -+ assert_se(!sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); - assert_se(sd_bus_error_get_errno(&error) == EOPNOTSUPP); - assert_se(sd_bus_error_is_set(&error)); - sd_bus_error_free(&error); -@@ -32,6 +37,7 @@ static void test_error(void) { - assert_se(error.name == NULL); - assert_se(error.message == NULL); - assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); -+ assert_se(!sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); - assert_se(sd_bus_error_get_errno(&error) == 0); - assert_se(!sd_bus_error_is_set(&error)); - -@@ -39,6 +45,7 @@ static void test_error(void) { - assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND)); - assert_se(streq(error.message, "yyy -1")); - assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); -+ assert_se(sd_bus_error_has_names(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); - assert_se(sd_bus_error_get_errno(&error) == ENOENT); - assert_se(sd_bus_error_is_set(&error)); - -@@ -51,6 +58,7 @@ static void test_error(void) { - assert_se(streq(error.message, second.message)); - assert_se(sd_bus_error_get_errno(&second) == ENOENT); - assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND)); -+ assert_se(sd_bus_error_has_names(&second, SD_BUS_ERROR_FILE_NOT_FOUND)); - assert_se(sd_bus_error_is_set(&second)); - - sd_bus_error_free(&error); -@@ -205,12 +213,87 @@ static void test_errno_mapping_custom(void) { - assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL); - } - -+static void test_sd_bus_error_set_errnof(void) { -+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -+ _cleanup_free_ char *str = NULL; -+ -+ assert_se(sd_bus_error_set_errnof(NULL, 0, NULL) == 0); -+ assert_se(sd_bus_error_set_errnof(NULL, ENOANO, NULL) == -ENOANO); -+ -+ assert_se(sd_bus_error_set_errnof(&error, 0, NULL) == 0); -+ assert_se(!bus_error_is_dirty(&error)); -+ -+ assert_se(sd_bus_error_set_errnof(&error, EACCES, NULL) == -EACCES); -+ assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED)); -+ errno = EACCES; -+ assert_se(asprintf(&str, "%m") >= 0); -+ assert_se(streq(error.message, str)); -+ assert_se(error._need_free == 0); -+ -+ str = mfree(str); -+ sd_bus_error_free(&error); -+ -+ assert_se(sd_bus_error_set_errnof(&error, ENOANO, NULL) == -ENOANO); -+ assert_se(sd_bus_error_has_name(&error, "System.Error.ENOANO")); -+ errno = ENOANO; -+ assert_se(asprintf(&str, "%m") >= 0); -+ assert_se(streq(error.message, str)); -+ assert_se(error._need_free == 1); -+ -+ str = mfree(str); -+ sd_bus_error_free(&error); -+ -+ assert_se(sd_bus_error_set_errnof(&error, 100000, NULL) == -100000); -+ assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FAILED)); -+ errno = 100000; -+ assert_se(asprintf(&str, "%m") >= 0); -+ assert_se(streq(error.message, str)); -+ assert_se(error._need_free == 1); -+ -+ str = mfree(str); -+ sd_bus_error_free(&error); -+ -+ assert_se(sd_bus_error_set_errnof(NULL, 0, "hoge %s: %m", "foo") == 0); -+ assert_se(sd_bus_error_set_errnof(NULL, ENOANO, "hoge %s: %m", "foo") == -ENOANO); -+ -+ assert_se(sd_bus_error_set_errnof(&error, 0, "hoge %s: %m", "foo") == 0); -+ assert_se(!bus_error_is_dirty(&error)); -+ -+ assert_se(sd_bus_error_set_errnof(&error, EACCES, "hoge %s: %m", "foo") == -EACCES); -+ assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED)); -+ errno = EACCES; -+ assert_se(asprintf(&str, "hoge %s: %m", "foo") >= 0); -+ assert_se(streq(error.message, str)); -+ assert_se(error._need_free == 1); -+ -+ str = mfree(str); -+ sd_bus_error_free(&error); -+ -+ assert_se(sd_bus_error_set_errnof(&error, ENOANO, "hoge %s: %m", "foo") == -ENOANO); -+ assert_se(sd_bus_error_has_name(&error, "System.Error.ENOANO")); -+ errno = ENOANO; -+ assert_se(asprintf(&str, "hoge %s: %m", "foo") >= 0); -+ assert_se(streq(error.message, str)); -+ assert_se(error._need_free == 1); -+ -+ str = mfree(str); -+ sd_bus_error_free(&error); -+ -+ assert_se(sd_bus_error_set_errnof(&error, 100000, "hoge %s: %m", "foo") == -100000); -+ assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FAILED)); -+ errno = 100000; -+ assert_se(asprintf(&str, "hoge %s: %m", "foo") >= 0); -+ assert_se(streq(error.message, str)); -+ assert_se(error._need_free == 1); -+} -+ - int main(int argc, char *argv[]) { - dump_mapping_table(); - - test_error(); - test_errno_mapping_standard(); - test_errno_mapping_custom(); -+ test_sd_bus_error_set_errnof(); - - return 0; - } -diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c -index 82eb35e..1302fdb 100644 ---- a/src/libsystemd/sd-bus/test-bus-server.c -+++ b/src/libsystemd/sd-bus/test-bus-server.c -@@ -129,7 +129,7 @@ static int client(struct context *c) { - - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) -- return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); - - return 0; - } -diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c -index bbe7cd7..bdcbb10 100644 ---- a/src/libsystemd/sd-daemon/sd-daemon.c -+++ b/src/libsystemd/sd-daemon/sd-daemon.c -@@ -101,7 +101,7 @@ _public_ int sd_listen_fds_with_names(int unset_environment, char ***names) { - - e = getenv("LISTEN_FDNAMES"); - if (e) { -- n_names = strv_split_extract(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ n_names = strv_split_full(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS); - if (n_names < 0) { - unsetenv_all(unset_environment); - return n_names; -diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c -index 95dfc2f..f3bac17 100644 ---- a/src/libsystemd/sd-device/device-enumerator.c -+++ b/src/libsystemd/sd-device/device-enumerator.c -@@ -308,16 +308,15 @@ static bool match_sysattr_value(sd_device *device, const char *sysattr, const ch - static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) { - const char *sysattr; - const char *value; -- Iterator i; - - assert(enumerator); - assert(device); - -- HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr, i) -+ HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr) - if (match_sysattr_value(device, sysattr, value)) - return false; - -- HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr, i) -+ HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr) - if (!match_sysattr_value(device, sysattr, value)) - return false; - -@@ -327,7 +326,6 @@ static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) { - static bool match_property(sd_device_enumerator *enumerator, sd_device *device) { - const char *property; - const char *value; -- Iterator i; - - assert(enumerator); - assert(device); -@@ -335,7 +333,7 @@ static bool match_property(sd_device_enumerator *enumerator, sd_device *device) - if (hashmap_isempty(enumerator->match_property)) - return true; - -- HASHMAP_FOREACH_KEY(value, property, enumerator->match_property, i) { -+ HASHMAP_FOREACH_KEY(value, property, enumerator->match_property) { - const char *property_dev, *value_dev; - - FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev) { -@@ -358,12 +356,11 @@ static bool match_property(sd_device_enumerator *enumerator, sd_device *device) - - static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) { - const char *tag; -- Iterator i; - - assert(enumerator); - assert(device); - -- SET_FOREACH(tag, enumerator->match_tag, i) -+ SET_FOREACH(tag, enumerator->match_tag) - if (!sd_device_has_tag(device, tag)) - return false; - -@@ -372,7 +369,6 @@ static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) { - - static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) { - const char *syspath_parent, *syspath; -- Iterator i; - - assert(enumerator); - assert(device); -@@ -382,7 +378,7 @@ static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) { - - assert_se(sd_device_get_syspath(device, &syspath) >= 0); - -- SET_FOREACH(syspath_parent, enumerator->match_parent, i) -+ SET_FOREACH(syspath_parent, enumerator->match_parent) - if (path_startswith(syspath, syspath_parent)) - return true; - -@@ -391,7 +387,6 @@ static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) { - - static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) { - const char *sysname_match; -- Iterator i; - - assert(enumerator); - assert(sysname); -@@ -399,7 +394,7 @@ static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) - if (set_isempty(enumerator->match_sysname)) - return true; - -- SET_FOREACH(sysname_match, enumerator->match_sysname, i) -+ SET_FOREACH(sysname_match, enumerator->match_sysname) - if (fnmatch(sysname_match, sysname, 0) == 0) - return true; - -@@ -496,21 +491,20 @@ static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, - - static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) { - const char *subsystem_match; -- Iterator i; - - assert(enumerator); - - if (!subsystem) - return false; - -- SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem, i) -+ SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem) - if (fnmatch(subsystem_match, subsystem, 0) == 0) - return false; - - if (set_isempty(enumerator->match_subsystem)) - return true; - -- SET_FOREACH(subsystem_match, enumerator->match_subsystem, i) -+ SET_FOREACH(subsystem_match, enumerator->match_subsystem) - if (fnmatch(subsystem_match, subsystem, 0) == 0) - return true; - -@@ -626,12 +620,11 @@ static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const c - - static int enumerator_scan_devices_tags(sd_device_enumerator *enumerator) { - const char *tag; -- Iterator i; - int r = 0; - - assert(enumerator); - -- SET_FOREACH(tag, enumerator->match_tag, i) { -+ SET_FOREACH(tag, enumerator->match_tag) { - int k; - - k = enumerator_scan_devices_tag(enumerator, tag); -@@ -722,9 +715,8 @@ static int parent_crawl_children(sd_device_enumerator *enumerator, const char *p - static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) { - const char *path; - int r = 0, k; -- Iterator i; - -- SET_FOREACH(path, enumerator->match_parent, i) { -+ SET_FOREACH(path, enumerator->match_parent) { - k = parent_add_child(enumerator, path); - if (k < 0) - r = k; -diff --git a/src/libsystemd/sd-device/device-internal.h b/src/libsystemd/sd-device/device-internal.h -index 1fe5c1a..9c6b8a3 100644 ---- a/src/libsystemd/sd-device/device-internal.h -+++ b/src/libsystemd/sd-device/device-internal.h -@@ -28,10 +28,10 @@ struct sd_device { - Set *sysattrs; /* names of sysattrs */ - Iterator sysattrs_iterator; - -- Set *tags; -- Iterator tags_iterator; -+ Set *all_tags, *current_tags; -+ Iterator all_tags_iterator, current_tags_iterator; -+ uint64_t all_tags_iterator_generation, current_tags_iterator_generation; /* generation when iteration was started */ - uint64_t tags_generation; /* changes whenever the tags are changed */ -- uint64_t tags_iterator_generation; /* generation when iteration was started */ - - Set *devlinks; - Iterator devlinks_iterator; -@@ -71,7 +71,7 @@ struct sd_device { - - bool parent_set:1; /* no need to try to reload parent */ - bool sysattrs_read:1; /* don't try to re-read sysattrs once read */ -- bool property_tags_outdated:1; /* need to update TAGS= property */ -+ bool property_tags_outdated:1; /* need to update TAGS= or CURRENT_TAGS= property */ - bool property_devlinks_outdated:1; /* need to update DEVLINKS= property */ - bool properties_buf_outdated:1; /* need to reread hashmap */ - bool sysname_set:1; /* don't reread sysname */ -diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c -index bed45da..43646e1 100644 ---- a/src/libsystemd/sd-device/device-monitor.c -+++ b/src/libsystemd/sd-device/device-monitor.c -@@ -91,18 +91,9 @@ int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor - } - - _public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) { -- int r, n = (int) size; -- - assert_return(m, -EINVAL); -- assert_return((size_t) n == size, -EINVAL); -- -- if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n) < 0) { -- r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n); -- if (r < 0) -- return r; -- } - -- return 0; -+ return fd_set_rcvbuf(m->sock, size, false); - } - - int device_monitor_disconnect(sd_device_monitor *m) { -@@ -353,7 +344,6 @@ DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_monitor, sd_device_monitor, devic - - static int passes_filter(sd_device_monitor *m, sd_device *device) { - const char *tag, *subsystem, *devtype, *s, *d = NULL; -- Iterator i; - int r; - - assert_return(m, -EINVAL); -@@ -370,7 +360,7 @@ static int passes_filter(sd_device_monitor *m, sd_device *device) { - if (r < 0 && r != -ENOENT) - return r; - -- HASHMAP_FOREACH_KEY(devtype, subsystem, m->subsystem_filter, i) { -+ HASHMAP_FOREACH_KEY(devtype, subsystem, m->subsystem_filter) { - if (!streq(s, subsystem)) - continue; - -@@ -390,7 +380,7 @@ tag: - if (set_isempty(m->tag_filter)) - return 1; - -- SET_FOREACH(tag, m->tag_filter, i) -+ SET_FOREACH(tag, m->tag_filter) - if (sd_device_has_tag(device, tag) > 0) - return 1; - -@@ -631,7 +621,6 @@ _public_ int sd_device_monitor_filter_update(sd_device_monitor *m) { - struct sock_fprog filter; - const char *subsystem, *devtype, *tag; - unsigned i = 0; -- Iterator it; - - assert_return(m, -EINVAL); - -@@ -655,7 +644,7 @@ _public_ int sd_device_monitor_filter_update(sd_device_monitor *m) { - int tag_matches = set_size(m->tag_filter); - - /* add all tags matches */ -- SET_FOREACH(tag, m->tag_filter, it) { -+ SET_FOREACH(tag, m->tag_filter) { - uint64_t tag_bloom_bits = string_bloom64(tag); - uint32_t tag_bloom_hi = tag_bloom_bits >> 32; - uint32_t tag_bloom_lo = tag_bloom_bits & 0xffffffff; -@@ -682,7 +671,7 @@ _public_ int sd_device_monitor_filter_update(sd_device_monitor *m) { - - /* add all subsystem matches */ - if (!hashmap_isempty(m->subsystem_filter)) { -- HASHMAP_FOREACH_KEY(devtype, subsystem, m->subsystem_filter, it) { -+ HASHMAP_FOREACH_KEY(devtype, subsystem, m->subsystem_filter) { - uint32_t hash = string_hash32(subsystem); - - /* load device subsystem value in A */ -diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c -index 1e61732..dc16d55 100644 ---- a/src/libsystemd/sd-device/device-private.c -+++ b/src/libsystemd/sd-device/device-private.c -@@ -316,32 +316,32 @@ static int device_amend(sd_device *device, const char *key, const char *value) { - if (r < 0) - return log_device_debug_errno(device, r, "sd-device: Failed to set SEQNUM to '%s': %m", value); - } else if (streq(key, "DEVLINKS")) { -- const char *word, *state; -- size_t l; -+ for (const char *p = value;;) { -+ _cleanup_free_ char *word = NULL; - -- FOREACH_WORD(word, l, value, state) { -- char devlink[l + 1]; -- -- strncpy(devlink, word, l); -- devlink[l] = '\0'; -+ r = extract_first_word(&p, &word, NULL, 0); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; - -- r = device_add_devlink(device, devlink); -+ r = device_add_devlink(device, word); - if (r < 0) -- return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", devlink); -+ return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", word); - } -- } else if (streq(key, "TAGS")) { -- const char *word, *state; -- size_t l; -+ } else if (STR_IN_SET(key, "TAGS", "CURRENT_TAGS")) { -+ for (const char *p = value;;) { -+ _cleanup_free_ char *word = NULL; - -- FOREACH_WORD_SEPARATOR(word, l, value, ":", state) { -- char tag[l + 1]; -- -- (void) strncpy(tag, word, l); -- tag[l] = '\0'; -+ r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; - -- r = device_add_tag(device, tag); -+ r = device_add_tag(device, word, streq(key, "CURRENT_TAGS")); - if (r < 0) -- return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", tag); -+ return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", word); - } - } else { - r = device_add_property_internal(device, key, value); -@@ -731,7 +731,6 @@ int device_new_from_stat_rdev(sd_device **ret, const struct stat *st) { - - int device_copy_properties(sd_device *device_dst, sd_device *device_src) { - const char *property, *value; -- Iterator i; - int r; - - assert(device_dst); -@@ -741,13 +740,13 @@ int device_copy_properties(sd_device *device_dst, sd_device *device_src) { - if (r < 0) - return r; - -- ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties_db, i) { -+ ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties_db) { - r = device_add_property_aux(device_dst, property, value, true); - if (r < 0) - return r; - } - -- ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties, i) { -+ ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties) { - r = device_add_property_aux(device_dst, property, value, false); - if (r < 0) - return r; -@@ -759,8 +758,8 @@ int device_copy_properties(sd_device *device_dst, sd_device *device_src) { - void device_cleanup_tags(sd_device *device) { - assert(device); - -- set_free_free(device->tags); -- device->tags = NULL; -+ device->all_tags = set_free_free(device->all_tags); -+ device->current_tags = set_free_free(device->current_tags); - device->property_tags_outdated = true; - device->tags_generation++; - } -@@ -778,7 +777,7 @@ void device_remove_tag(sd_device *device, const char *tag) { - assert(device); - assert(tag); - -- free(set_remove(device->tags, tag)); -+ free(set_remove(device->current_tags, tag)); - device->property_tags_outdated = true; - device->tags_generation++; - } -@@ -846,7 +845,10 @@ static bool device_has_info(sd_device *device) { - if (!ordered_hashmap_isempty(device->properties_db)) - return true; - -- if (!set_isempty(device->tags)) -+ if (!set_isempty(device->all_tags)) -+ return true; -+ -+ if (!set_isempty(device->current_tags)) - return true; - - if (device->watch_handle >= 0) -@@ -917,7 +919,6 @@ int device_update_db(sd_device *device) { - - if (has_info) { - const char *property, *value, *tag; -- Iterator i; - - if (major(device->devnum) > 0) { - const char *devlink; -@@ -935,11 +936,14 @@ int device_update_db(sd_device *device) { - if (device->usec_initialized > 0) - fprintf(f, "I:"USEC_FMT"\n", device->usec_initialized); - -- ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db, i) -+ ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db) - fprintf(f, "E:%s=%s\n", property, value); - - FOREACH_DEVICE_TAG(device, tag) -- fprintf(f, "G:%s\n", tag); -+ fprintf(f, "G:%s\n", tag); /* Any tag */ -+ -+ SET_FOREACH(tag, device->current_tags) -+ fprintf(f, "Q:%s\n", tag); /* Current tag */ - } - - r = fflush_and_check(f); -diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h -index 2bde53e..1f1c4ca 100644 ---- a/src/libsystemd/sd-device/device-private.h -+++ b/src/libsystemd/sd-device/device-private.h -@@ -45,7 +45,7 @@ void device_set_devlink_priority(sd_device *device, int priority); - int device_ensure_usec_initialized(sd_device *device, sd_device *device_old); - int device_add_devlink(sd_device *device, const char *devlink); - int device_add_property(sd_device *device, const char *property, const char *value); --int device_add_tag(sd_device *device, const char *tag); -+int device_add_tag(sd_device *device, const char *tag, bool both); - void device_remove_tag(sd_device *device, const char *tag); - void device_cleanup_tags(sd_device *device); - void device_cleanup_devlinks(sd_device *device); -diff --git a/src/libsystemd/sd-device/device-util.h b/src/libsystemd/sd-device/device-util.h -index 1a1795d..032d1dc 100644 ---- a/src/libsystemd/sd-device/device-util.h -+++ b/src/libsystemd/sd-device/device-util.h -@@ -11,6 +11,11 @@ - tag; \ - tag = sd_device_get_tag_next(device)) - -+#define FOREACH_DEVICE_CURRENT_TAG(device, tag) \ -+ for (tag = sd_device_get_current_tag_first(device); \ -+ tag; \ -+ tag = sd_device_get_current_tag_next(device)) -+ - #define FOREACH_DEVICE_SYSATTR(device, attr) \ - for (attr = sd_device_get_sysattr_first(device); \ - attr; \ -@@ -31,7 +36,7 @@ - device; \ - device = sd_device_enumerator_get_subsystem_next(enumerator)) - --#define log_device_full(device, level, error, ...) \ -+#define log_device_full_errno(device, level, error, ...) \ - ({ \ - const char *_sysname = NULL; \ - sd_device *_d = (device); \ -@@ -41,17 +46,19 @@ - (void) sd_device_get_sysname(_d, &_sysname); \ - log_object_internal(_level, _error, PROJECT_FILE, __LINE__, __func__, \ - _sysname ? "DEVICE=" : NULL, _sysname, \ -- NULL, NULL, ##__VA_ARGS__); \ -+ NULL, NULL, __VA_ARGS__); \ - }) - --#define log_device_debug(device, ...) log_device_full(device, LOG_DEBUG, 0, ##__VA_ARGS__) --#define log_device_info(device, ...) log_device_full(device, LOG_INFO, 0, ##__VA_ARGS__) --#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, 0, ##__VA_ARGS__) --#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, 0, ##__VA_ARGS__) --#define log_device_error(device, ...) log_device_full(device, LOG_ERR, 0, ##__VA_ARGS__) -- --#define log_device_debug_errno(device, error, ...) log_device_full(device, LOG_DEBUG, error, ##__VA_ARGS__) --#define log_device_info_errno(device, error, ...) log_device_full(device, LOG_INFO, error, ##__VA_ARGS__) --#define log_device_notice_errno(device, error, ...) log_device_full(device, LOG_NOTICE, error, ##__VA_ARGS__) --#define log_device_warning_errno(device, error, ...) log_device_full(device, LOG_WARNING, error, ##__VA_ARGS__) --#define log_device_error_errno(device, error, ...) log_device_full(device, LOG_ERR, error, ##__VA_ARGS__) -+#define log_device_full(device, level, ...) (void) log_device_full_errno(device, level, 0, __VA_ARGS__) -+ -+#define log_device_debug(device, ...) log_device_full_errno(device, LOG_DEBUG, 0, __VA_ARGS__) -+#define log_device_info(device, ...) log_device_full(device, LOG_INFO, __VA_ARGS__) -+#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, __VA_ARGS__) -+#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, __VA_ARGS__) -+#define log_device_error(device, ...) log_device_full(device, LOG_ERR, __VA_ARGS__) -+ -+#define log_device_debug_errno(device, error, ...) log_device_full_errno(device, LOG_DEBUG, error, __VA_ARGS__) -+#define log_device_info_errno(device, error, ...) log_device_full_errno(device, LOG_INFO, error, __VA_ARGS__) -+#define log_device_notice_errno(device, error, ...) log_device_full_errno(device, LOG_NOTICE, error, __VA_ARGS__) -+#define log_device_warning_errno(device, error, ...) log_device_full_errno(device, LOG_WARNING, error, __VA_ARGS__) -+#define log_device_error_errno(device, error, ...) log_device_full_errno(device, LOG_ERR, error, __VA_ARGS__) -diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c -index 3bba17a..634c9a2 100644 ---- a/src/libsystemd/sd-device/sd-device.c -+++ b/src/libsystemd/sd-device/sd-device.c -@@ -69,7 +69,8 @@ static sd_device *device_free(sd_device *device) { - ordered_hashmap_free_free_free(device->properties_db); - hashmap_free_free_free(device->sysattr_values); - set_free(device->sysattrs); -- set_free(device->tags); -+ set_free(device->all_tags); -+ set_free(device->current_tags); - set_free(device->devlinks); - - return mfree(device); -@@ -1062,8 +1063,8 @@ static bool is_valid_tag(const char *tag) { - return !strchr(tag, ':') && !strchr(tag, ' '); - } - --int device_add_tag(sd_device *device, const char *tag) { -- int r; -+int device_add_tag(sd_device *device, const char *tag, bool both) { -+ int r, added; - - assert(device); - assert(tag); -@@ -1071,9 +1072,21 @@ int device_add_tag(sd_device *device, const char *tag) { - if (!is_valid_tag(tag)) - return -EINVAL; - -- r = set_put_strdup(&device->tags, tag); -- if (r < 0) -- return r; -+ /* Definitely add to the "all" list of tags (i.e. the sticky list) */ -+ added = set_put_strdup(&device->all_tags, tag); -+ if (added < 0) -+ return added; -+ -+ /* And optionally, also add it to the current list of tags */ -+ if (both) { -+ r = set_put_strdup(&device->current_tags, tag); -+ if (r < 0) { -+ if (added > 0) -+ (void) set_remove(device->all_tags, tag); -+ -+ return r; -+ } -+ } - - device->tags_generation++; - device->property_tags_outdated = true; -@@ -1151,8 +1164,9 @@ static int handle_db_line(sd_device *device, char key, const char *value) { - assert(value); - - switch (key) { -- case 'G': -- r = device_add_tag(device, value); -+ case 'G': /* Any tag */ -+ case 'Q': /* Current tag */ -+ r = device_add_tag(device, value, key == 'Q'); - if (r < 0) - return r; - -@@ -1407,10 +1421,10 @@ _public_ const char *sd_device_get_tag_first(sd_device *device) { - - (void) device_read_db(device); - -- device->tags_iterator_generation = device->tags_generation; -- device->tags_iterator = ITERATOR_FIRST; -+ device->all_tags_iterator_generation = device->tags_generation; -+ device->all_tags_iterator = ITERATOR_FIRST; - -- (void) set_iterate(device->tags, &device->tags_iterator, &v); -+ (void) set_iterate(device->all_tags, &device->all_tags_iterator, &v); - return v; - } - -@@ -1421,10 +1435,38 @@ _public_ const char *sd_device_get_tag_next(sd_device *device) { - - (void) device_read_db(device); - -- if (device->tags_iterator_generation != device->tags_generation) -+ if (device->all_tags_iterator_generation != device->tags_generation) -+ return NULL; -+ -+ (void) set_iterate(device->all_tags, &device->all_tags_iterator, &v); -+ return v; -+} -+ -+_public_ const char *sd_device_get_current_tag_first(sd_device *device) { -+ void *v; -+ -+ assert_return(device, NULL); -+ -+ (void) device_read_db(device); -+ -+ device->current_tags_iterator_generation = device->tags_generation; -+ device->current_tags_iterator = ITERATOR_FIRST; -+ -+ (void) set_iterate(device->current_tags, &device->current_tags_iterator, &v); -+ return v; -+} -+ -+_public_ const char *sd_device_get_current_tag_next(sd_device *device) { -+ void *v; -+ -+ assert_return(device, NULL); -+ -+ (void) device_read_db(device); -+ -+ if (device->current_tags_iterator_generation != device->tags_generation) - return NULL; - -- (void) set_iterate(device->tags, &device->tags_iterator, &v); -+ (void) set_iterate(device->current_tags, &device->current_tags_iterator, &v); - return v; - } - -@@ -1456,6 +1498,30 @@ _public_ const char *sd_device_get_devlink_next(sd_device *device) { - return v; - } - -+static char *join_string_set(Set *s) { -+ size_t ret_allocated = 0, ret_len; -+ _cleanup_free_ char *ret = NULL; -+ const char *tag; -+ -+ if (!GREEDY_REALLOC(ret, ret_allocated, 2)) -+ return NULL; -+ -+ strcpy(ret, ":"); -+ ret_len = 1; -+ -+ SET_FOREACH(tag, s) { -+ char *e; -+ -+ if (!GREEDY_REALLOC(ret, ret_allocated, ret_len + strlen(tag) + 2)) -+ return NULL; -+ -+ e = stpcpy(stpcpy(ret + ret_len, tag), ":"); -+ ret_len = e - ret; -+ } -+ -+ return TAKE_PTR(ret); -+} -+ - int device_properties_prepare(sd_device *device) { - int r; - -@@ -1494,26 +1560,27 @@ int device_properties_prepare(sd_device *device) { - - if (device->property_tags_outdated) { - _cleanup_free_ char *tags = NULL; -- size_t tags_allocated = 0, tags_len = 0; -- const char *tag; - -- if (!GREEDY_REALLOC(tags, tags_allocated, 2)) -+ tags = join_string_set(device->all_tags); -+ if (!tags) - return -ENOMEM; -- stpcpy(tags, ":"); -- tags_len++; -- -- for (tag = sd_device_get_tag_first(device); tag; tag = sd_device_get_tag_next(device)) { -- char *e; - -- if (!GREEDY_REALLOC(tags, tags_allocated, tags_len + strlen(tag) + 2)) -- return -ENOMEM; -- e = stpcpy(stpcpy(tags + tags_len, tag), ":"); -- tags_len = e - tags; -+ if (!streq(tags, ":")) { -+ r = device_add_property_internal(device, "TAGS", tags); -+ if (r < 0) -+ return r; - } - -- r = device_add_property_internal(device, "TAGS", tags); -- if (r < 0) -- return r; -+ free(tags); -+ tags = join_string_set(device->current_tags); -+ if (!tags) -+ return -ENOMEM; -+ -+ if (!streq(tags, ":")) { -+ r = device_add_property_internal(device, "CURRENT_TAGS", tags); -+ if (r < 0) -+ return r; -+ } - - device->property_tags_outdated = false; - } -@@ -1689,7 +1756,16 @@ _public_ int sd_device_has_tag(sd_device *device, const char *tag) { - - (void) device_read_db(device); - -- return !!set_contains(device->tags, tag); -+ return set_contains(device->all_tags, tag); -+} -+ -+_public_ int sd_device_has_current_tag(sd_device *device, const char *tag) { -+ assert_return(device, -EINVAL); -+ assert_return(tag, -EINVAL); -+ -+ (void) device_read_db(device); -+ -+ return set_contains(device->current_tags, tag); - } - - _public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **_value) { -@@ -1903,3 +1979,26 @@ _public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, - - return 0; - } -+ -+_public_ int sd_device_set_sysattr_valuef(sd_device *device, const char *sysattr, const char *format, ...) { -+ _cleanup_free_ char *value = NULL; -+ va_list ap; -+ int r; -+ -+ assert_return(device, -EINVAL); -+ assert_return(sysattr, -EINVAL); -+ -+ if (!format) { -+ device_remove_sysattr_value(device, sysattr); -+ return 0; -+ } -+ -+ va_start(ap, format); -+ r = vasprintf(&value, format, ap); -+ va_end(ap); -+ -+ if (r < 0) -+ return -ENOMEM; -+ -+ return sd_device_set_sysattr_value(device, sysattr, value); -+} -diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c -index 860eb04..7dd43f2 100644 ---- a/src/libsystemd/sd-event/sd-event.c -+++ b/src/libsystemd/sd-event/sd-event.c -@@ -1146,6 +1146,31 @@ _public_ int sd_event_add_time( - return 0; - } - -+_public_ int sd_event_add_time_relative( -+ sd_event *e, -+ sd_event_source **ret, -+ clockid_t clock, -+ uint64_t usec, -+ uint64_t accuracy, -+ sd_event_time_handler_t callback, -+ void *userdata) { -+ -+ usec_t t; -+ int r; -+ -+ /* Same as sd_event_add_time() but operates relative to the event loop's current point in time, and -+ * checks for overflow. */ -+ -+ r = sd_event_now(e, clock, &t); -+ if (r < 0) -+ return r; -+ -+ if (usec >= USEC_INFINITY - t) -+ return -EOVERFLOW; -+ -+ return sd_event_add_time(e, ret, clock, t + usec, accuracy, callback, userdata); -+} -+ - static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { - assert(s); - -@@ -2402,6 +2427,23 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { - return 0; - } - -+_public_ int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec) { -+ usec_t t; -+ int r; -+ -+ assert_return(s, -EINVAL); -+ assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); -+ -+ r = sd_event_now(s->event, event_source_type_to_clock(s->type), &t); -+ if (r < 0) -+ return r; -+ -+ if (usec >= USEC_INFINITY - t) -+ return -EOVERFLOW; -+ -+ return sd_event_source_set_time(s, t + usec); -+} -+ - _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) { - assert_return(s, -EINVAL); - assert_return(usec, -EINVAL); -@@ -2828,7 +2870,6 @@ static int process_timer( - - static int process_child(sd_event *e) { - sd_event_source *s; -- Iterator i; - int r; - - assert(e); -@@ -2853,7 +2894,7 @@ static int process_child(sd_event *e) { - the callback still sees the process as a zombie. - */ - -- HASHMAP_FOREACH(s, e->child_sources, i) { -+ HASHMAP_FOREACH(s, e->child_sources) { - assert(s->type == SOURCE_CHILD); - - if (s->pending) -@@ -3058,12 +3099,11 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { - - if (d->buffer.ev.mask & IN_Q_OVERFLOW) { - struct inode_data *inode_data; -- Iterator i; - - /* The queue overran, let's pass this event to all event sources connected to this inotify - * object */ - -- HASHMAP_FOREACH(inode_data, d->inodes, i) { -+ HASHMAP_FOREACH(inode_data, d->inodes) { - sd_event_source *s; - - LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { -@@ -3161,12 +3201,11 @@ static int source_dispatch(sd_event_source *s) { - - if (s->type != SOURCE_POST) { - sd_event_source *z; -- Iterator i; - - /* If we execute a non-post source, let's mark all - * post sources as pending */ - -- SET_FOREACH(z, s->event->post_sources, i) { -+ SET_FOREACH(z, s->event->post_sources) { - if (z->enabled == SD_EVENT_OFF) - continue; - -diff --git a/src/libsystemd/sd-hwdb/hwdb-util.c b/src/libsystemd/sd-hwdb/hwdb-util.c -index 5c75216..1b642b6 100644 ---- a/src/libsystemd/sd-hwdb/hwdb-util.c -+++ b/src/libsystemd/sd-hwdb/hwdb-util.c -@@ -477,7 +477,7 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr - _cleanup_fclose_ FILE *f = NULL; - _cleanup_strv_free_ char **match_list = NULL; - uint32_t line_number = 0; -- int r = 0, err; -+ int r, err; - - f = fopen(filename, "re"); - if (!f) -diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c -index 746c895..d8baa6f 100644 ---- a/src/libsystemd/sd-login/sd-login.c -+++ b/src/libsystemd/sd-login/sd-login.c -@@ -12,6 +12,7 @@ - #include "dirent-util.h" - #include "env-file.h" - #include "escape.h" -+#include "extract-word.h" - #include "fd-util.h" - #include "format-util.h" - #include "fs-util.h" -@@ -22,6 +23,7 @@ - #include "parse-util.h" - #include "path-util.h" - #include "socket-util.h" -+#include "stdio-util.h" - #include "string-util.h" - #include "strv.h" - #include "user-util.h" -@@ -331,35 +333,29 @@ static int file_of_seat(const char *seat, char **_p) { - } - - _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) { -- _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL; -- size_t l; -+ _cleanup_free_ char *filename = NULL, *content = NULL; - int r; -- const char *word, *variable, *state; - - assert_return(uid_is_valid(uid), -EINVAL); - -- r = file_of_seat(seat, &p); -+ r = file_of_seat(seat, &filename); - if (r < 0) - return r; - -- variable = require_active ? "ACTIVE_UID" : "UIDS"; -- -- r = parse_env_file(NULL, p, variable, &s); -+ r = parse_env_file(NULL, filename, -+ require_active ? "ACTIVE_UID" : "UIDS", -+ &content); - if (r == -ENOENT) - return 0; - if (r < 0) - return r; -- if (isempty(s)) -+ if (isempty(content)) - return 0; - -- if (asprintf(&t, UID_FMT, uid) < 0) -- return -ENOMEM; -+ char t[DECIMAL_STR_MAX(uid_t)]; -+ xsprintf(t, UID_FMT, uid); - -- FOREACH_WORD(word, l, s, state) -- if (strneq(t, word, l)) -- return 1; -- -- return 0; -+ return string_contains_word(content, ",", t); - } - - static int uid_get_array(uid_t uid, const char *variable, char ***array) { -@@ -382,7 +378,7 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) { - if (r < 0) - return r; - -- a = strv_split(s, " "); -+ a = strv_split(s, NULL); - if (!a) - return -ENOMEM; - -@@ -654,73 +650,70 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) { - return 0; - } - --_public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) { -- _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; -- _cleanup_strv_free_ char **a = NULL; -- _cleanup_free_ uid_t *b = NULL; -- unsigned n = 0; -+_public_ int sd_seat_get_sessions( -+ const char *seat, -+ char ***ret_sessions, -+ uid_t **ret_uids, -+ unsigned *ret_n_uids) { -+ -+ _cleanup_free_ char *fname = NULL, *session_line = NULL, *uid_line = NULL; -+ _cleanup_strv_free_ char **sessions = NULL; -+ _cleanup_free_ uid_t *uids = NULL; -+ unsigned n_sessions = 0; - int r; - -- r = file_of_seat(seat, &p); -+ r = file_of_seat(seat, &fname); - if (r < 0) - return r; - -- r = parse_env_file(NULL, p, -- "SESSIONS", &s, -- "UIDS", &t); -+ r = parse_env_file(NULL, fname, -+ "SESSIONS", &session_line, -+ "UIDS", &uid_line); - if (r == -ENOENT) - return -ENXIO; - if (r < 0) - return r; - -- if (s) { -- a = strv_split(s, " "); -- if (!a) -+ if (session_line) { -+ sessions = strv_split(session_line, NULL); -+ if (!sessions) - return -ENOMEM; -- } - -- if (uids && t) { -- const char *word, *state; -- size_t l; -+ n_sessions = strv_length(sessions); -+ }; - -- FOREACH_WORD(word, l, t, state) -- n++; -- -- if (n > 0) { -- unsigned i = 0; -- -- b = new(uid_t, n); -- if (!b) -- return -ENOMEM; -+ if (ret_uids && uid_line) { -+ uids = new(uid_t, n_sessions); -+ if (!uids) -+ return -ENOMEM; - -- FOREACH_WORD(word, l, t, state) { -- _cleanup_free_ char *k = NULL; -+ size_t n = 0; -+ for (const char *p = uid_line;;) { -+ _cleanup_free_ char *word = NULL; - -- k = strndup(word, l); -- if (!k) -- return -ENOMEM; -+ r = extract_first_word(&p, &word, NULL, 0); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; - -- r = parse_uid(k, b + i); -- if (r < 0) -- return r; -- -- i++; -- } -+ r = parse_uid(word, &uids[n++]); -+ if (r < 0) -+ return r; - } -- } -- -- r = (int) strv_length(a); -- -- if (sessions) -- *sessions = TAKE_PTR(a); - -- if (uids) -- *uids = TAKE_PTR(b); -+ if (n != n_sessions) -+ return -EUCLEAN; -+ } - -- if (n_uids) -- *n_uids = n; -+ if (ret_sessions) -+ *ret_sessions = TAKE_PTR(sessions); -+ if (ret_uids) -+ *ret_uids = TAKE_PTR(uids); -+ if (ret_n_uids) -+ *ret_n_uids = n_sessions; - -- return r; -+ return n_sessions; - } - - static int seat_get_can(const char *seat, const char *variable) { -@@ -901,47 +894,53 @@ _public_ int sd_machine_get_class(const char *machine, char **class) { - return 0; - } - --_public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) { -- _cleanup_free_ char *netif = NULL; -- size_t l, allocated = 0, nr = 0; -- int *ni = NULL; -- const char *p, *word, *state; -+_public_ int sd_machine_get_ifindices(const char *machine, int **ret_ifindices) { -+ _cleanup_free_ char *netif_line = NULL; -+ const char *p; - int r; - - assert_return(machine_name_is_valid(machine), -EINVAL); -- assert_return(ifindices, -EINVAL); - - p = strjoina("/run/systemd/machines/", machine); -- r = parse_env_file(NULL, p, "NETIF", &netif); -+ r = parse_env_file(NULL, p, "NETIF", &netif_line); - if (r == -ENOENT) - return -ENXIO; - if (r < 0) - return r; -- if (!netif) { -- *ifindices = NULL; -+ if (!netif_line) { -+ *ret_ifindices = NULL; - return 0; - } - -- FOREACH_WORD(word, l, netif, state) { -- char buf[l+1]; -- int ifi; -+ _cleanup_strv_free_ char **tt = strv_split(netif_line, NULL); -+ if (!tt) -+ return -ENOMEM; - -- *(char*) (mempcpy(buf, word, l)) = 0; -+ _cleanup_free_ int *ifindices = NULL; -+ if (ret_ifindices) { -+ ifindices = new(int, strv_length(tt)); -+ if (!ifindices) -+ return -ENOMEM; -+ } - -- ifi = parse_ifindex(buf); -- if (ifi < 0) -- continue; -+ size_t n = 0; -+ for (size_t i = 0; tt[i]; i++) { -+ int ind; - -- if (!GREEDY_REALLOC(ni, allocated, nr+1)) { -- free(ni); -- return -ENOMEM; -- } -+ ind = parse_ifindex(tt[i]); -+ if (ind < 0) -+ /* Return -EUCLEAN to distinguish from -EINVAL for invalid args */ -+ return ind == -EINVAL ? -EUCLEAN : ind; - -- ni[nr++] = ifi; -+ if (ret_ifindices) -+ ifindices[n] = ind; -+ n++; - } - -- *ifindices = ni; -- return nr; -+ if (ret_ifindices) -+ *ret_ifindices = TAKE_PTR(ifindices); -+ -+ return n; - } - - static int MONITOR_TO_FD(sd_login_monitor *m) { -diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c -index 060458a..23d2025 100644 ---- a/src/libsystemd/sd-netlink/netlink-types.c -+++ b/src/libsystemd/sd-netlink/netlink-types.c -@@ -968,6 +968,15 @@ static const NLTypeSystem rtnl_tca_type_system = { - .types = rtnl_tca_types, - }; - -+static const NLType mdb_types[] = { -+ [MDBA_SET_ENTRY] = { .size = sizeof(struct br_port_msg) }, -+}; -+ -+static const NLTypeSystem rtnl_mdb_type_system = { -+ .count = ELEMENTSOF(mdb_types), -+ .types = mdb_types, -+}; -+ - static const NLType error_types[] = { - [NLMSGERR_ATTR_MSG] = { .type = NETLINK_TYPE_STRING }, - [NLMSGERR_ATTR_OFFS] = { .type = NETLINK_TYPE_U32 }, -@@ -1012,6 +1021,9 @@ static const NLType rtnl_types[] = { - [RTM_NEWTCLASS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) }, - [RTM_DELTCLASS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) }, - [RTM_GETTCLASS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) }, -+ [RTM_NEWMDB] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system, .size = sizeof(struct br_port_msg) }, -+ [RTM_DELMDB] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system, .size = sizeof(struct br_port_msg) }, -+ [RTM_GETMDB] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system, .size = sizeof(struct br_port_msg) }, - }; - - const NLTypeSystem rtnl_type_system_root = { -diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h -index 04e6a98..ddf5686 100644 ---- a/src/libsystemd/sd-netlink/netlink-util.h -+++ b/src/libsystemd/sd-netlink/netlink-util.h -@@ -51,6 +51,10 @@ static inline bool rtnl_message_type_is_tclass(uint16_t type) { - return IN_SET(type, RTM_NEWTCLASS, RTM_DELTCLASS, RTM_GETTCLASS); - } - -+static inline bool rtnl_message_type_is_mdb(uint16_t type) { -+ return IN_SET(type, RTM_NEWMDB, RTM_DELMDB, RTM_GETMDB); -+} -+ - int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name); - int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu); - int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret); -diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c -index 7689bf6..2681500 100644 ---- a/src/libsystemd/sd-netlink/rtnl-message.c -+++ b/src/libsystemd/sd-netlink/rtnl-message.c -@@ -2,6 +2,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -436,7 +437,7 @@ int sd_rtnl_message_new_neigh(sd_netlink *rtnl, sd_netlink_message **ret, uint16 - int r; - - assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL); -- assert_return(IN_SET(ndm_family, AF_UNSPEC, AF_INET, AF_INET6, PF_BRIDGE), -EINVAL); -+ assert_return(IN_SET(ndm_family, AF_UNSPEC, AF_INET, AF_INET6, AF_BRIDGE), -EINVAL); - assert_return(ret, -EINVAL); - - r = message_new(rtnl, ret, nlmsg_type); -@@ -1120,3 +1121,24 @@ int sd_rtnl_message_set_tclass_handle(sd_netlink_message *m, uint32_t handle) { - - return 0; - } -+ -+int sd_rtnl_message_new_mdb(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int mdb_ifindex) { -+ struct br_port_msg *bpm; -+ int r; -+ -+ assert_return(rtnl_message_type_is_mdb(nlmsg_type), -EINVAL); -+ assert_return(ret, -EINVAL); -+ -+ r = message_new(rtnl, ret, nlmsg_type); -+ if (r < 0) -+ return r; -+ -+ if (nlmsg_type == RTM_NEWMDB) -+ (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; -+ -+ bpm = NLMSG_DATA((*ret)->hdr); -+ bpm->family = AF_BRIDGE; -+ bpm->ifindex = mdb_ifindex; -+ -+ return 0; -+} -diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c -index 91670ee..ff0886d 100644 ---- a/src/libsystemd/sd-netlink/sd-netlink.c -+++ b/src/libsystemd/sd-netlink/sd-netlink.c -@@ -495,10 +495,8 @@ static int rtnl_poll(sd_netlink *rtnl, bool need_more, uint64_t timeout_usec) { - m = timeout_usec; - - r = fd_wait_for_event(rtnl->fd, e, m); -- if (r < 0) -+ if (r <= 0) - return r; -- if (r == 0) -- return 0; - - return 1; - } -diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c -index 9598ad8..f9d79bc 100644 ---- a/src/libsystemd/sd-netlink/test-netlink.c -+++ b/src/libsystemd/sd-netlink/test-netlink.c -@@ -21,7 +21,7 @@ static void test_message_link_bridge(sd_netlink *rtnl) { - uint32_t cost; - - assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0); -- assert_se(sd_rtnl_message_link_set_family(message, PF_BRIDGE) >= 0); -+ assert_se(sd_rtnl_message_link_set_family(message, AF_BRIDGE) >= 0); - assert_se(sd_netlink_message_open_container(message, IFLA_PROTINFO) >= 0); - assert_se(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0); - assert_se(sd_netlink_message_close_container(message) >= 0); -diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c -index 736795d..26d2341 100644 ---- a/src/libsystemd/sd-path/sd-path.c -+++ b/src/libsystemd/sd-path/sd-path.c -@@ -321,7 +321,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { - return from_user_dir("XDG_DESKTOP_DIR", buffer, ret); - - case SD_PATH_SYSTEMD_UTIL: -- *ret = ROOTPREFIX "/lib/systemd"; -+ *ret = ROOTPREFIX_NOSLASH "/lib/systemd"; - return 0; - - case SD_PATH_SYSTEMD_SYSTEM_UNIT: -@@ -329,7 +329,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { - return 0; - - case SD_PATH_SYSTEMD_SYSTEM_PRESET: -- *ret = ROOTPREFIX "/lib/systemd/system-preset"; -+ *ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-preset"; - return 0; - - case SD_PATH_SYSTEMD_USER_UNIT: -@@ -337,7 +337,7 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { - return 0; - - case SD_PATH_SYSTEMD_USER_PRESET: -- *ret = ROOTPREFIX "/lib/systemd/user-preset"; -+ *ret = ROOTPREFIX_NOSLASH "/lib/systemd/user-preset"; - return 0; - - case SD_PATH_SYSTEMD_SYSTEM_CONF: -@@ -357,33 +357,31 @@ static int get_path(uint64_t type, char **buffer, const char **ret) { - return 0; - - case SD_PATH_SYSTEMD_SLEEP: -- *ret = ROOTPREFIX "/lib/systemd/system-sleep"; -+ *ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-sleep"; - return 0; - - case SD_PATH_SYSTEMD_SHUTDOWN: -- *ret = ROOTPREFIX "/lib/systemd/system-shutdown"; -+ *ret = ROOTPREFIX_NOSLASH "/lib/systemd/system-shutdown"; - return 0; - -- /* FIXME: systemd.pc uses ${prefix}, but CONF_PATHS_NULSTR doesn't. -- * Should ${prefix} use in systemd.pc be removed? */ - case SD_PATH_TMPFILES: - *ret = "/usr/lib/tmpfiles.d"; - return 0; - - case SD_PATH_SYSUSERS: -- *ret = ROOTPREFIX "/lib/sysusers.d"; -+ *ret = ROOTPREFIX_NOSLASH "/lib/sysusers.d"; - return 0; - - case SD_PATH_SYSCTL: -- *ret = ROOTPREFIX "/lib/sysctl.d"; -+ *ret = ROOTPREFIX_NOSLASH "/lib/sysctl.d"; - return 0; - - case SD_PATH_BINFMT: -- *ret = ROOTPREFIX "/lib/binfmt.d"; -+ *ret = ROOTPREFIX_NOSLASH "/lib/binfmt.d"; - return 0; - - case SD_PATH_MODULES_LOAD: -- *ret = ROOTPREFIX "/lib/modules-load.d"; -+ *ret = ROOTPREFIX_NOSLASH "/lib/modules-load.d"; - return 0; - - case SD_PATH_CATALOG: -diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c -index 9d4057f..1dc3203 100644 ---- a/src/libsystemd/sd-resolve/sd-resolve.c -+++ b/src/libsystemd/sd-resolve/sd-resolve.c -@@ -496,10 +496,10 @@ _public_ int sd_resolve_new(sd_resolve **ret) { - for (i = 0; i < _FD_MAX; i++) - resolve->fds[i] = -1; - -- if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD) < 0) -+ if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD) < 0) - return -errno; - -- if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD) < 0) -+ if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD) < 0) - return -errno; - - for (i = 0; i < _FD_MAX; i++) -diff --git a/src/libsystemd/sd-resolve/test-resolve.c b/src/libsystemd/sd-resolve/test-resolve.c -index 38a78ee..8377c66 100644 ---- a/src/libsystemd/sd-resolve/test-resolve.c -+++ b/src/libsystemd/sd-resolve/test-resolve.c -@@ -53,10 +53,10 @@ static int getnameinfo_handler(sd_resolve_query *q, int ret, const char *host, c - int main(int argc, char *argv[]) { - _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q1 = NULL, *q2 = NULL; - _cleanup_(sd_resolve_unrefp) sd_resolve *resolve = NULL; -- int r = 0; -+ int r; - - struct addrinfo hints = { -- .ai_family = PF_UNSPEC, -+ .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_flags = AI_CANONNAME - }; -diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c -index b993309..704a09d 100644 ---- a/src/libudev/libudev-device.c -+++ b/src/libudev/libudev-device.c -@@ -56,12 +56,13 @@ struct udev_device { - - struct udev_list *properties; - uint64_t properties_generation; -- struct udev_list *tags; -- uint64_t tags_generation; -+ struct udev_list *all_tags, *current_tags; -+ uint64_t all_tags_generation, current_tags_generation; - struct udev_list *devlinks; - uint64_t devlinks_generation; - bool properties_read:1; -- bool tags_read:1; -+ bool all_tags_read:1; -+ bool current_tags_read:1; - bool devlinks_read:1; - struct udev_list *sysattrs; - bool sysattrs_read; -@@ -199,7 +200,7 @@ _public_ const char *udev_device_get_property_value(struct udev_device *udev_dev - } - - struct udev_device *udev_device_new(struct udev *udev, sd_device *device) { -- _cleanup_(udev_list_freep) struct udev_list *properties = NULL, *tags = NULL, *sysattrs = NULL, *devlinks = NULL; -+ _cleanup_(udev_list_freep) struct udev_list *properties = NULL, *all_tags = NULL, *current_tags = NULL, *sysattrs = NULL, *devlinks = NULL; - struct udev_device *udev_device; - - assert(device); -@@ -207,8 +208,11 @@ struct udev_device *udev_device_new(struct udev *udev, sd_device *device) { - properties = udev_list_new(true); - if (!properties) - return_with_errno(NULL, ENOMEM); -- tags = udev_list_new(true); -- if (!tags) -+ all_tags = udev_list_new(true); -+ if (!all_tags) -+ return_with_errno(NULL, ENOMEM); -+ current_tags = udev_list_new(true); -+ if (!current_tags) - return_with_errno(NULL, ENOMEM); - sysattrs = udev_list_new(true); - if (!sysattrs) -@@ -226,7 +230,8 @@ struct udev_device *udev_device_new(struct udev *udev, sd_device *device) { - .udev = udev, - .device = sd_device_ref(device), - .properties = TAKE_PTR(properties), -- .tags = TAKE_PTR(tags), -+ .all_tags = TAKE_PTR(all_tags), -+ .current_tags = TAKE_PTR(current_tags), - .sysattrs = TAKE_PTR(sysattrs), - .devlinks = TAKE_PTR(devlinks), - }; -@@ -475,7 +480,8 @@ static struct udev_device *udev_device_free(struct udev_device *udev_device) { - - udev_list_free(udev_device->properties); - udev_list_free(udev_device->sysattrs); -- udev_list_free(udev_device->tags); -+ udev_list_free(udev_device->all_tags); -+ udev_list_free(udev_device->current_tags); - udev_list_free(udev_device->devlinks); - - return mfree(udev_device); -@@ -834,21 +840,41 @@ _public_ int udev_device_get_is_initialized(struct udev_device *udev_device) { - _public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) { - assert_return_errno(udev_device, NULL, EINVAL); - -- if (device_get_tags_generation(udev_device->device) != udev_device->tags_generation || -- !udev_device->tags_read) { -+ if (device_get_tags_generation(udev_device->device) != udev_device->all_tags_generation || -+ !udev_device->all_tags_read) { - const char *tag; - -- udev_list_cleanup(udev_device->tags); -+ udev_list_cleanup(udev_device->all_tags); - - FOREACH_DEVICE_TAG(udev_device->device, tag) -- if (!udev_list_entry_add(udev_device->tags, tag, NULL)) -+ if (!udev_list_entry_add(udev_device->all_tags, tag, NULL)) -+ return_with_errno(NULL, ENOMEM); -+ -+ udev_device->all_tags_read = true; -+ udev_device->all_tags_generation = device_get_tags_generation(udev_device->device); -+ } -+ -+ return udev_list_get_entry(udev_device->all_tags); -+} -+ -+_public_ struct udev_list_entry *udev_device_get_current_tags_list_entry(struct udev_device *udev_device) { -+ assert_return_errno(udev_device, NULL, EINVAL); -+ -+ if (device_get_tags_generation(udev_device->device) != udev_device->current_tags_generation || -+ !udev_device->current_tags_read) { -+ const char *tag; -+ -+ udev_list_cleanup(udev_device->current_tags); -+ -+ FOREACH_DEVICE_CURRENT_TAG(udev_device->device, tag) -+ if (!udev_list_entry_add(udev_device->current_tags, tag, NULL)) - return_with_errno(NULL, ENOMEM); - -- udev_device->tags_read = true; -- udev_device->tags_generation = device_get_tags_generation(udev_device->device); -+ udev_device->current_tags_read = true; -+ udev_device->current_tags_generation = device_get_tags_generation(udev_device->device); - } - -- return udev_list_get_entry(udev_device->tags); -+ return udev_list_get_entry(udev_device->current_tags); - } - - /** -@@ -866,6 +892,12 @@ _public_ int udev_device_has_tag(struct udev_device *udev_device, const char *ta - return sd_device_has_tag(udev_device->device, tag) > 0; - } - -+_public_ int udev_device_has_current_tag(struct udev_device *udev_device, const char *tag) { -+ assert_return(udev_device, 0); -+ -+ return sd_device_has_current_tag(udev_device->device, tag) > 0; -+} -+ - sd_device *udev_device_get_sd_device(struct udev_device *udev_device) { - assert(udev_device); - -diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c -index 95a9942..3b22976 100644 ---- a/src/libudev/libudev-list.c -+++ b/src/libudev/libudev-list.c -@@ -157,7 +157,6 @@ struct udev_list_entry *udev_list_get_entry(struct udev_list *list) { - else { - _cleanup_free_ struct udev_list_entry **buf = NULL; - struct udev_list_entry *entry, **p; -- Iterator i; - size_t j; - - buf = new(struct udev_list_entry *, n); -@@ -165,7 +164,7 @@ struct udev_list_entry *udev_list_get_entry(struct udev_list *list) { - return NULL; - - p = buf; -- HASHMAP_FOREACH(entry, list->unique_entries, i) -+ HASHMAP_FOREACH(entry, list->unique_entries) - *p++ = entry; - - typesafe_qsort(buf, n, udev_list_entry_compare_func); -diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h -index 02c2e5e..c9d0bf2 100644 ---- a/src/libudev/libudev.h -+++ b/src/libudev/libudev.h -@@ -82,6 +82,7 @@ int udev_device_get_is_initialized(struct udev_device *udev_device); - struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device); - struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device); - struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device); -+struct udev_list_entry *udev_device_get_current_tags_list_entry(struct udev_device *udev_device); - struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device); - const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key); - const char *udev_device_get_driver(struct udev_device *udev_device); -@@ -92,6 +93,7 @@ unsigned long long int udev_device_get_usec_since_initialized(struct udev_device - const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr); - int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value); - int udev_device_has_tag(struct udev_device *udev_device, const char *tag); -+int udev_device_has_current_tag(struct udev_device *udev_device, const char *tag); - - /* - * udev_monitor -diff --git a/src/libudev/libudev.sym b/src/libudev/libudev.sym -index fb2e03e..bad8313 100644 ---- a/src/libudev/libudev.sym -+++ b/src/libudev/libudev.sym -@@ -118,3 +118,9 @@ global: - udev_queue_flush; - udev_queue_get_fd; - } LIBUDEV_199; -+ -+LIBUDEV_247 { -+global: -+ udev_device_has_current_tag; -+ udev_device_get_current_tags_list_entry; -+} LIBUDEV_215; -diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c -index 233d081..8e0cb74 100644 ---- a/src/locale/keymap-util.c -+++ b/src/locale/keymap-util.c -@@ -251,7 +251,7 @@ int x11_read_data(Context *c, sd_bus_message *m) { - if (in_section && first_word(l, "Option")) { - _cleanup_strv_free_ char **a = NULL; - -- r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_UNQUOTE); -+ r = strv_split_full(&a, l, WHITESPACE, EXTRACT_UNQUOTE); - if (r < 0) - return r; - -@@ -274,7 +274,7 @@ int x11_read_data(Context *c, sd_bus_message *m) { - } else if (!in_section && first_word(l, "Section")) { - _cleanup_strv_free_ char **a = NULL; - -- r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_UNQUOTE); -+ r = strv_split_full(&a, l, WHITESPACE, EXTRACT_UNQUOTE); - if (r < 0) - return -ENOMEM; - -@@ -489,7 +489,7 @@ static int read_next_mapping(const char* filename, - if (IN_SET(l[0], 0, '#')) - continue; - -- r = strv_split_extract(&b, l, WHITESPACE, EXTRACT_UNQUOTE); -+ r = strv_split_full(&b, l, WHITESPACE, EXTRACT_UNQUOTE); - if (r < 0) - return r; - -diff --git a/src/locale/localectl.c b/src/locale/localectl.c -index e0664de..4895c29 100644 ---- a/src/locale/localectl.c -+++ b/src/locale/localectl.c -@@ -178,7 +178,7 @@ static int set_locale(int argc, char **argv, void *userdata) { - - r = sd_bus_call(bus, m, 0, &error, NULL); - if (r < 0) -- return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); - - return 0; - } -@@ -218,7 +218,7 @@ static int set_vconsole_keymap(int argc, char **argv, void *userdata) { - NULL, - "ssbb", map, toggle_map, arg_convert, arg_ask_password); - if (r < 0) -- return log_error_errno(r, "Failed to set keymap: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to set keymap: %s", bus_error_message(&error, r)); - - return 0; - } -@@ -260,7 +260,7 @@ static int set_x11_keymap(int argc, char **argv, void *userdata) { - "ssssbb", layout, model, variant, options, - arg_convert, arg_ask_password); - if (r < 0) -- return log_error_errno(r, "Failed to set keymap: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to set keymap: %s", bus_error_message(&error, r)); - - return 0; - } -diff --git a/src/login/loginctl.c b/src/login/loginctl.c -index 4297a51..bc4f25f 100644 ---- a/src/login/loginctl.c -+++ b/src/login/loginctl.c -@@ -1022,7 +1022,7 @@ static int kill_session(int argc, char *argv[], void *userdata) { - &error, NULL, - "ssi", argv[i], arg_kill_who, arg_signal); - if (r < 0) -- return log_error_errno(r, "Could not kill session: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not kill session: %s", bus_error_message(&error, r)); - } - - return 0; -@@ -1071,7 +1071,7 @@ static int enable_linger(int argc, char *argv[], void *userdata) { - &error, NULL, - "ubb", (uint32_t) uid, b, true); - if (r < 0) -- return log_error_errno(r, "Could not enable linger: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not enable linger: %s", bus_error_message(&error, r)); - } - - return 0; -@@ -1096,7 +1096,7 @@ static int terminate_user(int argc, char *argv[], void *userdata) { - - r = bus_call_method(bus, bus_login_mgr, "TerminateUser", &error, NULL, "u", (uint32_t) uid); - if (r < 0) -- return log_error_errno(r, "Could not terminate user: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not terminate user: %s", bus_error_message(&error, r)); - } - - return 0; -@@ -1129,7 +1129,7 @@ static int kill_user(int argc, char *argv[], void *userdata) { - &error, NULL, - "ui", (uint32_t) uid, arg_signal); - if (r < 0) -- return log_error_errno(r, "Could not kill user: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not kill user: %s", bus_error_message(&error, r)); - } - - return 0; -@@ -1154,7 +1154,7 @@ static int attach(int argc, char *argv[], void *userdata) { - &error, NULL, - "ssb", argv[1], argv[i], true); - if (r < 0) -- return log_error_errno(r, "Could not attach device: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not attach device: %s", bus_error_message(&error, r)); - } - - return 0; -@@ -1172,7 +1172,7 @@ static int flush_devices(int argc, char *argv[], void *userdata) { - - r = bus_call_method(bus, bus_login_mgr, "FlushDevices", &error, NULL, "b", true); - if (r < 0) -- return log_error_errno(r, "Could not flush devices: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not flush devices: %s", bus_error_message(&error, r)); - - return 0; - } -@@ -1194,7 +1194,7 @@ static int lock_sessions(int argc, char *argv[], void *userdata) { - &error, NULL, - NULL); - if (r < 0) -- return log_error_errno(r, "Could not lock sessions: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not lock sessions: %s", bus_error_message(&error, r)); - - return 0; - } -@@ -1213,7 +1213,7 @@ static int terminate_seat(int argc, char *argv[], void *userdata) { - - r = bus_call_method(bus, bus_login_mgr, "TerminateSeat", &error, NULL, "s", argv[i]); - if (r < 0) -- return log_error_errno(r, "Could not terminate seat: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not terminate seat: %s", bus_error_message(&error, r)); - } - - return 0; -@@ -1337,7 +1337,7 @@ static int parse_argv(int argc, char *argv[]) { - return log_oom(); - - /* If the user asked for a particular -- * property, show it to him, even if it is -+ * property, show it to them, even if it is - * empty. */ - arg_all = true; - break; -diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c -index 76af208..0cb3b0b 100644 ---- a/src/login/logind-acl.c -+++ b/src/login/logind-acl.c -@@ -168,7 +168,6 @@ int devnode_acl_all(const char *seat, - _cleanup_closedir_ DIR *dir = NULL; - struct dirent *dent; - sd_device *d; -- Iterator i; - char *n; - int r; - -@@ -195,6 +194,10 @@ int devnode_acl_all(const char *seat, - FOREACH_DEVICE(e, d) { - const char *node, *sn; - -+ /* Make sure the tag is still in place */ -+ if (sd_device_has_current_tag(d, "uaccess") <= 0) -+ continue; -+ - if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn)) - sn = "seat0"; - -@@ -235,7 +238,7 @@ int devnode_acl_all(const char *seat, - } - - r = 0; -- SET_FOREACH(n, nodes, i) { -+ SET_FOREACH(n, nodes) { - int k; - - log_debug("Changing ACLs at %s for seat %s (uid "UID_FMT"→"UID_FMT"%s%s)", -diff --git a/src/login/logind-button.c b/src/login/logind-button.c -index 9ec235a..096cf70 100644 ---- a/src/login/logind-button.c -+++ b/src/login/logind-button.c -@@ -14,7 +14,7 @@ - #include "string-util.h" - #include "util.h" - --#define CONST_MAX4(a, b, c, d) CONST_MAX(CONST_MAX(a, b), CONST_MAX(c, d)) -+#define CONST_MAX5(a, b, c, d, e) CONST_MAX(CONST_MAX(a, b), CONST_MAX(CONST_MAX(c, d), e)) - - #define ULONG_BITS (sizeof(unsigned long)*8) - -@@ -158,7 +158,20 @@ static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *u - manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true); - break; - -- /* The kernel is a bit confused here: -+ /* The kernel naming is a bit confusing here: -+ KEY_RESTART was probably introduced for media playback purposes, but -+ is now being predominantly used to indicate device reboot. -+ */ -+ -+ case KEY_RESTART: -+ log_struct(LOG_INFO, -+ LOG_MESSAGE("Reboot key pressed."), -+ "MESSAGE_ID=" SD_MESSAGE_REBOOT_KEY_STR); -+ -+ manager_handle_action(b->manager, INHIBIT_HANDLE_REBOOT_KEY, b->manager->handle_reboot_key, b->manager->reboot_key_ignore_inhibited, true); -+ break; -+ -+ /* The kernel naming is a bit confusing here: - - KEY_SLEEP = suspend-to-ram, which everybody else calls "suspend" - KEY_SUSPEND = suspend-to-disk, which everybody else calls "hibernate" -@@ -231,7 +244,7 @@ static int button_suitable(int fd) { - return -errno; - - if (bitset_get(types, EV_KEY)) { -- unsigned long keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1]; -+ unsigned long keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/ULONG_BITS+1]; - - if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof keys), keys) < 0) - return -errno; -@@ -239,7 +252,8 @@ static int button_suitable(int fd) { - if (bitset_get(keys, KEY_POWER) || - bitset_get(keys, KEY_POWER2) || - bitset_get(keys, KEY_SLEEP) || -- bitset_get(keys, KEY_SUSPEND)) -+ bitset_get(keys, KEY_SUSPEND) || -+ bitset_get(keys, KEY_RESTART)) - return true; - } - -@@ -260,7 +274,7 @@ static int button_suitable(int fd) { - static int button_set_mask(const char *name, int fd) { - unsigned long - types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {}, -- keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1] = {}, -+ keys[CONST_MAX5(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND, KEY_RESTART)/ULONG_BITS+1] = {}, - switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {}; - struct input_mask mask; - -@@ -285,6 +299,7 @@ static int button_set_mask(const char *name, int fd) { - bitset_put(keys, KEY_POWER2); - bitset_put(keys, KEY_SLEEP); - bitset_put(keys, KEY_SUSPEND); -+ bitset_put(keys, KEY_RESTART); - - mask = (struct input_mask) { - .type = EV_KEY, -diff --git a/src/login/logind-core.c b/src/login/logind-core.c -index 480ec19..a685b8e 100644 ---- a/src/login/logind-core.c -+++ b/src/login/logind-core.c -@@ -43,10 +43,12 @@ void manager_reset_config(Manager *m) { - m->handle_lid_switch = HANDLE_SUSPEND; - m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID; - m->handle_lid_switch_docked = HANDLE_IGNORE; -+ m->handle_reboot_key = HANDLE_REBOOT; - m->power_key_ignore_inhibited = false; - m->suspend_key_ignore_inhibited = false; - m->hibernate_key_ignore_inhibited = false; - m->lid_switch_ignore_inhibited = true; -+ m->reboot_key_ignore_inhibited = false; - - m->holdoff_timeout_usec = 30 * USEC_PER_SEC; - -@@ -243,7 +245,8 @@ int manager_process_seat_device(Manager *m, sd_device *d) { - - assert(m); - -- if (device_for_action(d, DEVICE_ACTION_REMOVE)) { -+ if (device_for_action(d, DEVICE_ACTION_REMOVE) || -+ sd_device_has_current_tag(d, "seat") <= 0) { - const char *syspath; - - r = sd_device_get_syspath(d, &syspath); -@@ -271,7 +274,7 @@ int manager_process_seat_device(Manager *m, sd_device *d) { - } - - seat = hashmap_get(m->seats, sn); -- master = sd_device_has_tag(d, "master-of-seat") > 0; -+ master = sd_device_has_current_tag(d, "master-of-seat") > 0; - - /* Ignore non-master devices for unknown seats */ - if (!master && !seat) -@@ -313,7 +316,8 @@ int manager_process_button_device(Manager *m, sd_device *d) { - if (r < 0) - return r; - -- if (device_for_action(d, DEVICE_ACTION_REMOVE)) { -+ if (device_for_action(d, DEVICE_ACTION_REMOVE) || -+ sd_device_has_current_tag(d, "power-switch") <= 0) { - - b = hashmap_get(m->buttons, sysname); - if (!b) -@@ -389,13 +393,12 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t) { - Session *s; - bool idle_hint; - dual_timestamp ts = DUAL_TIMESTAMP_NULL; -- Iterator i; - - assert(m); - - idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL); - -- HASHMAP_FOREACH(s, m->sessions, i) { -+ HASHMAP_FOREACH(s, m->sessions) { - dual_timestamp k; - int ih; - -@@ -463,12 +466,14 @@ int config_parse_n_autovts( - - r = safe_atou(rvalue, &o); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse number of autovts, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse number of autovts, ignoring: %s", rvalue); - return 0; - } - - if (o > 15) { -- log_syntax(unit, LOG_ERR, filename, line, r, "A maximum of 15 autovts are supported, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "A maximum of 15 autovts are supported, ignoring: %s", rvalue); - return 0; - } - -@@ -478,7 +483,7 @@ int config_parse_n_autovts( - - static int vt_is_busy(unsigned vtnr) { - struct vt_stat vt_stat; -- int r = 0; -+ int r; - _cleanup_close_ int fd; - - assert(vtnr >= 1); -@@ -545,10 +550,9 @@ int manager_spawn_autovt(Manager *m, unsigned vtnr) { - } - - bool manager_is_lid_closed(Manager *m) { -- Iterator i; - Button *b; - -- HASHMAP_FOREACH(b, m->buttons, i) -+ HASHMAP_FOREACH(b, m->buttons) - if (b->lid_closed) - return true; - -@@ -556,10 +560,9 @@ bool manager_is_lid_closed(Manager *m) { - } - - static bool manager_is_docked(Manager *m) { -- Iterator i; - Button *b; - -- HASHMAP_FOREACH(b, m->buttons, i) -+ HASHMAP_FOREACH(b, m->buttons) - if (b->docked) - return true; - -@@ -676,6 +679,8 @@ bool manager_all_buttons_ignored(Manager *m) { - return false; - if (m->handle_lid_switch_docked != HANDLE_IGNORE) - return false; -+ if (m->handle_reboot_key != HANDLE_IGNORE) -+ return false; - - return true; - } -diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c -index 75a4830..9f16b7f 100644 ---- a/src/login/logind-dbus.c -+++ b/src/login/logind-dbus.c -@@ -516,7 +516,6 @@ static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_ - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; - Session *session; -- Iterator i; - int r; - - assert(message); -@@ -530,7 +529,7 @@ static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_ - if (r < 0) - return r; - -- HASHMAP_FOREACH(session, m->sessions, i) { -+ HASHMAP_FOREACH(session, m->sessions) { - _cleanup_free_ char *p = NULL; - - p = session_bus_path(session); -@@ -558,7 +557,6 @@ static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_err - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; - User *user; -- Iterator i; - int r; - - assert(message); -@@ -572,7 +570,7 @@ static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_err - if (r < 0) - return r; - -- HASHMAP_FOREACH(user, m->users, i) { -+ HASHMAP_FOREACH(user, m->users) { - _cleanup_free_ char *p = NULL; - - p = user_bus_path(user); -@@ -598,7 +596,6 @@ static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_err - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; - Seat *seat; -- Iterator i; - int r; - - assert(message); -@@ -612,7 +609,7 @@ static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_err - if (r < 0) - return r; - -- HASHMAP_FOREACH(seat, m->seats, i) { -+ HASHMAP_FOREACH(seat, m->seats) { - _cleanup_free_ char *p = NULL; - - p = seat_bus_path(seat); -@@ -635,7 +632,6 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; - Inhibitor *inhibitor; -- Iterator i; - int r; - - assert(message); -@@ -649,7 +645,7 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu - if (r < 0) - return r; - -- HASHMAP_FOREACH(inhibitor, m->inhibitors, i) { -+ HASHMAP_FOREACH(inhibitor, m->inhibitors) { - - r = sd_bus_message_append(reply, "(ssssuu)", - strempty(inhibit_what_to_string(inhibitor->what)), -@@ -1361,7 +1357,7 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) { - if (r < 0) - return r; - -- if (sd_device_has_tag(d, "seat") <= 0) -+ if (sd_device_has_current_tag(d, "seat") <= 0) - return -ENODEV; - - if (sd_device_get_property_value(d, "ID_FOR_SEAT", &id_for_seat) < 0) -@@ -1499,13 +1495,12 @@ static int have_multiple_sessions( - uid_t uid) { - - Session *session; -- Iterator i; - - assert(m); - - /* Check for other users' sessions. Greeter sessions do not - * count, and non-login sessions do not count either. */ -- HASHMAP_FOREACH(session, m->sessions, i) -+ HASHMAP_FOREACH(session, m->sessions) - if (session->class == SESSION_USER && - session->user->user_record->uid != uid) - return true; -@@ -1720,26 +1715,26 @@ static int delay_shutdown_or_sleep( - const char *unit_name) { - - int r; -- usec_t timeout_val; - - assert(m); - assert(w >= 0); - assert(w < _INHIBIT_WHAT_MAX); - assert(unit_name); - -- timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max; -- - if (m->inhibit_timeout_source) { -- r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val); -+ r = sd_event_source_set_time_relative(m->inhibit_timeout_source, m->inhibit_delay_max); - if (r < 0) -- return log_error_errno(r, "sd_event_source_set_time() failed: %m"); -+ return log_error_errno(r, "sd_event_source_set_time_relative() failed: %m"); - - r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT); - if (r < 0) - return log_error_errno(r, "sd_event_source_set_enabled() failed: %m"); - } else { -- r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC, -- timeout_val, 0, manager_inhibit_timeout_handler, m); -+ r = sd_event_add_time_relative( -+ m->event, -+ &m->inhibit_timeout_source, -+ CLOCK_MONOTONIC, m->inhibit_delay_max, 0, -+ manager_inhibit_timeout_handler, m); - if (r < 0) - return r; - } -@@ -3245,6 +3240,7 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error - w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" : - w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" : - w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" : -+ w == INHIBIT_HANDLE_REBOOT_KEY ? "org.freedesktop.login1.inhibit-handle-reboot-key" : - w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" : - "org.freedesktop.login1.inhibit-handle-lid-switch", - NULL, -@@ -3900,7 +3896,6 @@ int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_err - int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) { - Manager *m = userdata; - Session *session; -- Iterator i; - int b, r; - - assert(message); -@@ -3918,7 +3913,7 @@ int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error - /* systemd finished reloading, let's recheck all our sessions */ - log_debug("System manager has been reloaded, rechecking sessions..."); - -- HASHMAP_FOREACH(session, m->sessions, i) -+ HASHMAP_FOREACH(session, m->sessions) - session_add_to_gc_queue(session); - - return 0; -@@ -4077,13 +4072,13 @@ int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, - return strdup_job(reply, job); - } - --int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { -+int manager_stop_unit(Manager *manager, const char *unit, const char *job_mode, sd_bus_error *error, char **ret_job) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - int r; - - assert(manager); - assert(unit); -- assert(job); -+ assert(ret_job); - - r = bus_call_method( - manager->bus, -@@ -4091,12 +4086,12 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c - "StopUnit", - error, - &reply, -- "ss", unit, "fail"); -+ "ss", unit, job_mode ?: "fail"); - if (r < 0) { -- if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || -- sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) { -+ if (sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT, -+ BUS_ERROR_LOAD_FAILED)) { - -- *job = NULL; -+ *ret_job = NULL; - sd_bus_error_free(error); - return 0; - } -@@ -4104,7 +4099,7 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c - return r; - } - -- return strdup_job(reply, job); -+ return strdup_job(reply, ret_job); - } - - int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *ret_error) { -@@ -4129,9 +4124,9 @@ int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *ret - NULL, - NULL); - if (r < 0) { -- if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || -- sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED) || -- sd_bus_error_has_name(&error, BUS_ERROR_SCOPE_NOT_RUNNING)) -+ if (sd_bus_error_has_names(&error, BUS_ERROR_NO_SUCH_UNIT, -+ BUS_ERROR_LOAD_FAILED, -+ BUS_ERROR_SCOPE_NOT_RUNNING)) - return 0; - - sd_bus_error_move(ret_error, &error); -@@ -4180,14 +4175,14 @@ int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret - if (r < 0) { - /* systemd might have dropped off momentarily, let's - * not make this an error */ -- if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || -- sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) -+ if (sd_bus_error_has_names(&error, SD_BUS_ERROR_NO_REPLY, -+ SD_BUS_ERROR_DISCONNECTED)) - return true; - - /* If the unit is already unloaded then it's not - * active */ -- if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || -- sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) -+ if (sd_bus_error_has_names(&error, BUS_ERROR_NO_SUCH_UNIT, -+ BUS_ERROR_LOAD_FAILED)) - return false; - - sd_bus_error_move(ret_error, &error); -@@ -4219,8 +4214,8 @@ int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *ret_ - &reply, - "s"); - if (r < 0) { -- if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || -- sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) -+ if (sd_bus_error_has_names(&error, SD_BUS_ERROR_NO_REPLY, -+ SD_BUS_ERROR_DISCONNECTED)) - return true; - - if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) -diff --git a/src/login/logind-dbus.h b/src/login/logind-dbus.h -index 7707587..3e0f380 100644 ---- a/src/login/logind-dbus.h -+++ b/src/login/logind-dbus.h -@@ -25,7 +25,7 @@ int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_ - - int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job); - int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); --int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); -+int manager_stop_unit(Manager *manager, const char *unit, const char *job_mode, sd_bus_error *error, char **job); - int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error); - int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error); - int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *error); -diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf -index 73d96ff..2c152d2 100644 ---- a/src/login/logind-gperf.gperf -+++ b/src/login/logind-gperf.gperf -@@ -30,10 +30,12 @@ Login.HandleHibernateKey, config_parse_handle_action, 0, offse - Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch) - Login.HandleLidSwitchExternalPower, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep) - Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked) -+Login.HandleRebootKey, config_parse_handle_action, 0, offsetof(Manager, handle_reboot_key) - Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited) - Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited) - Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited) - Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited) -+Login.RebootKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, reboot_key_ignore_inhibited) - Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec) - Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action) - Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec) -diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c -index 1d335f9..f52d5ba 100644 ---- a/src/login/logind-inhibit.c -+++ b/src/login/logind-inhibit.c -@@ -8,6 +8,7 @@ - - #include "alloc-util.h" - #include "env-file.h" -+#include "errno-list.h" - #include "escape.h" - #include "fd-util.h" - #include "fileio.h" -@@ -372,12 +373,11 @@ bool inhibitor_is_orphan(Inhibitor *i) { - - InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) { - Inhibitor *i; -- Iterator j; - InhibitWhat what = 0; - - assert(m); - -- HASHMAP_FOREACH(i, m->inhibitors, j) -+ HASHMAP_FOREACH(i, m->inhibitors) - if (i->mode == mm && i->started) - what |= i->what; - -@@ -413,14 +413,13 @@ bool manager_is_inhibited( - Inhibitor **offending) { - - Inhibitor *i; -- Iterator j; - struct dual_timestamp ts = DUAL_TIMESTAMP_NULL; - bool inhibited = false; - - assert(m); - assert(w > 0 && w < _INHIBIT_WHAT_MAX); - -- HASHMAP_FOREACH(i, m->inhibitors, j) { -+ HASHMAP_FOREACH(i, m->inhibitors) { - if (!i->started) - continue; - -@@ -453,7 +452,15 @@ bool manager_is_inhibited( - } - - const char *inhibit_what_to_string(InhibitWhat w) { -- static thread_local char buffer[97]; -+ static thread_local char buffer[STRLEN( -+ "shutdown:" -+ "sleep:" -+ "idle:" -+ "handle-power-key:" -+ "handle-suspend-key:" -+ "handle-hibernate-key:" -+ "handle-lid-switch:" -+ "handle-reboot-key")+1]; - char *p; - - if (w < 0 || w >= _INHIBIT_WHAT_MAX) -@@ -474,6 +481,8 @@ const char *inhibit_what_to_string(InhibitWhat w) { - p = stpcpy(p, "handle-hibernate-key:"); - if (w & INHIBIT_HANDLE_LID_SWITCH) - p = stpcpy(p, "handle-lid-switch:"); -+ if (w & INHIBIT_HANDLE_REBOOT_KEY) -+ p = stpcpy(p, "handle-reboot-key:"); - - if (p > buffer) - *(p-1) = 0; -@@ -483,31 +492,41 @@ const char *inhibit_what_to_string(InhibitWhat w) { - return buffer; - } - --InhibitWhat inhibit_what_from_string(const char *s) { -+int inhibit_what_from_string(const char *s) { - InhibitWhat what = 0; -- const char *word, *state; -- size_t l; - -- FOREACH_WORD_SEPARATOR(word, l, s, ":", state) { -- if (l == 8 && strneq(word, "shutdown", l)) -+ for (const char *p = s;;) { -+ _cleanup_free_ char *word = NULL; -+ int r; -+ -+ /* A sanity check that our return values fit in an int */ -+ assert_cc((int) _INHIBIT_WHAT_MAX == _INHIBIT_WHAT_MAX); -+ -+ r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return what; -+ -+ if (streq(word, "shutdown")) - what |= INHIBIT_SHUTDOWN; -- else if (l == 5 && strneq(word, "sleep", l)) -+ else if (streq(word, "sleep")) - what |= INHIBIT_SLEEP; -- else if (l == 4 && strneq(word, "idle", l)) -+ else if (streq(word, "idle")) - what |= INHIBIT_IDLE; -- else if (l == 16 && strneq(word, "handle-power-key", l)) -+ else if (streq(word, "handle-power-key")) - what |= INHIBIT_HANDLE_POWER_KEY; -- else if (l == 18 && strneq(word, "handle-suspend-key", l)) -+ else if (streq(word, "handle-suspend-key")) - what |= INHIBIT_HANDLE_SUSPEND_KEY; -- else if (l == 20 && strneq(word, "handle-hibernate-key", l)) -+ else if (streq(word, "handle-hibernate-key")) - what |= INHIBIT_HANDLE_HIBERNATE_KEY; -- else if (l == 17 && strneq(word, "handle-lid-switch", l)) -+ else if (streq(word, "handle-lid-switch")) - what |= INHIBIT_HANDLE_LID_SWITCH; -+ else if (streq(word, "handle-reboot-key")) -+ what |= INHIBIT_HANDLE_REBOOT_KEY; - else - return _INHIBIT_WHAT_INVALID; - } -- -- return what; - } - - static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = { -diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h -index cea67a0..e5d4426 100644 ---- a/src/login/logind-inhibit.h -+++ b/src/login/logind-inhibit.h -@@ -11,7 +11,8 @@ typedef enum InhibitWhat { - INHIBIT_HANDLE_SUSPEND_KEY = 1 << 4, - INHIBIT_HANDLE_HIBERNATE_KEY = 1 << 5, - INHIBIT_HANDLE_LID_SWITCH = 1 << 6, -- _INHIBIT_WHAT_MAX = 1 << 7, -+ INHIBIT_HANDLE_REBOOT_KEY = 1 << 7, -+ _INHIBIT_WHAT_MAX = 1 << 8, - _INHIBIT_WHAT_INVALID = -1 - } InhibitWhat; - -@@ -66,7 +67,7 @@ InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm); - bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since, bool ignore_inactive, bool ignore_uid, uid_t uid, Inhibitor **offending); - - const char *inhibit_what_to_string(InhibitWhat k); --InhibitWhat inhibit_what_from_string(const char *s); -+int inhibit_what_from_string(const char *s); - - const char *inhibit_mode_to_string(InhibitMode k); - InhibitMode inhibit_mode_from_string(const char *s); -diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c -index a917652..a945132 100644 ---- a/src/login/logind-seat-dbus.c -+++ b/src/login/logind-seat-dbus.c -@@ -152,7 +152,7 @@ int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_er - if (r == 0) - return 1; /* Will call us back */ - -- r = seat_stop_sessions(s, true); -+ r = seat_stop_sessions(s, /* force = */ true); - if (r < 0) - return r; - -@@ -345,14 +345,13 @@ static int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, c - sd_bus_message *message; - Manager *m = userdata; - Seat *seat; -- Iterator i; - int r; - - assert(bus); - assert(path); - assert(nodes); - -- HASHMAP_FOREACH(seat, m->seats, i) { -+ HASHMAP_FOREACH(seat, m->seats) { - char *p; - - p = seat_bus_path(seat); -diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c -index 5ed20eb..ccc5ac8 100644 ---- a/src/login/logind-session-dbus.c -+++ b/src/login/logind-session-dbus.c -@@ -178,7 +178,7 @@ int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus - if (r == 0) - return 1; /* Will call us back */ - -- r = session_stop(s, true); -+ r = session_stop(s, /* force = */ true); - if (r < 0) - return r; - -@@ -635,14 +635,13 @@ static int session_node_enumerator(sd_bus *bus, const char *path, void *userdata - sd_bus_message *message; - Manager *m = userdata; - Session *session; -- Iterator i; - int r; - - assert(bus); - assert(path); - assert(nodes); - -- HASHMAP_FOREACH(session, m->sessions, i) { -+ HASHMAP_FOREACH(session, m->sessions) { - char *p; - - p = session_bus_path(session); -@@ -753,12 +752,11 @@ int session_send_lock(Session *s, bool lock) { - - int session_send_lock_all(Manager *m, bool lock) { - Session *session; -- Iterator i; - int r = 0; - - assert(m); - -- HASHMAP_FOREACH(session, m->sessions, i) { -+ HASHMAP_FOREACH(session, m->sessions) { - int k; - - k = session_send_lock(session, lock); -diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c -index 23df756..5cef516 100644 ---- a/src/login/logind-session-device.c -+++ b/src/login/logind-session-device.c -@@ -408,7 +408,6 @@ void session_device_free(SessionDevice *sd) { - - void session_device_complete_pause(SessionDevice *sd) { - SessionDevice *iter; -- Iterator i; - - if (!sd->active) - return; -@@ -416,7 +415,7 @@ void session_device_complete_pause(SessionDevice *sd) { - session_device_stop(sd); - - /* if not all devices are paused, wait for further completion events */ -- HASHMAP_FOREACH(iter, sd->session->devices, i) -+ HASHMAP_FOREACH(iter, sd->session->devices) - if (iter->active) - return; - -@@ -426,11 +425,10 @@ void session_device_complete_pause(SessionDevice *sd) { - - void session_device_resume_all(Session *s) { - SessionDevice *sd; -- Iterator i; - - assert(s); - -- HASHMAP_FOREACH(sd, s->devices, i) { -+ HASHMAP_FOREACH(sd, s->devices) { - if (sd->active) - continue; - -@@ -445,11 +443,10 @@ void session_device_resume_all(Session *s) { - - void session_device_pause_all(Session *s) { - SessionDevice *sd; -- Iterator i; - - assert(s); - -- HASHMAP_FOREACH(sd, s->devices, i) { -+ HASHMAP_FOREACH(sd, s->devices) { - if (!sd->active) - continue; - -@@ -461,11 +458,10 @@ void session_device_pause_all(Session *s) { - unsigned session_device_try_pause_all(Session *s) { - unsigned num_pending = 0; - SessionDevice *sd; -- Iterator i; - - assert(s); - -- HASHMAP_FOREACH(sd, s->devices, i) { -+ HASHMAP_FOREACH(sd, s->devices) { - if (!sd->active) - continue; - -diff --git a/src/login/logind-session.c b/src/login/logind-session.c -index 5c4149e..cbb5549 100644 ---- a/src/login/logind-session.c -+++ b/src/login/logind-session.c -@@ -189,11 +189,10 @@ int session_set_leader(Session *s, pid_t pid) { - - static void session_save_devices(Session *s, FILE *f) { - SessionDevice *sd; -- Iterator i; - - if (!hashmap_isempty(s->devices)) { - fprintf(f, "DEVICES="); -- HASHMAP_FOREACH(sd, s->devices, i) -+ HASHMAP_FOREACH(sd, s->devices) - fprintf(f, "%u:%u ", major(sd->dev), minor(sd->dev)); - fprintf(f, "\n"); - } -@@ -202,7 +201,7 @@ static void session_save_devices(Session *s, FILE *f) { - int session_save(Session *s) { - _cleanup_free_ char *temp_path = NULL; - _cleanup_fclose_ FILE *f = NULL; -- int r = 0; -+ int r; - - assert(s); - -@@ -736,10 +735,9 @@ int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) { - /* Send signals */ - session_send_signal(s, true); - user_send_changed(s->user, "Display", NULL); -- if (s->seat) { -- if (s->seat->active == s) -- seat_send_changed(s->seat, "ActiveSession", NULL); -- } -+ -+ if (s->seat && s->seat->active == s) -+ seat_send_changed(s->seat, "ActiveSession", NULL); - - return 0; - } -@@ -770,7 +768,7 @@ static int session_stop_scope(Session *s, bool force) { - (s->user->user_record->kill_processes > 0 || - manager_shall_kill(s->manager, s->user->user_record->user_name)))) { - -- r = manager_stop_unit(s->manager, s->scope, &error, &s->scope_job); -+ r = manager_stop_unit(s->manager, s->scope, force ? "replace" : "fail", &error, &s->scope_job); - if (r < 0) { - if (force) - return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r)); -@@ -883,7 +881,7 @@ static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *us - assert(es); - assert(s); - -- session_stop(s, false); -+ session_stop(s, /* force = */ false); - return 0; - } - -@@ -896,11 +894,12 @@ int session_release(Session *s) { - if (s->timer_event_source) - return 0; - -- return sd_event_add_time(s->manager->event, -- &s->timer_event_source, -- CLOCK_MONOTONIC, -- usec_add(now(CLOCK_MONOTONIC), RELEASE_USEC), 0, -- release_timeout_callback, s); -+ return sd_event_add_time_relative( -+ s->manager->event, -+ &s->timer_event_source, -+ CLOCK_MONOTONIC, -+ RELEASE_USEC, 0, -+ release_timeout_callback, s); - } - - bool session_is_active(Session *s) { -@@ -1054,7 +1053,7 @@ static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, - /* EOF on the FIFO means the session died abnormally. */ - - session_remove_fifo(s); -- session_stop(s, false); -+ session_stop(s, /* force = */ false); - - return 1; - } -diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c -index 2377237..307462f 100644 ---- a/src/login/logind-user-dbus.c -+++ b/src/login/logind-user-dbus.c -@@ -216,7 +216,7 @@ int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_er - if (r == 0) - return 1; /* Will call us back */ - -- r = user_stop(u, true); -+ r = user_stop(u, /* force */ true); - if (r < 0) - return r; - -@@ -319,14 +319,13 @@ static int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, c - sd_bus_message *message; - Manager *m = userdata; - User *user; -- Iterator i; - int r; - - assert(bus); - assert(path); - assert(nodes); - -- HASHMAP_FOREACH(user, m->users, i) { -+ HASHMAP_FOREACH(user, m->users) { - char *p; - - p = user_bus_path(user); -diff --git a/src/login/logind-user.c b/src/login/logind-user.c -index 9ceb33c..9cb4dce 100644 ---- a/src/login/logind-user.c -+++ b/src/login/logind-user.c -@@ -475,7 +475,7 @@ int user_start(User *u) { - return 0; - } - --static void user_stop_service(User *u) { -+static void user_stop_service(User *u, bool force) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - int r; - -@@ -487,7 +487,7 @@ static void user_stop_service(User *u) { - - u->service_job = mfree(u->service_job); - -- r = manager_stop_unit(u->manager, u->service, &error, &u->service_job); -+ r = manager_stop_unit(u->manager, u->service, force ? "replace" : "fail", &error, &u->service_job); - if (r < 0) - log_warning_errno(r, "Failed to stop user service '%s', ignoring: %s", u->service, bus_error_message(&error, r)); - } -@@ -518,7 +518,7 @@ int user_stop(User *u, bool force) { - r = k; - } - -- user_stop_service(u); -+ user_stop_service(u, force); - - u->stopping = true; - -@@ -919,7 +919,7 @@ int config_parse_tmpfs_size( - if (r >= 0 && (k <= 0 || (uint64_t) (size_t) k != k)) - r = -ERANGE; - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue); - return 0; - } - -diff --git a/src/login/logind.c b/src/login/logind.c -index c50a083..677a501 100644 ---- a/src/login/logind.c -+++ b/src/login/logind.c -@@ -912,7 +912,7 @@ static void manager_gc(Manager *m, bool drop_not_started) { - seat->in_gc_queue = false; - - if (seat_may_gc(seat, drop_not_started)) { -- seat_stop(seat, false); -+ seat_stop(seat, /* force = */ false); - seat_free(seat); - } - } -@@ -924,7 +924,7 @@ static void manager_gc(Manager *m, bool drop_not_started) { - /* First, if we are not closing yet, initiate stopping */ - if (session_may_gc(session, drop_not_started) && - session_get_state(session) != SESSION_CLOSING) -- (void) session_stop(session, false); -+ (void) session_stop(session, /* force = */ false); - - /* Normally, this should make the session referenced - * again, if it doesn't then let's get rid of it -@@ -1032,7 +1032,6 @@ static int manager_startup(Manager *m) { - User *user; - Button *button; - Inhibitor *inhibitor; -- Iterator i; - - assert(m); - -@@ -1102,16 +1101,16 @@ static int manager_startup(Manager *m) { - manager_read_utmp(m); - - /* And start everything */ -- HASHMAP_FOREACH(seat, m->seats, i) -+ HASHMAP_FOREACH(seat, m->seats) - (void) seat_start(seat); - -- HASHMAP_FOREACH(user, m->users, i) -+ HASHMAP_FOREACH(user, m->users) - (void) user_start(user); - -- HASHMAP_FOREACH(session, m->sessions, i) -+ HASHMAP_FOREACH(session, m->sessions) - (void) session_start(session, NULL, NULL); - -- HASHMAP_FOREACH(inhibitor, m->inhibitors, i) { -+ HASHMAP_FOREACH(inhibitor, m->inhibitors) { - (void) inhibitor_start(inhibitor); - - /* Let's see if the inhibitor is dead now, then remove it */ -@@ -1121,7 +1120,7 @@ static int manager_startup(Manager *m) { - } - } - -- HASHMAP_FOREACH(button, m->buttons, i) -+ HASHMAP_FOREACH(button, m->buttons) - button_check_switches(button); - - manager_dispatch_idle_action(NULL, 0, m); -diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in -index ed1084b..8b22026 100644 ---- a/src/login/logind.conf.in -+++ b/src/login/logind.conf.in -@@ -18,16 +18,19 @@ - #KillOnlyUsers= - #KillExcludeUsers=root - #InhibitDelayMaxSec=5 -+#UserStopDelaySec=10 - #HandlePowerKey=poweroff - #HandleSuspendKey=suspend - #HandleHibernateKey=hibernate - #HandleLidSwitch=suspend - #HandleLidSwitchExternalPower=suspend - #HandleLidSwitchDocked=ignore -+#HandleRebootKey=reboot - #PowerKeyIgnoreInhibited=no - #SuspendKeyIgnoreInhibited=no - #HibernateKeyIgnoreInhibited=no - #LidSwitchIgnoreInhibited=yes -+#RebootKeyIgnoreInhibited=no - #HoldoffTimeoutSec=30s - #IdleAction=ignore - #IdleActionSec=30min -diff --git a/src/login/logind.h b/src/login/logind.h -index e64ecce..82d319a 100644 ---- a/src/login/logind.h -+++ b/src/login/logind.h -@@ -2,6 +2,7 @@ - #pragma once - - #include -+#include - - #include "sd-bus.h" - #include "sd-device.h" -@@ -106,11 +107,13 @@ struct Manager { - HandleAction handle_lid_switch; - HandleAction handle_lid_switch_ep; - HandleAction handle_lid_switch_docked; -+ HandleAction handle_reboot_key; - - bool power_key_ignore_inhibited; - bool suspend_key_ignore_inhibited; - bool hibernate_key_ignore_inhibited; - bool lid_switch_ignore_inhibited; -+ bool reboot_key_ignore_inhibited; - - bool remove_ipc; - -diff --git a/src/login/org.freedesktop.login1.policy b/src/login/org.freedesktop.login1.policy -index 1b6d85e..1d269c1 100644 ---- a/src/login/org.freedesktop.login1.policy -+++ b/src/login/org.freedesktop.login1.policy -@@ -113,6 +113,17 @@ - - - -+ -+ Allow applications to inhibit system handling of the reboot key -+ Authentication is required for an application to inhibit system handling of the reboot key. -+ -+ no -+ yes -+ yes -+ -+ org.freedesktop.login1.inhibit-handle-suspend-key org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch -+ -+ - - Allow non-logged-in user to run programs - Explicit request is required to run programs as a non-logged-in user. -diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c -index a66be28..9b7fc20 100644 ---- a/src/login/sysfs-show.c -+++ b/src/login/sysfs-show.c -@@ -53,14 +53,14 @@ static int show_sysfs_one( - - /* Explicitly also check for tag 'seat' here */ - if (!streq(seat, sn) || -- sd_device_has_tag(dev_list[*i_dev], "seat") <= 0 || -+ sd_device_has_current_tag(dev_list[*i_dev], "seat") <= 0 || - sd_device_get_subsystem(dev_list[*i_dev], &subsystem) < 0 || - sd_device_get_sysname(dev_list[*i_dev], &sysname) < 0) { - (*i_dev)++; - continue; - } - -- is_master = sd_device_has_tag(dev_list[*i_dev], "master-of-seat") > 0; -+ is_master = sd_device_has_current_tag(dev_list[*i_dev], "master-of-seat") > 0; - - if (sd_device_get_sysattr_value(dev_list[*i_dev], "name", &name) < 0) - (void) sd_device_get_sysattr_value(dev_list[*i_dev], "id", &name); -@@ -80,7 +80,7 @@ static int show_sysfs_one( - isempty(lookahead_sn)) - lookahead_sn = "seat0"; - -- if (streq(seat, lookahead_sn) && sd_device_has_tag(dev_list[lookahead], "seat") > 0) -+ if (streq(seat, lookahead_sn) && sd_device_has_current_tag(dev_list[lookahead], "seat") > 0) - break; - } - } -diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c -index 38058d7..ab25ebf 100644 ---- a/src/login/user-runtime-dir.c -+++ b/src/login/user-runtime-dir.c -@@ -7,9 +7,10 @@ - - #include "bus-error.h" - #include "dev-setup.h" --#include "fs-util.h" - #include "format-util.h" -+#include "fs-util.h" - #include "label.h" -+#include "limits-util.h" - #include "main-func.h" - #include "mkdir.h" - #include "mountpoint-util.h" -@@ -32,12 +33,16 @@ static int acquire_runtime_dir_properties(uint64_t *size, uint64_t *inodes) { - return log_error_errno(r, "Failed to connect to system bus: %m"); - - r = sd_bus_get_property_trivial(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "RuntimeDirectorySize", &error, 't', size); -- if (r < 0) -- return log_error_errno(r, "Failed to acquire runtime directory size: %s", bus_error_message(&error, r)); -+ if (r < 0) { -+ log_warning_errno(r, "Failed to acquire runtime directory size, ignoring: %s", bus_error_message(&error, r)); -+ *size = physical_memory_scale(10U, 100U); /* 10% */ -+ } - - r = sd_bus_get_property_trivial(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "RuntimeDirectoryInodesMax", &error, 't', inodes); -- if (r < 0) -- return log_error_errno(r, "Failed to acquire number of inodes for runtime directory: %s", bus_error_message(&error, r)); -+ if (r < 0) { -+ log_warning_errno(r, "Failed to acquire number of inodes for runtime directory, ignoring: %s", bus_error_message(&error, r)); -+ *inodes = DIV_ROUND_UP(*size, 4096); -+ } - - return 0; - } -@@ -83,7 +88,8 @@ static int user_mkdir_runtime_path( - goto fail; - } - -- log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s.\n" -+ log_debug_errno(errno, -+ "Failed to mount per-user tmpfs directory %s.\n" - "Assuming containerized execution, ignoring: %m", runtime_path); - - r = chmod_and_chown(runtime_path, 0700, uid, gid); -@@ -98,8 +104,6 @@ static int user_mkdir_runtime_path( - log_warning_errno(r, "Failed to fix label of \"%s\", ignoring: %m", runtime_path); - } - -- /* Set up inaccessible nodes now so they're available if we decide to use them with user namespaces. */ -- (void) make_inaccessible_nodes(runtime_path, uid, gid); - return 0; - - fail: -@@ -162,7 +166,7 @@ static int do_umount(const char *user) { - int r; - - /* The user may be already removed. So, first try to parse the string by parse_uid(), -- * and if it fails, fallback to get_user_creds().*/ -+ * and if it fails, fall back to get_user_creds().*/ - if (parse_uid(user, &uid) < 0) { - r = get_user_creds(&user, &uid, NULL, NULL, NULL, 0); - if (r < 0) -diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c -index 7a15bcc..740684c 100644 ---- a/src/machine/image-dbus.c -+++ b/src/machine/image-dbus.c -@@ -442,7 +442,6 @@ static int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, - _cleanup_hashmap_free_ Hashmap *images = NULL; - _cleanup_strv_free_ char **l = NULL; - Image *image; -- Iterator i; - int r; - - assert(bus); -@@ -457,7 +456,7 @@ static int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, - if (r < 0) - return r; - -- HASHMAP_FOREACH(image, images, i) { -+ HASHMAP_FOREACH(image, images) { - char *p; - - p = image_bus_path(image->name); -diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c -index 73ef594..a98e883 100644 ---- a/src/machine/machine-dbus.c -+++ b/src/machine/machine-dbus.c -@@ -585,7 +585,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu - r = sd_bus_message_read(message, "ss", &user, &path); - if (r < 0) - return r; -- user = empty_to_null(user); -+ user = isempty(user) ? "root" : user; - r = sd_bus_message_read_strv(message, &args_wire); - if (r < 0) - return r; -@@ -604,7 +604,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu - r = asprintf(&args[2], - "shell=$(getent passwd %s 2>/dev/null | { IFS=: read _ _ _ _ _ _ x; echo \"$x\"; })\n"\ - "exec \"${shell:-/bin/sh}\" -l", /* -l is means --login */ -- isempty(user) ? "root" : user); -+ user); - if (r < 0) { - args[2] = NULL; - return -ENOMEM; -@@ -628,11 +628,18 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu - if (!strv_env_is_valid(env)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments"); - -+ const char *details[] = { -+ "machine", m->name, -+ "user", user, -+ "program", path, -+ NULL -+ }; -+ - r = bus_verify_polkit_async( - message, - CAP_SYS_ADMIN, - m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell", -- NULL, -+ details, - false, - UID_INVALID, - &m->manager->polkit_registry, -@@ -677,7 +684,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu - if (r < 0) - return r; - -- description = strjoina("Shell for User ", isempty(user) ? "root" : user); -+ description = strjoina("Shell for User ", user); - r = sd_bus_message_append(tm, - "(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)", - "Description", "s", description, -@@ -695,7 +702,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu - if (r < 0) - return r; - -- r = sd_bus_message_append(tm, "(sv)", "User", "s", isempty(user) ? "root" : user); -+ r = sd_bus_message_append(tm, "(sv)", "User", "s", user); - if (r < 0) - return r; - -@@ -971,9 +978,8 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu - goto finish; - } - if (r == 0) { -- const char *mount_inside; -+ const char *mount_inside, *q; - int mntfd; -- const char *q; - - errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); - -@@ -994,12 +1000,11 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu - (void) mkdir_p(dest, 0755); - else { - (void) mkdir_parents(dest, 0755); -- safe_close(open(dest, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600)); -+ (void) mknod(dest, S_IFREG|0600, 0); - } - } - -- /* Fifth, move the mount to the right place inside */ -- mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside)); -+ mount_inside = strjoina("/run/host/incoming/", basename(mount_outside)); - if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) { - r = log_error_errno(errno, "Failed to mount: %m"); - goto child_fail; -@@ -1061,7 +1066,7 @@ finish: - int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) { - const char *src, *dest, *host_path, *container_path, *host_basename, *container_basename, *container_dirname; - _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; -- CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE; -+ CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS; - _cleanup_close_ int hostfd = -1; - Machine *m = userdata; - bool copy_from; -@@ -1377,14 +1382,13 @@ static int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata - _cleanup_strv_free_ char **l = NULL; - Machine *machine = NULL; - Manager *m = userdata; -- Iterator i; - int r; - - assert(bus); - assert(path); - assert(nodes); - -- HASHMAP_FOREACH(machine, m->machines, i) { -+ HASHMAP_FOREACH(machine, m->machines) { - char *p; - - p = machine_bus_path(machine); -diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c -index 841eeae..41070dc 100644 ---- a/src/machine/machinectl.c -+++ b/src/machine/machinectl.c -@@ -720,7 +720,7 @@ static int show_machine(int argc, char *argv[], void *userdata) { - - r = bus_call_method(bus, bus_machine_mgr, "GetMachine", &error, &reply, "s", argv[i]); - if (r < 0) -- return log_error_errno(r, "Could not get path to machine: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not get path to machine: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "o", &path); - if (r < 0) -@@ -1037,7 +1037,7 @@ static int show_image(int argc, char *argv[], void *userdata) { - - r = bus_call_method(bus, bus_machine_mgr, "GetImage", &error, &reply, "s", argv[i]); - if (r < 0) -- return log_error_errno(r, "Could not get path to image: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not get path to image: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "o", &path); - if (r < 0) -@@ -1073,7 +1073,7 @@ static int kill_machine(int argc, char *argv[], void *userdata) { - NULL, - "ssi", argv[i], arg_kill_who, arg_signal); - if (r < 0) -- return log_error_errno(r, "Could not kill machine: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not kill machine: %s", bus_error_message(&error, r)); - } - - return 0; -@@ -1105,7 +1105,7 @@ static int terminate_machine(int argc, char *argv[], void *userdata) { - for (int i = 1; i < argc; i++) { - r = bus_call_method(bus, bus_machine_mgr, "TerminateMachine", &error, NULL, "s", argv[i]); - if (r < 0) -- return log_error_errno(r, "Could not terminate machine: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not terminate machine: %s", bus_error_message(&error, r)); - } - - return 0; -@@ -1184,7 +1184,7 @@ static int bind_mount(int argc, char *argv[], void *userdata) { - arg_read_only, - arg_mkdir); - if (r < 0) -- return log_error_errno(r, "Failed to bind mount: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to bind mount: %s", bus_error_message(&error, r)); - - return 0; - } -@@ -1347,7 +1347,7 @@ static int login_machine(int argc, char *argv[], void *userdata) { - - r = bus_call_method(bus, bus_machine_mgr, "OpenMachineLogin", &error, &reply, "s", machine); - if (r < 0) -- return log_error_errno(r, "Failed to get login PTY: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to get login PTY: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "hs", &master, NULL); - if (r < 0) -@@ -1430,7 +1430,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) { - - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) -- return log_error_errno(r, "Failed to get shell PTY: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to get shell PTY: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "hs", &master, NULL); - if (r < 0) -@@ -1485,7 +1485,7 @@ static int rename_image(int argc, char *argv[], void *userdata) { - NULL, - "ss", argv[1], argv[2]); - if (r < 0) -- return log_error_errno(r, "Could not rename image: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not rename image: %s", bus_error_message(&error, r)); - - return 0; - } -@@ -1535,7 +1535,7 @@ static int read_only_image(int argc, char *argv[], void *userdata) { - - r = bus_call_method(bus, bus_machine_mgr, "MarkImageReadOnly", &error, NULL, "sb", argv[1], b); - if (r < 0) -- return log_error_errno(r, "Could not mark image read-only: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not mark image read-only: %s", bus_error_message(&error, r)); - - return 0; - } -@@ -1552,7 +1552,7 @@ static int image_exists(sd_bus *bus, const char *name) { - if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_IMAGE)) - return 0; - -- return log_error_errno(r, "Failed to check whether image %s exists: %s", name, bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to check whether image %s exists: %s", name, bus_error_message(&error, r)); - } - - return 1; -@@ -1617,7 +1617,7 @@ static int start_machine(int argc, char *argv[], void *userdata) { - &reply, - "ss", unit, "fail"); - if (r < 0) -- return log_error_errno(r, "Failed to start unit: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to start unit: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "o", &object); - if (r < 0) -@@ -1697,7 +1697,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) { - - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) -- return log_error_errno(r, "Failed to enable or disable unit: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to enable or disable unit: %s", bus_error_message(&error, r)); - - if (streq(argv[0], "enable")) { - r = sd_bus_message_read(reply, "b", NULL); -@@ -1719,7 +1719,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) { - NULL, - NULL); - if (r < 0) { -- log_error("Failed to reload daemon: %s", bus_error_message(&error, -r)); -+ log_error("Failed to reload daemon: %s", bus_error_message(&error, r)); - goto finish; - } - -@@ -1831,7 +1831,7 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) { - - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) -- return log_error_errno(r, "Failed to transfer image: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to transfer image: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "uo", &id, &path); - if (r < 0) -@@ -2272,7 +2272,7 @@ static int list_transfers(int argc, char *argv[], void *userdata) { - - r = bus_call_method(bus, bus_import_mgr, "ListTransfers", &error, &reply, NULL); - if (r < 0) -- return log_error_errno(r, "Could not get transfers: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not get transfers: %s", bus_error_message(&error, r)); - - r = sd_bus_message_enter_container(reply, 'a', "(usssdo)"); - if (r < 0) -@@ -2369,7 +2369,7 @@ static int cancel_transfer(int argc, char *argv[], void *userdata) { - - r = bus_call_method(bus, bus_import_mgr, "CancelTransfer", &error, NULL, "u", id); - if (r < 0) -- return log_error_errno(r, "Could not cancel transfer: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Could not cancel transfer: %s", bus_error_message(&error, r)); - } - - return 0; -@@ -2672,7 +2672,7 @@ static int parse_argv(int argc, char *argv[]) { - return log_oom(); - - /* If the user asked for a particular -- * property, show it to him, even if it is -+ * property, show it to them, even if it is - * empty. */ - arg_all = true; - break; -diff --git a/src/machine/machined-core.c b/src/machine/machined-core.c -index c44bb94..2ff155d 100644 ---- a/src/machine/machined-core.c -+++ b/src/machine/machined-core.c -@@ -38,7 +38,6 @@ int manager_enqueue_nscd_cache_flush(Manager *m) { - - int manager_find_machine_for_uid(Manager *m, uid_t uid, Machine **ret_machine, uid_t *ret_internal_uid) { - Machine *machine; -- Iterator i; - int r; - - assert(m); -@@ -47,7 +46,7 @@ int manager_find_machine_for_uid(Manager *m, uid_t uid, Machine **ret_machine, u - /* Finds the machine for the specified host UID and returns it along with the UID translated into the - * internal UID inside the machine */ - -- HASHMAP_FOREACH(machine, m->machines, i) { -+ HASHMAP_FOREACH(machine, m->machines) { - uid_t converted; - - r = machine_owns_uid(machine, uid, &converted); -@@ -74,13 +73,12 @@ int manager_find_machine_for_uid(Manager *m, uid_t uid, Machine **ret_machine, u - - int manager_find_machine_for_gid(Manager *m, gid_t gid, Machine **ret_machine, gid_t *ret_internal_gid) { - Machine *machine; -- Iterator i; - int r; - - assert(m); - assert(gid_is_valid(gid)); - -- HASHMAP_FOREACH(machine, m->machines, i) { -+ HASHMAP_FOREACH(machine, m->machines) { - gid_t converted; - - r = machine_owns_gid(machine, gid, &converted); -diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c -index 467f16b..6d4a705 100644 ---- a/src/machine/machined-dbus.c -+++ b/src/machine/machined-dbus.c -@@ -185,7 +185,6 @@ static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_ - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *m = userdata; - Machine *machine; -- Iterator i; - int r; - - assert(message); -@@ -199,7 +198,7 @@ static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_ - if (r < 0) - return sd_bus_error_set_errno(error, r); - -- HASHMAP_FOREACH(machine, m->machines, i) { -+ HASHMAP_FOREACH(machine, m->machines) { - _cleanup_free_ char *p = NULL; - - p = machine_bus_path(machine); -@@ -474,7 +473,6 @@ static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_er - _cleanup_hashmap_free_ Hashmap *images = NULL; - _unused_ Manager *m = userdata; - Image *image; -- Iterator i; - int r; - - assert(message); -@@ -496,7 +494,7 @@ static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_er - if (r < 0) - return r; - -- HASHMAP_FOREACH(image, images, i) { -+ HASHMAP_FOREACH(image, images) { - _cleanup_free_ char *p = NULL; - - p = image_bus_path(image->name); -@@ -749,7 +747,6 @@ static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_err - _cleanup_hashmap_free_ Hashmap *images = NULL; - bool success = true; - Image *image; -- Iterator i; - ssize_t l; - - errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); -@@ -770,7 +767,7 @@ static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_err - goto child_fail; - } - -- HASHMAP_FOREACH(image, images, i) { -+ HASHMAP_FOREACH(image, images) { - - /* We can't remove vendor images (i.e. those in /usr) */ - if (IMAGE_IS_VENDOR(image)) -@@ -1421,7 +1418,6 @@ int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *er - int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) { - Manager *m = userdata; - Machine *machine; -- Iterator i; - int b, r; - - assert(message); -@@ -1438,7 +1434,7 @@ int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error - /* systemd finished reloading, let's recheck all our machines */ - log_debug("System manager has been reloaded, rechecking machines..."); - -- HASHMAP_FOREACH(machine, m->machines, i) -+ HASHMAP_FOREACH(machine, m->machines) - machine_add_to_gc_queue(machine); - - return 0; -@@ -1464,8 +1460,8 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c - - r = bus_call_method(manager->bus, bus_systemd_mgr, "StopUnit", error, &reply, "ss", unit, "fail"); - if (r < 0) { -- if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || -- sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) { -+ if (sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT, -+ BUS_ERROR_LOAD_FAILED)) { - - if (job) - *job = NULL; -@@ -1526,12 +1522,12 @@ int manager_unit_is_active(Manager *manager, const char *unit) { - &reply, - "s"); - if (r < 0) { -- if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || -- sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) -+ if (sd_bus_error_has_names(&error, SD_BUS_ERROR_NO_REPLY, -+ SD_BUS_ERROR_DISCONNECTED)) - return true; - -- if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || -- sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) -+ if (sd_bus_error_has_names(&error, BUS_ERROR_NO_SUCH_UNIT, -+ BUS_ERROR_LOAD_FAILED)) - return false; - - return r; -@@ -1562,8 +1558,8 @@ int manager_job_is_active(Manager *manager, const char *path) { - &reply, - "s"); - if (r < 0) { -- if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || -- sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) -+ if (sd_bus_error_has_names(&error, SD_BUS_ERROR_NO_REPLY, -+ SD_BUS_ERROR_DISCONNECTED)) - return true; - - if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) -diff --git a/src/machine/machined-varlink.c b/src/machine/machined-varlink.c -index 058ee5c..de8cdeb 100644 ---- a/src/machine/machined-varlink.c -+++ b/src/machine/machined-varlink.c -@@ -93,6 +93,8 @@ static int user_lookup_name(Manager *m, const char *name, uid_t *ret_uid, char * - int r; - - assert(m); -+ assert(ret_uid); -+ assert(ret_real_name); - - if (!valid_user_group_name(name, 0)) - return -ESRCH; -@@ -186,7 +188,7 @@ static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, Var - return varlink_reply(link, v); - } - --static int build_group_json(const char *group_name, gid_t gid, JsonVariant **ret) { -+static int build_group_json(const char *group_name, gid_t gid, const char *description, JsonVariant **ret) { - assert(group_name); - assert(gid_is_valid(gid)); - assert(ret); -@@ -195,6 +197,7 @@ static int build_group_json(const char *group_name, gid_t gid, JsonVariant **ret - JSON_BUILD_PAIR("record", JSON_BUILD_OBJECT( - JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(group_name)), - JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(gid)), -+ JSON_BUILD_PAIR_CONDITION(!isempty(description), "description", JSON_BUILD_STRING(description)), - JSON_BUILD_PAIR("service", JSON_BUILD_STRING("io.systemd.Machine")), - JSON_BUILD_PAIR("disposition", JSON_BUILD_STRING("container")))))); - } -@@ -211,8 +214,8 @@ static bool group_match_lookup_parameters(LookupParameters *p, const char *name, - return true; - } - --static int group_lookup_gid(Manager *m, gid_t gid, char **ret_name) { -- _cleanup_free_ char *n = NULL; -+static int group_lookup_gid(Manager *m, gid_t gid, char **ret_name, char **ret_description) { -+ _cleanup_free_ char *n = NULL, *d = NULL; - gid_t converted_gid; - Machine *machine; - int r; -@@ -220,6 +223,7 @@ static int group_lookup_gid(Manager *m, gid_t gid, char **ret_name) { - assert(m); - assert(gid_is_valid(gid)); - assert(ret_name); -+ assert(ret_description); - - if (gid < 0x10000) /* Host GID range */ - return -ESRCH; -@@ -236,18 +240,27 @@ static int group_lookup_gid(Manager *m, gid_t gid, char **ret_name) { - if (!valid_user_group_name(n, 0)) - return -ESRCH; - -+ if (asprintf(&d, "GID " GID_FMT " of Container %s", converted_gid, machine->name) < 0) -+ return -ENOMEM; -+ if (!valid_gecos(d)) -+ d = mfree(d); -+ - *ret_name = TAKE_PTR(n); -+ *ret_description = TAKE_PTR(d); -+ - return 0; - } - --static int group_lookup_name(Manager *m, const char *name, gid_t *ret_gid) { -- _cleanup_free_ char *mn = NULL; -+static int group_lookup_name(Manager *m, const char *name, gid_t *ret_gid, char **ret_description) { -+ _cleanup_free_ char *mn = NULL, *desc = NULL; - gid_t gid, converted_gid; - Machine *machine; - const char *e, *d; - int r; - - assert(m); -+ assert(ret_gid); -+ assert(ret_description); - - if (!valid_user_group_name(name, 0)) - return -ESRCH; -@@ -278,7 +291,13 @@ static int group_lookup_name(Manager *m, const char *name, gid_t *ret_gid) { - if (r < 0) - return r; - -+ if (asprintf(&desc, "GID " GID_FMT " of Container %s", gid, machine->name) < 0) -+ return -ENOMEM; -+ if (!valid_gecos(desc)) -+ desc = mfree(desc); -+ - *ret_gid = converted_gid; -+ *ret_description = desc; - return 0; - } - -@@ -295,7 +314,7 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va - LookupParameters p = { - .gid = GID_INVALID, - }; -- _cleanup_free_ char *found_name = NULL; -+ _cleanup_free_ char *found_name = NULL, *found_description = NULL; - uid_t found_gid = GID_INVALID, gid; - Manager *m = userdata; - const char *gn; -@@ -312,9 +331,9 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va - return varlink_error(link, "io.systemd.UserDatabase.BadService", NULL); - - if (gid_is_valid(p.gid)) -- r = group_lookup_gid(m, p.gid, &found_name); -+ r = group_lookup_gid(m, p.gid, &found_name, &found_description); - else if (p.group_name) -- r = group_lookup_name(m, p.group_name, (uid_t*) &found_gid); -+ r = group_lookup_name(m, p.group_name, (uid_t*) &found_gid, &found_description); - else - return varlink_error(link, "io.systemd.UserDatabase.EnumerationNotSupported", NULL); - if (r == -ESRCH) -@@ -328,7 +347,7 @@ static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, Va - if (!group_match_lookup_parameters(&p, gn, gid)) - return varlink_error(link, "io.systemd.UserDatabase.ConflictingRecordFound", NULL); - -- r = build_group_json(gn, gid, &v); -+ r = build_group_json(gn, gid, found_description, &v); - if (r < 0) - return r; - -diff --git a/src/machine/machined.c b/src/machine/machined.c -index a884f3d..2828ed6 100644 ---- a/src/machine/machined.c -+++ b/src/machine/machined.c -@@ -136,7 +136,7 @@ static int manager_add_host_machine(Manager *m) { - static int manager_enumerate_machines(Manager *m) { - _cleanup_closedir_ DIR *d = NULL; - struct dirent *de; -- int r = 0; -+ int r; - - assert(m); - -@@ -265,7 +265,6 @@ static void manager_gc(Manager *m, bool drop_not_started) { - - static int manager_startup(Manager *m) { - Machine *machine; -- Iterator i; - int r; - - assert(m); -@@ -287,7 +286,7 @@ static int manager_startup(Manager *m) { - manager_gc(m, false); - - /* And start everything */ -- HASHMAP_FOREACH(machine, m->machines, i) -+ HASHMAP_FOREACH(machine, m->machines) - machine_start(machine, NULL, NULL); - - return 0; -diff --git a/src/network/generator/main.c b/src/network/generator/main.c -index 75bd2b4..61a741e 100644 ---- a/src/network/generator/main.c -+++ b/src/network/generator/main.c -@@ -83,8 +83,7 @@ static int context_save(Context *context) { - Network *network; - NetDev *netdev; - Link *link; -- Iterator i; -- int k, r = 0; -+ int k, r; - const char *p; - - p = prefix_roota(arg_root, NETWORKD_UNIT_DIRECTORY); -@@ -93,19 +92,19 @@ static int context_save(Context *context) { - if (r < 0) - return log_error_errno(r, "Failed to create directory " NETWORKD_UNIT_DIRECTORY ": %m"); - -- HASHMAP_FOREACH(network, context->networks_by_name, i) { -+ HASHMAP_FOREACH(network, context->networks_by_name) { - k = network_save(network, p); - if (k < 0 && r >= 0) - r = k; - } - -- HASHMAP_FOREACH(netdev, context->netdevs_by_name, i) { -+ HASHMAP_FOREACH(netdev, context->netdevs_by_name) { - k = netdev_save(netdev, p); - if (k < 0 && r >= 0) - r = k; - } - -- HASHMAP_FOREACH(link, context->links_by_name, i) { -+ HASHMAP_FOREACH(link, context->links_by_name) { - k = link_save(link, p); - if (k < 0 && r >= 0) - r = k; -diff --git a/src/network/generator/network-generator.c b/src/network/generator/network-generator.c -index bed1e42..465b3ed 100644 ---- a/src/network/generator/network-generator.c -+++ b/src/network/generator/network-generator.c -@@ -957,7 +957,6 @@ int parse_cmdline_item(const char *key, const char *value, void *data) { - int context_merge_networks(Context *context) { - Network *all, *network; - Route *route; -- Iterator i; - int r; - - assert(context); -@@ -974,7 +973,7 @@ int context_merge_networks(Context *context) { - if (hashmap_size(context->networks_by_name) <= 1) - return 0; - -- HASHMAP_FOREACH(network, context->networks_by_name, i) { -+ HASHMAP_FOREACH(network, context->networks_by_name) { - if (network == all) - continue; - -diff --git a/src/network/meson.build b/src/network/meson.build -index b3a88d9..cb8f801 100644 ---- a/src/network/meson.build -+++ b/src/network/meson.build -@@ -87,6 +87,8 @@ sources = files(''' - networkd-manager-bus.h - networkd-manager.c - networkd-manager.h -+ networkd-mdb.c -+ networkd-mdb.h - networkd-ndisc.c - networkd-ndisc.h - networkd-neighbor.c -diff --git a/src/network/netdev/bond.c b/src/network/netdev/bond.c -index b5cf162..3007d69 100644 ---- a/src/network/netdev/bond.c -+++ b/src/network/netdev/bond.c -@@ -201,7 +201,6 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin - } - - if (b->arp_interval > 0 && !ordered_set_isempty(b->arp_ip_targets)) { -- Iterator i; - void *val; - int n = 0; - -@@ -209,7 +208,7 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not open contaniner IFLA_BOND_ARP_IP_TARGET : %m"); - -- ORDERED_SET_FOREACH(val, b->arp_ip_targets, i) { -+ ORDERED_SET_FOREACH(val, b->arp_ip_targets) { - r = sd_netlink_message_append_u32(m, n++, PTR_TO_UINT32(val)); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); -diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c -index 7024066..45d97ac 100644 ---- a/src/network/netdev/bridge.c -+++ b/src/network/netdev/bridge.c -@@ -192,7 +192,7 @@ int link_set_bridge(Link *link) { - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); - -- r = sd_rtnl_message_link_set_family(req, PF_BRIDGE); -+ r = sd_rtnl_message_link_set_family(req, AF_BRIDGE); - if (r < 0) - return log_link_error_errno(link, r, "Could not set message family: %m"); - -diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c -index 0d670cb..949f124 100644 ---- a/src/network/netdev/l2tp-tunnel.c -+++ b/src/network/netdev/l2tp-tunnel.c -@@ -275,7 +275,6 @@ static int l2tp_acquire_local_address_one(L2tpTunnel *t, Address *a, union in_ad - - static int l2tp_acquire_local_address(L2tpTunnel *t, Link *link, union in_addr_union *ret) { - Address *a; -- Iterator i; - - assert(t); - assert(link); -@@ -288,11 +287,11 @@ static int l2tp_acquire_local_address(L2tpTunnel *t, Link *link, union in_addr_u - return 0; - } - -- SET_FOREACH(a, link->addresses, i) -+ SET_FOREACH(a, link->addresses) - if (l2tp_acquire_local_address_one(t, a, ret) >= 0) - return 1; - -- SET_FOREACH(a, link->addresses_foreign, i) -+ SET_FOREACH(a, link->addresses_foreign) - if (l2tp_acquire_local_address_one(t, a, ret) >= 0) - return 1; - -@@ -348,7 +347,6 @@ static int l2tp_create_session(NetDev *netdev, L2tpSession *session) { - static int l2tp_create_tunnel_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) { - L2tpSession *session; - L2tpTunnel *t; -- Iterator i; - int r; - - assert(netdev); -@@ -370,7 +368,7 @@ static int l2tp_create_tunnel_handler(sd_netlink *rtnl, sd_netlink_message *m, N - - log_netdev_debug(netdev, "L2TP tunnel is created"); - -- ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i) -+ ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) - (void) l2tp_create_session(netdev, session); - - return 1; -@@ -677,7 +675,6 @@ static int l2tp_session_verify(L2tpSession *session) { - static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) { - L2tpTunnel *t; - L2tpSession *session; -- Iterator i; - - assert(netdev); - assert(filename); -@@ -701,7 +698,7 @@ static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) { - "%s: L2TP tunnel without tunnel IDs configured. Ignoring", - filename); - -- ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i) -+ ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section) - if (l2tp_session_verify(session) < 0) - l2tp_session_free(session); - -diff --git a/src/network/netdev/macsec.c b/src/network/netdev/macsec.c -index 2ffa5ec..9d3b8d6 100644 ---- a/src/network/netdev/macsec.c -+++ b/src/network/netdev/macsec.c -@@ -494,7 +494,6 @@ static int netdev_macsec_configure_transmit_association(NetDev *netdev, Transmit - static int netdev_macsec_configure(NetDev *netdev, Link *link, sd_netlink_message *m) { - TransmitAssociation *a; - ReceiveChannel *c; -- Iterator i; - MACsec *s; - int r; - -@@ -502,13 +501,13 @@ static int netdev_macsec_configure(NetDev *netdev, Link *link, sd_netlink_messag - s = MACSEC(netdev); - assert(s); - -- ORDERED_HASHMAP_FOREACH(a, s->transmit_associations_by_section, i) { -+ ORDERED_HASHMAP_FOREACH(a, s->transmit_associations_by_section) { - r = netdev_macsec_configure_transmit_association(netdev, a); - if (r < 0) - return r; - } - -- ORDERED_HASHMAP_FOREACH(c, s->receive_channels, i) { -+ ORDERED_HASHMAP_FOREACH(c, s->receive_channels) { - r = netdev_macsec_configure_receive_channel(netdev, c); - if (r < 0) - return r; -@@ -848,14 +847,19 @@ int config_parse_macsec_key_id( - return log_oom(); - - r = unhexmem(rvalue, strlen(rvalue), &p, &l); -+ if (r == -ENOMEM) -+ return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse KeyId \"%s\": %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse KeyId=%s, ignoring assignment: %m", rvalue); -+ return 0; -+ } -+ if (l > MACSEC_KEYID_LEN) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Specified KeyId= is larger then the allowed maximum (%zu > %u), ignoring: %s", -+ l, MACSEC_KEYID_LEN, rvalue); - return 0; - } -- if (l > MACSEC_KEYID_LEN) -- return log_syntax(unit, LOG_WARNING, filename, line, 0, -- "Specified KeyId is larger then the allowed maximum (%zu > %u), ignoring: %s", -- l, MACSEC_KEYID_LEN, rvalue); - - dest = a ? a->sa.key_id : b->sa.key_id; - memcpy_safe(dest, p, l); -@@ -1148,7 +1152,6 @@ static int netdev_macsec_verify(NetDev *netdev, const char *filename) { - TransmitAssociation *a; - ReceiveAssociation *n; - ReceiveChannel *c; -- Iterator i; - uint8_t an, encoding_an; - bool use_for_encoding; - int r; -@@ -1157,7 +1160,7 @@ static int netdev_macsec_verify(NetDev *netdev, const char *filename) { - assert(v); - assert(filename); - -- ORDERED_HASHMAP_FOREACH(c, v->receive_channels_by_section, i) { -+ ORDERED_HASHMAP_FOREACH(c, v->receive_channels_by_section) { - r = macsec_receive_channel_verify(c); - if (r < 0) - macsec_receive_channel_free(c); -@@ -1166,7 +1169,7 @@ static int netdev_macsec_verify(NetDev *netdev, const char *filename) { - an = 0; - use_for_encoding = false; - encoding_an = 0; -- ORDERED_HASHMAP_FOREACH(a, v->transmit_associations_by_section, i) { -+ ORDERED_HASHMAP_FOREACH(a, v->transmit_associations_by_section) { - r = macsec_transmit_association_verify(a); - if (r < 0) { - macsec_transmit_association_free(a); -@@ -1201,7 +1204,7 @@ static int netdev_macsec_verify(NetDev *netdev, const char *filename) { - assert(encoding_an < MACSEC_MAX_ASSOCIATION_NUMBER); - v->encoding_an = encoding_an; - -- ORDERED_HASHMAP_FOREACH(n, v->receive_associations_by_section, i) { -+ ORDERED_HASHMAP_FOREACH(n, v->receive_associations_by_section) { - r = macsec_receive_association_verify(n); - if (r < 0) - macsec_receive_association_free(n); -diff --git a/src/network/netdev/macvlan.c b/src/network/netdev/macvlan.c -index 4139178..8f38217 100644 ---- a/src/network/netdev/macvlan.c -+++ b/src/network/netdev/macvlan.c -@@ -24,7 +24,6 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net - assert(m); - - if (m->mode == NETDEV_MACVLAN_MODE_SOURCE && !set_isempty(m->match_source_mac)) { -- Iterator i; - const struct ether_addr *mac_addr; - - r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MACADDR_MODE, MACVLAN_MACADDR_SET); -@@ -35,7 +34,7 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not open IFLA_MACVLAN_MACADDR_DATA container: %m"); - -- SET_FOREACH(mac_addr, m->match_source_mac, i) { -+ SET_FOREACH(mac_addr, m->match_source_mac) { - r = sd_netlink_message_append_ether_addr(req, IFLA_MACVLAN_MACADDR, mac_addr); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_MACADDR attribute: %m"); -diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf -index 0e2a9ce..c532dfd 100644 ---- a/src/network/netdev/netdev-gperf.gperf -+++ b/src/network/netdev/netdev-gperf.gperf -@@ -220,8 +220,8 @@ WireGuard.PrivateKey, config_parse_wireguard_private_key, - WireGuard.PrivateKeyFile, config_parse_wireguard_private_key_file, 0, 0 - WireGuardPeer.AllowedIPs, config_parse_wireguard_allowed_ips, 0, 0 - WireGuardPeer.Endpoint, config_parse_wireguard_endpoint, 0, 0 --WireGuardPeer.PublicKey, config_parse_wireguard_public_key, 0, 0 --WireGuardPeer.PresharedKey, config_parse_wireguard_preshared_key, 0, 0 -+WireGuardPeer.PublicKey, config_parse_wireguard_peer_key, 0, 0 -+WireGuardPeer.PresharedKey, config_parse_wireguard_peer_key, 0, 0 - WireGuardPeer.PresharedKeyFile, config_parse_wireguard_preshared_key_file, 0, 0 - WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0 - Xfrm.InterfaceId, config_parse_uint32, 0, offsetof(Xfrm, if_id) -diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c -index 6812b07..f1de5d4 100644 ---- a/src/network/netdev/wireguard.c -+++ b/src/network/netdev/wireguard.c -@@ -395,14 +395,13 @@ static void resolve_endpoints(NetDev *netdev) { - }; - WireguardPeer *peer; - Wireguard *w; -- Iterator i; - int r; - - assert(netdev); - w = WIREGUARD(netdev); - assert(w); - -- SET_FOREACH(peer, w->peers_with_unresolved_endpoint, i) { -+ SET_FOREACH(peer, w->peers_with_unresolved_endpoint) { - r = resolve_getaddrinfo(netdev->manager->resolve, - NULL, - peer->endpoint_host, -@@ -493,13 +492,19 @@ static int wireguard_decode_key_and_warn( - (void) warn_file_is_world_accessible(filename, NULL, unit, line); - - r = unbase64mem_full(rvalue, strlen(rvalue), true, &key, &len); -- if (r < 0) -- return log_syntax(unit, LOG_WARNING, filename, line, r, -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to decode wireguard key provided by %s=, ignoring assignment: %m", lvalue); -- if (len != WG_KEY_LEN) -- return log_syntax(unit, LOG_WARNING, filename, line, SYNTHETIC_ERRNO(EINVAL), -+ return 0; -+ } -+ if (len != WG_KEY_LEN) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, - "Wireguard key provided by %s= has invalid length (%zu bytes), ignoring assignment.", - lvalue, len); -+ return 0; -+ } - - memcpy(ret, key, WG_KEY_LEN); - return 0; -@@ -523,8 +528,7 @@ int config_parse_wireguard_private_key( - w = WIREGUARD(data); - assert(w); - -- (void) wireguard_decode_key_and_warn(rvalue, w->private_key, unit, filename, line, lvalue); -- return 0; -+ return wireguard_decode_key_and_warn(rvalue, w->private_key, unit, filename, line, lvalue); - } - - int config_parse_wireguard_private_key_file( -@@ -561,7 +565,7 @@ int config_parse_wireguard_private_key_file( - return free_and_replace(w->private_key_file, path); - } - --int config_parse_wireguard_preshared_key( -+int config_parse_wireguard_peer_key( - const char *unit, - const char *filename, - unsigned line, -@@ -573,7 +577,7 @@ int config_parse_wireguard_preshared_key( - void *data, - void *userdata) { - -- WireguardPeer *peer; -+ _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; - Wireguard *w; - int r; - -@@ -585,7 +589,13 @@ int config_parse_wireguard_preshared_key( - if (r < 0) - return log_oom(); - -- (void) wireguard_decode_key_and_warn(rvalue, peer->preshared_key, unit, filename, line, lvalue); -+ r = wireguard_decode_key_and_warn(rvalue, -+ streq(lvalue, "PublicKey") ? peer->public_key : peer->preshared_key, -+ unit, filename, line, lvalue); -+ if (r < 0) -+ return r; -+ -+ TAKE_PTR(peer); - return 0; - } - -@@ -632,38 +642,6 @@ int config_parse_wireguard_preshared_key_file( - return 0; - } - --int config_parse_wireguard_public_key( -- const char *unit, -- const char *filename, -- unsigned line, -- const char *section, -- unsigned section_line, -- const char *lvalue, -- int ltype, -- const char *rvalue, -- void *data, -- void *userdata) { -- -- _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; -- Wireguard *w; -- int r; -- -- assert(data); -- w = WIREGUARD(data); -- assert(w); -- -- r = wireguard_peer_new_static(w, filename, section_line, &peer); -- if (r < 0) -- return log_oom(); -- -- r = wireguard_decode_key_and_warn(rvalue, peer->public_key, unit, filename, line, lvalue); -- if (r < 0) -- return 0; -- -- TAKE_PTR(peer); -- return 0; --} -- - int config_parse_wireguard_allowed_ips( - const char *unit, - const char *filename, -@@ -818,7 +796,7 @@ int config_parse_wireguard_keepalive( - void *data, - void *userdata) { - -- WireguardPeer *peer; -+ _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; - uint16_t keepalive = 0; - Wireguard *w; - int r; -@@ -846,6 +824,8 @@ int config_parse_wireguard_keepalive( - } - - peer->persistent_keepalive_interval = keepalive; -+ -+ TAKE_PTR(peer); - return 0; - } - -diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h -index ce336c9..6111311 100644 ---- a/src/network/netdev/wireguard.h -+++ b/src/network/netdev/wireguard.h -@@ -61,10 +61,8 @@ extern const NetDevVTable wireguard_vtable; - CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_allowed_ips); - CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_endpoint); - CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_listen_port); -- --CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_public_key); -+CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_peer_key); - CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key); - CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key_file); --CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key); - CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key_file); - CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_keepalive); -diff --git a/src/network/networkctl.c b/src/network/networkctl.c -index 48182e6..0c4f930 100644 ---- a/src/network/networkctl.c -+++ b/src/network/networkctl.c -@@ -510,8 +510,8 @@ static int acquire_link_bitrates(sd_bus *bus, LinkInfo *link) { - - r = link_get_property(bus, link, &error, &reply, "org.freedesktop.network1.Link", "BitRates"); - if (r < 0) { -- bool quiet = sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_PROPERTY) || -- sd_bus_error_has_name(&error, BUS_ERROR_SPEED_METER_INACTIVE); -+ bool quiet = sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_PROPERTY, -+ BUS_ERROR_SPEED_METER_INACTIVE); - - return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, - r, "Failed to query link bit rates: %s", bus_error_message(&error, r)); -@@ -2477,7 +2477,6 @@ static int link_up_down(int argc, char *argv[], void *userdata) { - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_set_free_ Set *indexes = NULL; - int index, r, i; -- Iterator j; - void *p; - - r = sd_netlink_open(&rtnl); -@@ -2498,7 +2497,7 @@ static int link_up_down(int argc, char *argv[], void *userdata) { - return log_oom(); - } - -- SET_FOREACH(p, indexes, j) { -+ SET_FOREACH(p, indexes) { - index = PTR_TO_INT(p); - r = link_up_down_send_message(rtnl, argv[0], index); - if (r < 0) { -@@ -2516,7 +2515,6 @@ static int link_delete(int argc, char *argv[], void *userdata) { - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_set_free_ Set *indexes = NULL; - int index, r, i; -- Iterator j; - void *p; - - r = sd_netlink_open(&rtnl); -@@ -2537,7 +2535,7 @@ static int link_delete(int argc, char *argv[], void *userdata) { - return log_oom(); - } - -- SET_FOREACH(p, indexes, j) { -+ SET_FOREACH(p, indexes) { - index = PTR_TO_INT(p); - r = link_delete_send_message(rtnl, index); - if (r < 0) { -@@ -2641,7 +2639,6 @@ static int verb_reconfigure(int argc, char *argv[], void *userdata) { - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_set_free_ Set *indexes = NULL; - int index, i, r; -- Iterator j; - void *p; - - r = sd_bus_open_system(&bus); -@@ -2662,7 +2659,7 @@ static int verb_reconfigure(int argc, char *argv[], void *userdata) { - return log_oom(); - } - -- SET_FOREACH(p, indexes, j) { -+ SET_FOREACH(p, indexes) { - index = PTR_TO_INT(p); - r = bus_call_method(bus, bus_network_mgr, "ReconfigureLink", &error, NULL, "i", index); - if (r < 0) { -@@ -2794,7 +2791,7 @@ static int networkctl_main(int argc, char *argv[]) { - { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links }, - { "status", VERB_ANY, VERB_ANY, 0, link_status }, - { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status }, -- { "label", VERB_ANY, VERB_ANY, 0, list_address_labels }, -+ { "label", 1, 1, 0, list_address_labels }, - { "delete", 2, VERB_ANY, 0, link_delete }, - { "up", 2, VERB_ANY, 0, link_up_down }, - { "down", 2, VERB_ANY, 0, link_up_down }, -diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c -index db6c145..b4a94f0 100644 ---- a/src/network/networkd-address-pool.c -+++ b/src/network/networkd-address-pool.c -@@ -75,19 +75,17 @@ static bool address_pool_prefix_is_taken( - const union in_addr_union *u, - unsigned prefixlen) { - -- Iterator i; - Link *l; - Network *n; - - assert(p); - assert(u); - -- HASHMAP_FOREACH(l, p->manager->links, i) { -+ HASHMAP_FOREACH(l, p->manager->links) { - Address *a; -- Iterator j; - - /* Don't clash with assigned addresses */ -- SET_FOREACH(a, l->addresses, j) { -+ SET_FOREACH(a, l->addresses) { - if (a->family != p->family) - continue; - -@@ -106,7 +104,7 @@ static bool address_pool_prefix_is_taken( - } - - /* And don't clash with configured but un-assigned addresses either */ -- ORDERED_HASHMAP_FOREACH(n, p->manager->networks, i) { -+ ORDERED_HASHMAP_FOREACH(n, p->manager->networks) { - Address *a; - - LIST_FOREACH(addresses, a, n->static_addresses) { -diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c -index b09d75e..76c91ef 100644 ---- a/src/network/networkd-address.c -+++ b/src/network/networkd-address.c -@@ -10,6 +10,7 @@ - #include "netlink-util.h" - #include "networkd-address.h" - #include "networkd-manager.h" -+#include "networkd-ndisc.h" - #include "parse-util.h" - #include "set.h" - #include "socket-util.h" -@@ -123,6 +124,8 @@ void address_free(Address *address) { - } - - if (address->link && !address->acd) { -+ NDiscAddress *n; -+ - set_remove(address->link->addresses, address); - set_remove(address->link->addresses_foreign, address); - set_remove(address->link->static_addresses, address); -@@ -134,8 +137,9 @@ void address_free(Address *address) { - set_remove(address->link->dhcp6_addresses_old, address); - set_remove(address->link->dhcp6_pd_addresses, address); - set_remove(address->link->dhcp6_pd_addresses_old, address); -- set_remove(address->link->ndisc_addresses, address); -- set_remove(address->link->ndisc_addresses_old, address); -+ SET_FOREACH(n, address->link->ndisc_addresses) -+ if (n->address == address) -+ free(set_remove(address->link->ndisc_addresses, n)); - - if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address)) - memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr)); -@@ -162,7 +166,7 @@ static uint32_t address_prefix(const Address *a) { - return be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen); - } - --static void address_hash_func(const Address *a, struct siphash *state) { -+void address_hash_func(const Address *a, struct siphash *state) { - assert(a); - - siphash24_compress(&a->family, sizeof(a->family), state); -@@ -187,7 +191,7 @@ static void address_hash_func(const Address *a, struct siphash *state) { - } - } - --static int address_compare_func(const Address *a1, const Address *a2) { -+int address_compare_func(const Address *a1, const Address *a2) { - int r; - - r = CMP(a1->family, a2->family); -@@ -450,9 +454,8 @@ int address_get(Link *link, - - static bool address_exists_internal(Set *addresses, int family, const union in_addr_union *in_addr) { - Address *address; -- Iterator i; - -- SET_FOREACH(address, addresses, i) { -+ SET_FOREACH(address, addresses) { - if (address->family != family) - continue; - if (in_addr_equal(address->family, &address->in_addr, in_addr)) -@@ -487,7 +490,7 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EADDRNOTAVAIL) - log_link_message_warning_errno(link, m, r, "Could not drop address"); -- else -+ else if (r >= 0) - (void) manager_rtnl_process_address(rtnl, m, link->manager); - - return 1; -diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h -index 3fc9935..1378901 100644 ---- a/src/network/networkd-address.h -+++ b/src/network/networkd-address.h -@@ -75,6 +75,8 @@ int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret); - - DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free); - -+void address_hash_func(const Address *a, struct siphash *state); -+int address_compare_func(const Address *a1, const Address *a2); - extern const struct hash_ops address_hash_ops; - - CONFIG_PARSER_PROTOTYPE(config_parse_address); -diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c -index 3fc252d..bbe0103 100644 ---- a/src/network/networkd-brvlan.c -+++ b/src/network/networkd-brvlan.c -@@ -169,7 +169,7 @@ int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32 - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); - -- r = sd_rtnl_message_link_set_family(req, PF_BRIDGE); -+ r = sd_rtnl_message_link_set_family(req, AF_BRIDGE); - if (r < 0) - return log_link_error_errno(link, r, "Could not set message family: %m"); - -diff --git a/src/network/networkd-dhcp-server-bus.c b/src/network/networkd-dhcp-server-bus.c -index 1731d0b..3de8c16 100644 ---- a/src/network/networkd-dhcp-server-bus.c -+++ b/src/network/networkd-dhcp-server-bus.c -@@ -22,7 +22,6 @@ static int property_get_leases( - Link *l = userdata; - sd_dhcp_server *s; - DHCPLease *lease; -- Iterator i; - int r; - - assert(reply); -@@ -36,7 +35,7 @@ static int property_get_leases( - if (r < 0) - return r; - -- HASHMAP_FOREACH(lease, s->leases_by_client_id, i) { -+ HASHMAP_FOREACH(lease, s->leases_by_client_id) { - r = sd_bus_message_open_container(reply, 'r', "uayayayayt"); - if (r < 0) - return r; -diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c -index 5129a2e..890d9b5 100644 ---- a/src/network/networkd-dhcp-server.c -+++ b/src/network/networkd-dhcp-server.c -@@ -228,7 +228,6 @@ int dhcp4_server_configure(Link *link) { - sd_dhcp_option *p; - Link *uplink = NULL; - Address *address; -- Iterator i; - int r; - - address = link_find_dhcp_server_address(link); -@@ -322,7 +321,7 @@ int dhcp4_server_configure(Link *link) { - return log_link_error_errno(link, r, "Failed to set timezone for DHCP server: %m"); - } - -- ORDERED_HASHMAP_FOREACH(p, link->network->dhcp_server_send_options, i) { -+ ORDERED_HASHMAP_FOREACH(p, link->network->dhcp_server_send_options) { - r = sd_dhcp_server_add_option(link->dhcp_server, p); - if (r == -EEXIST) - continue; -@@ -330,7 +329,7 @@ int dhcp4_server_configure(Link *link) { - return log_link_error_errno(link, r, "Failed to set DHCPv4 option: %m"); - } - -- ORDERED_HASHMAP_FOREACH(p, link->network->dhcp_server_send_vendor_options, i) { -+ ORDERED_HASHMAP_FOREACH(p, link->network->dhcp_server_send_vendor_options) { - r = sd_dhcp_server_add_vendor_option(link->dhcp_server, p); - if (r == -EEXIST) - continue; -diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c -index 722e0d2..eddeb0d 100644 ---- a/src/network/networkd-dhcp4.c -+++ b/src/network/networkd-dhcp4.c -@@ -22,21 +22,9 @@ - - static int dhcp4_update_address(Link *link, bool announce); - static int dhcp4_remove_all(Link *link); --static int dhcp4_release_old_lease(Link *link, bool force); - --static int dhcp4_address_callback(Address *address) { -- assert(address); -- assert(address->link); -- -- /* Do not call this callback again. */ -- address->callback = NULL; -- -- return dhcp4_release_old_lease(address->link, true); --} -- --static int dhcp4_release_old_lease(Link *link, bool force) { -+static int dhcp4_release_old_lease(Link *link) { - Route *route; -- Iterator i; - int k, r = 0; - - assert(link); -@@ -44,17 +32,11 @@ static int dhcp4_release_old_lease(Link *link, bool force) { - if (!link->dhcp_address_old && set_isempty(link->dhcp_routes_old)) - return 0; - -- if (!force && (link->dhcp_address && !address_is_ready(link->dhcp_address))) { -- log_link_debug(link, "New DHCPv4 address is not ready. The old lease will be removed later."); -- link->dhcp_address->callback = dhcp4_address_callback; -- return 0; -- } -- - log_link_debug(link, "Removing old DHCPv4 address and routes."); - - link_dirty(link); - -- SET_FOREACH(route, link->dhcp_routes_old, i) { -+ SET_FOREACH(route, link->dhcp_routes_old) { - k = route_remove(route, link, NULL); - if (k < 0) - r = k; -@@ -81,7 +63,7 @@ static void dhcp4_check_ready(Link *link) { - link->dhcp4_configured = true; - - /* New address and routes are configured now. Let's release old lease. */ -- r = dhcp4_release_old_lease(link, false); -+ r = dhcp4_release_old_lease(link); - if (r < 0) { - link_enter_failed(link); - return; -@@ -251,11 +233,10 @@ static int dhcp_prefix_route_from_lease( - static int link_set_dhcp_routes(Link *link) { - _cleanup_free_ sd_dhcp_route **static_routes = NULL; - bool classless_route = false, static_route = false; -- const struct in_addr *router; - struct in_addr address; -- int r, n, i; - uint32_t table; - Route *rt; -+ int r, n; - - assert(link); - -@@ -298,9 +279,9 @@ static int link_set_dhcp_routes(Link *link) { - if (n == -ENODATA) - log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m"); - else if (n < 0) -- log_link_debug_errno(link, n, "DHCP: could not get routes: %m"); -+ return log_link_error_errno(link, n, "DHCP: could not get routes: %m"); - -- for (i = 0; i < n; i++) { -+ for (int i = 0; i < n; i++) { - switch (sd_dhcp_route_get_option(static_routes[i])) { - case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE: - classless_route = true; -@@ -312,11 +293,14 @@ static int link_set_dhcp_routes(Link *link) { - } - - if (link->network->dhcp_use_routes) { -- for (i = 0; i < n; i++) { -+ /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option, -+ * the DHCP client MUST ignore the Static Routes option. */ -+ if (classless_route && static_route) -+ log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option"); -+ -+ for (int i = 0; i < n; i++) { - _cleanup_(route_freep) Route *route = NULL; - -- /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option, -- the DHCP client MUST ignore the Static Routes option. */ - if (classless_route && - sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE) - continue; -@@ -347,20 +331,20 @@ static int link_set_dhcp_routes(Link *link) { - } - - if (link->network->dhcp_use_gateway) { -+ const struct in_addr *router; -+ - r = sd_dhcp_lease_get_router(link->dhcp_lease, &router); - if (IN_SET(r, 0, -ENODATA)) - log_link_info(link, "DHCP: No gateway received from DHCP server."); - else if (r < 0) -- log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); -+ return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m"); - else if (in4_addr_is_null(&router[0])) - log_link_info(link, "DHCP: Received gateway is null."); -- -- /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and -- a Router option, the DHCP client MUST ignore the Router option. */ -- if (classless_route && static_route) -- log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option"); -- -- if (r > 0 && !classless_route && !in4_addr_is_null(&router[0])) { -+ else if (classless_route) -+ /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and -+ * a Router option, the DHCP client MUST ignore the Router option. */ -+ log_link_warning(link, "Classless static routes received from DHCP server: ignoring router option"); -+ else { - _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL; - - r = route_new(&route_gw); -@@ -399,20 +383,20 @@ static int link_set_dhcp_routes(Link *link) { - r = dhcp_route_configure(route, link); - if (r < 0) - return log_link_error_errno(link, r, "Could not set router: %m"); -- } - -- LIST_FOREACH(routes, rt, link->network->static_routes) { -- if (!rt->gateway_from_dhcp) -- continue; -+ LIST_FOREACH(routes, rt, link->network->static_routes) { -+ if (!rt->gateway_from_dhcp) -+ continue; - -- if (rt->family != AF_INET) -- continue; -+ if (rt->family != AF_INET) -+ continue; - -- rt->gw.in = router[0]; -+ rt->gw.in = router[0]; - -- r = dhcp_route_configure(rt, link); -- if (r < 0) -- return log_link_error_errno(link, r, "Could not set gateway: %m"); -+ r = dhcp_route_configure(rt, link); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Could not set gateway: %m"); -+ } - } - } - -@@ -429,18 +413,17 @@ static int dhcp_reset_mtu(Link *link) { - return 0; - - r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu); -+ if (r == -ENODATA) -+ return 0; - if (r < 0) -- return r; -+ return log_link_error_errno(link, r, "DHCP error: failed to get MTU from lease: %m"); - - if (link->original_mtu == mtu) - return 0; - - r = link_set_mtu(link, link->original_mtu); -- if (r < 0) { -- log_link_error_errno(link, r, "DHCP error: could not reset MTU: %m"); -- link_enter_failed(link); -- return r; -- } -+ if (r < 0) -+ return log_link_error_errno(link, r, "DHCP error: could not reset MTU: %m"); - - return 0; - } -@@ -523,12 +506,11 @@ static int dhcp4_remove_address_handler(sd_netlink *rtnl, sd_netlink_message *m, - - static int dhcp4_remove_all(Link *link) { - Route *route; -- Iterator i; - int k, r = 0; - - assert(link); - -- SET_FOREACH(route, link->dhcp_routes, i) { -+ SET_FOREACH(route, link->dhcp_routes) { - k = route_remove(route, link, dhcp4_remove_route_handler); - if (k < 0) - r = k; -@@ -558,7 +540,7 @@ static int dhcp_lease_lost(Link *link) { - link->dhcp4_configured = false; - - /* dhcp_lease_lost() may be called during renewing IP address. */ -- k = dhcp4_release_old_lease(link, true); -+ k = dhcp4_release_old_lease(link); - if (k < 0) - r = k; - -@@ -626,7 +608,7 @@ static void dhcp_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { - assert_not_reached("Invalid IPv4ACD event."); - } - -- sd_ipv4acd_stop(acd); -+ (void) sd_ipv4acd_stop(acd); - - return; - } -@@ -657,6 +639,7 @@ static int configure_dhcpv4_duplicate_address_detection(Link *link) { - - static int dhcp4_start_acd(Link *link) { - union in_addr_union addr; -+ struct in_addr old; - int r; - - if (!link->network->dhcp_send_decline) -@@ -665,12 +648,18 @@ static int dhcp4_start_acd(Link *link) { - if (!link->dhcp_lease) - return 0; - -+ (void) sd_ipv4acd_stop(link->network->dhcp_acd); -+ - link->dhcp4_address_bind = false; - - r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr.in); - if (r < 0) - return r; - -+ r = sd_ipv4acd_get_address(link->network->dhcp_acd, &old); -+ if (r < 0) -+ return r; -+ - r = sd_ipv4acd_set_address(link->network->dhcp_acd, &addr.in); - if (r < 0) - return r; -@@ -686,13 +675,41 @@ static int dhcp4_start_acd(Link *link) { - log_link_debug(link, "Starting IPv4ACD client. Probing DHCPv4 address %s", strna(pretty)); - } - -- r = sd_ipv4acd_start(link->network->dhcp_acd, true); -+ r = sd_ipv4acd_start(link->network->dhcp_acd, !in4_addr_equal(&addr.in, &old)); - if (r < 0) - return r; - - return 1; - } - -+static int dhcp4_address_ready_callback(Address *address) { -+ Link *link; -+ int r; -+ -+ assert(address); -+ -+ link = address->link; -+ -+ /* Do not call this again. */ -+ address->callback = NULL; -+ -+ r = link_set_dhcp_routes(link); -+ if (r < 0) -+ return r; -+ -+ /* Reconfigure static routes as kernel may remove some routes when lease expires. */ -+ r = link_request_set_routes(link); -+ if (r < 0) -+ return r; -+ -+ r = dhcp4_start_acd(link); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Failed to start IPv4ACD for DHCP4 address: %m"); -+ -+ dhcp4_check_ready(link); -+ return 0; -+} -+ - static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - -@@ -709,27 +726,14 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * - } else if (r >= 0) - (void) manager_rtnl_process_address(rtnl, m, link->manager); - -- r = link_set_dhcp_routes(link); -- if (r < 0) { -- link_enter_failed(link); -- return 1; -- } -- -- /* Add back static routes since kernel removes while DHCPv4 address is removed from when lease expires */ -- r = link_request_set_routes(link); -- if (r < 0) { -- link_enter_failed(link); -- return 1; -- } -- -- r = dhcp4_start_acd(link); -- if (r < 0) { -- log_link_error_errno(link, r, "Failed to start IPv4ACD for DHCP4 adddress: %m"); -- link_enter_failed(link); -- return 1; -- } -- -- dhcp4_check_ready(link); -+ if (address_is_ready(link->dhcp_address)) { -+ r = dhcp4_address_ready_callback(link->dhcp_address); -+ if (r < 0) { -+ link_enter_failed(link); -+ return 1; -+ } -+ } else -+ link->dhcp_address->callback = dhcp4_address_ready_callback; - - return 1; - } -@@ -1239,7 +1243,6 @@ int dhcp4_set_client_identifier(Link *link) { - int dhcp4_configure(Link *link) { - sd_dhcp_option *send_option; - void *request_options; -- Iterator i; - int r; - - assert(link); -@@ -1331,7 +1334,7 @@ int dhcp4_configure(Link *link) { - return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for timezone: %m"); - } - -- SET_FOREACH(request_options, link->network->dhcp_request_options, i) { -+ SET_FOREACH(request_options, link->network->dhcp_request_options) { - uint32_t option = PTR_TO_UINT32(request_options); - - r = sd_dhcp_client_set_request_option(link->dhcp_client, option); -@@ -1343,7 +1346,7 @@ int dhcp4_configure(Link *link) { - return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for '%u': %m", option); - } - -- ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_options, i) { -+ ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_options) { - r = sd_dhcp_client_add_option(link->dhcp_client, send_option); - if (r == -EEXIST) - continue; -@@ -1351,7 +1354,7 @@ int dhcp4_configure(Link *link) { - return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m"); - } - -- ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_vendor_options, i) { -+ ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_vendor_options) { - r = sd_dhcp_client_add_vendor_option(link->dhcp_client, send_option); - if (r == -EEXIST) - continue; -diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c -index d671284..7996e82 100644 ---- a/src/network/networkd-dhcp6.c -+++ b/src/network/networkd-dhcp6.c -@@ -108,13 +108,12 @@ static int dhcp6_pd_remove_old(Link *link, bool force); - - static int dhcp6_pd_address_callback(Address *address) { - Address *a; -- Iterator i; - - assert(address); - assert(address->link); - - /* Make this called only once */ -- SET_FOREACH(a, address->link->dhcp6_pd_addresses, i) -+ SET_FOREACH(a, address->link->dhcp6_pd_addresses) - a->callback = NULL; - - return dhcp6_pd_remove_old(address->link, true); -@@ -123,7 +122,6 @@ static int dhcp6_pd_address_callback(Address *address) { - static int dhcp6_pd_remove_old(Link *link, bool force) { - Address *address; - Route *route; -- Iterator i; - int k, r = 0; - - assert(link); -@@ -138,14 +136,14 @@ static int dhcp6_pd_remove_old(Link *link, bool force) { - if (!force) { - bool set_callback = !set_isempty(link->dhcp6_pd_addresses); - -- SET_FOREACH(address, link->dhcp6_pd_addresses, i) -+ SET_FOREACH(address, link->dhcp6_pd_addresses) - if (address_is_ready(address)) { - set_callback = false; - break; - } - - if (set_callback) { -- SET_FOREACH(address, link->dhcp6_pd_addresses, i) -+ SET_FOREACH(address, link->dhcp6_pd_addresses) - address->callback = dhcp6_pd_address_callback; - return 0; - } -@@ -155,16 +153,17 @@ static int dhcp6_pd_remove_old(Link *link, bool force) { - - link_dirty(link); - -- SET_FOREACH(route, link->dhcp6_pd_routes_old, i) { -+ SET_FOREACH(route, link->dhcp6_pd_routes_old) { - k = route_remove(route, link, NULL); - if (k < 0) - r = k; - -- (void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64); -+ if (link->radv) -+ (void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64); - dhcp6_pd_free(hashmap_get(link->manager->dhcp6_prefixes, &route->dst.in6)); - } - -- SET_FOREACH(address, link->dhcp6_pd_addresses_old, i) { -+ SET_FOREACH(address, link->dhcp6_pd_addresses_old) { - k = address_remove(address, link, NULL); - if (k < 0) - r = k; -@@ -176,7 +175,6 @@ static int dhcp6_pd_remove_old(Link *link, bool force) { - int dhcp6_pd_remove(Link *link) { - Address *address; - Route *route; -- Iterator i; - int k, r = 0; - - assert(link); -@@ -196,16 +194,17 @@ int dhcp6_pd_remove(Link *link) { - - link_dirty(link); - -- SET_FOREACH(route, link->dhcp6_pd_routes, i) { -+ SET_FOREACH(route, link->dhcp6_pd_routes) { - k = route_remove(route, link, NULL); - if (k < 0) - r = k; - -- (void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64); -+ if (link->radv) -+ (void) sd_radv_remove_prefix(link->radv, &route->dst.in6, 64); - dhcp6_pd_free(hashmap_get(link->manager->dhcp6_prefixes, &route->dst.in6)); - } - -- SET_FOREACH(address, link->dhcp6_pd_addresses, i) { -+ SET_FOREACH(address, link->dhcp6_pd_addresses) { - k = address_remove(address, link, NULL); - if (k < 0) - r = k; -@@ -517,7 +516,6 @@ static void dhcp6_pd_prefix_distribute(Link *dhcp6_link, - uint32_t lifetime_valid, - bool assign_preferred_subnet_id) { - -- Iterator i; - Link *link; - int r; - -@@ -526,7 +524,7 @@ static void dhcp6_pd_prefix_distribute(Link *dhcp6_link, - assert(masked_pd_prefix); - assert(pd_prefix_len <= 64); - -- HASHMAP_FOREACH(link, dhcp6_link->manager->links, i) { -+ HASHMAP_FOREACH(link, dhcp6_link->manager->links) { - _cleanup_free_ char *assigned_buf = NULL; - union in_addr_union assigned_prefix; - -@@ -636,13 +634,12 @@ static int dhcp6_pd_finalize(Link *link) { - - static void dhcp6_pd_prefix_lost(Link *dhcp6_link) { - Link *link; -- Iterator i; - int r; - - assert(dhcp6_link); - assert(dhcp6_link->manager); - -- HASHMAP_FOREACH(link, dhcp6_link->manager->links, i) { -+ HASHMAP_FOREACH(link, dhcp6_link->manager->links) { - if (link == dhcp6_link) - continue; - -@@ -659,13 +656,12 @@ static int dhcp6_remove_old(Link *link, bool force); - - static int dhcp6_address_callback(Address *address) { - Address *a; -- Iterator i; - - assert(address); - assert(address->link); - - /* Make this called only once */ -- SET_FOREACH(a, address->link->dhcp6_addresses, i) -+ SET_FOREACH(a, address->link->dhcp6_addresses) - a->callback = NULL; - - return dhcp6_remove_old(address->link, true); -@@ -674,7 +670,6 @@ static int dhcp6_address_callback(Address *address) { - static int dhcp6_remove_old(Link *link, bool force) { - Address *address; - Route *route; -- Iterator i; - int k, r = 0; - - assert(link); -@@ -688,14 +683,14 @@ static int dhcp6_remove_old(Link *link, bool force) { - if (!force) { - bool set_callback = !set_isempty(link->dhcp6_addresses); - -- SET_FOREACH(address, link->dhcp6_addresses, i) -+ SET_FOREACH(address, link->dhcp6_addresses) - if (address_is_ready(address)) { - set_callback = false; - break; - } - - if (set_callback) { -- SET_FOREACH(address, link->dhcp6_addresses, i) -+ SET_FOREACH(address, link->dhcp6_addresses) - address->callback = dhcp6_address_callback; - return 0; - } -@@ -705,13 +700,13 @@ static int dhcp6_remove_old(Link *link, bool force) { - - link_dirty(link); - -- SET_FOREACH(route, link->dhcp6_routes_old, i) { -+ SET_FOREACH(route, link->dhcp6_routes_old) { - k = route_remove(route, link, NULL); - if (k < 0) - r = k; - } - -- SET_FOREACH(address, link->dhcp6_addresses_old, i) { -+ SET_FOREACH(address, link->dhcp6_addresses_old) { - k = address_remove(address, link, NULL); - if (k < 0) - r = k; -@@ -723,7 +718,6 @@ static int dhcp6_remove_old(Link *link, bool force) { - static int dhcp6_remove(Link *link) { - Address *address; - Route *route; -- Iterator i; - int k, r = 0; - - assert(link); -@@ -742,13 +736,13 @@ static int dhcp6_remove(Link *link) { - - link_dirty(link); - -- SET_FOREACH(route, link->dhcp6_routes, i) { -+ SET_FOREACH(route, link->dhcp6_routes) { - k = route_remove(route, link, NULL); - if (k < 0) - r = k; - } - -- SET_FOREACH(address, link->dhcp6_addresses, i) { -+ SET_FOREACH(address, link->dhcp6_addresses) { - k = address_remove(address, link, NULL); - if (k < 0) - r = k; -@@ -846,14 +840,13 @@ static int dhcp6_set_unreachable_route(Link *link, const union in_addr_union *ad - } - - static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { -- Iterator i; - Link *link; - int r; - - assert(dhcp6_link); - assert(dhcp6_link->dhcp6_lease); - -- HASHMAP_FOREACH(link, dhcp6_link->manager->links, i) { -+ HASHMAP_FOREACH(link, dhcp6_link->manager->links) { - if (link == dhcp6_link) - continue; - -@@ -918,7 +911,7 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) { - false); - } - -- HASHMAP_FOREACH(link, dhcp6_link->manager->links, i) { -+ HASHMAP_FOREACH(link, dhcp6_link->manager->links) { - if (link == dhcp6_link) - continue; - -@@ -992,7 +985,8 @@ static int dhcp6_update_address( - addr->cinfo.ifa_valid = lifetime_valid; - - (void) in_addr_to_string(addr->family, &addr->in_addr, &buffer); -- log_link_info(link, "DHCPv6 address %s/%u timeout preferred %d valid %d", -+ log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO, -+ "DHCPv6 address %s/%u timeout preferred %d valid %d", - strna(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid); - - r = address_configure(addr, link, dhcp6_address_handler, true, &ret); -@@ -1229,7 +1223,6 @@ int dhcp6_request_address(Link *link, int ir) { - - int dhcp6_request_prefix_delegation(Link *link) { - Link *l; -- Iterator i; - - assert(link); - assert(link->manager); -@@ -1239,7 +1232,7 @@ int dhcp6_request_prefix_delegation(Link *link) { - - log_link_debug(link, "Requesting DHCPv6 prefixes to be delegated for new link"); - -- HASHMAP_FOREACH(l, link->manager->links, i) { -+ HASHMAP_FOREACH(l, link->manager->links) { - int r, enabled; - - if (l == link) -@@ -1333,12 +1326,11 @@ static int dhcp6_set_hostname(sd_dhcp6_client *client, Link *link) { - - static bool dhcp6_enable_prefix_delegation(Link *dhcp6_link) { - Link *link; -- Iterator i; - - assert(dhcp6_link); - assert(dhcp6_link->manager); - -- HASHMAP_FOREACH(link, dhcp6_link->manager->links, i) { -+ HASHMAP_FOREACH(link, dhcp6_link->manager->links) { - if (link == dhcp6_link) - continue; - -@@ -1357,7 +1349,6 @@ int dhcp6_configure(Link *link) { - sd_dhcp6_option *send_option; - void *request_options; - const DUID *duid; -- Iterator i; - int r; - - assert(link); -@@ -1399,7 +1390,7 @@ int dhcp6_configure(Link *link) { - if (r < 0) - return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set DUID: %m"); - -- ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp6_client_send_options, i) { -+ ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp6_client_send_options) { - r = sd_dhcp6_client_add_option(client, send_option); - if (r == -EEXIST) - continue; -@@ -1427,7 +1418,7 @@ int dhcp6_configure(Link *link) { - return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set MUD URL: %m"); - } - -- SET_FOREACH(request_options, link->network->dhcp6_request_options, i) { -+ SET_FOREACH(request_options, link->network->dhcp6_request_options) { - uint32_t option = PTR_TO_UINT32(request_options); - - r = sd_dhcp6_client_set_request_option(client, option); -@@ -1451,7 +1442,7 @@ int dhcp6_configure(Link *link) { - return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set vendor class: %m"); - } - -- ORDERED_HASHMAP_FOREACH(vendor_option, link->network->dhcp6_client_send_vendor_options, i) { -+ ORDERED_HASHMAP_FOREACH(vendor_option, link->network->dhcp6_client_send_vendor_options) { - r = sd_dhcp6_client_add_vendor_option(client, vendor_option); - if (r == -EEXIST) - continue; -diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c -index 833d13c..628c398 100644 ---- a/src/network/networkd-fdb.c -+++ b/src/network/networkd-fdb.c -@@ -124,7 +124,7 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { - assert(fdb_entry); - - /* create new RTM message */ -- r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE); -+ r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, AF_BRIDGE); - if (r < 0) - return log_link_error_errno(link, r, "Could not create RTM_NEWNEIGH message: %m"); - -@@ -292,10 +292,12 @@ int config_parse_fdb_destination( - return log_oom(); - - r = in_addr_from_string_auto(rvalue, &fdb_entry->family, &fdb_entry->destination_addr); -- if (r < 0) -- return log_syntax(unit, LOG_WARNING, filename, line, r, -- "FDB destination IP address is invalid, ignoring assignment: %s", -- rvalue); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "FDB destination IP address is invalid, ignoring assignment: %s", -+ rvalue); -+ return 0; -+ } - - fdb_entry = NULL; - -diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c -index f623a9b..072dfac 100644 ---- a/src/network/networkd-link-bus.c -+++ b/src/network/networkd-link-bus.c -@@ -727,7 +727,6 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char *** - Manager *m = userdata; - unsigned c = 0; - Link *link; -- Iterator i; - - assert(bus); - assert(path); -@@ -738,7 +737,7 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char *** - if (!l) - return -ENOMEM; - -- HASHMAP_FOREACH(link, m->links, i) { -+ HASHMAP_FOREACH(link, m->links) { - char *p; - - p = link_bus_path(link); -diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c -index 0057d18..297b26c 100644 ---- a/src/network/networkd-link.c -+++ b/src/network/networkd-link.c -@@ -365,7 +365,6 @@ void link_update_operstate(Link *link, bool also_update_master) { - uint8_t scope = RT_SCOPE_NOWHERE; - bool changed = false; - Address *address; -- Iterator i; - - assert(link); - -@@ -384,7 +383,7 @@ void link_update_operstate(Link *link, bool also_update_master) { - if (carrier_state >= LINK_CARRIER_STATE_CARRIER) { - Link *slave; - -- SET_FOREACH(slave, link->slaves, i) { -+ SET_FOREACH(slave, link->slaves) { - link_update_operstate(slave, false); - - if (slave->carrier_state < LINK_CARRIER_STATE_CARRIER) -@@ -392,7 +391,7 @@ void link_update_operstate(Link *link, bool also_update_master) { - } - } - -- SET_FOREACH(address, link->addresses, i) { -+ SET_FOREACH(address, link->addresses) { - if (!address_is_ready(address)) - continue; - -@@ -401,7 +400,7 @@ void link_update_operstate(Link *link, bool also_update_master) { - } - - /* for operstate we also take foreign addresses into account */ -- SET_FOREACH(address, link->addresses_foreign, i) { -+ SET_FOREACH(address, link->addresses_foreign) { - if (!address_is_ready(address)) - continue; - -@@ -720,7 +719,6 @@ static Link *link_free(Link *link) { - link->dhcp6_pd_routes = set_free(link->dhcp6_pd_routes); - link->dhcp6_pd_routes_old = set_free(link->dhcp6_pd_routes_old); - link->ndisc_routes = set_free(link->ndisc_routes); -- link->ndisc_routes_old = set_free(link->ndisc_routes_old); - - link->nexthops = set_free(link->nexthops); - link->nexthops_foreign = set_free(link->nexthops_foreign); -@@ -736,7 +734,6 @@ static Link *link_free(Link *link) { - link->dhcp6_pd_addresses = set_free(link->dhcp6_pd_addresses); - link->dhcp6_pd_addresses_old = set_free(link->dhcp6_pd_addresses_old); - link->ndisc_addresses = set_free(link->ndisc_addresses); -- link->ndisc_addresses_old = set_free(link->ndisc_addresses_old); - - while ((address = link->pool_addresses)) { - LIST_REMOVE(addresses, link->pool_addresses, address); -@@ -888,10 +885,9 @@ void link_enter_failed(Link *link) { - - static int link_join_netdevs_after_configured(Link *link) { - NetDev *netdev; -- Iterator i; - int r; - -- HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) { -+ HASHMAP_FOREACH(netdev, link->network->stacked_netdevs) { - if (netdev->ifindex > 0) - /* Assume already enslaved. */ - continue; -@@ -1103,7 +1099,6 @@ int link_request_set_routes(Link *link) { - - void link_check_ready(Link *link) { - Address *a; -- Iterator i; - - assert(link); - -@@ -1128,7 +1123,7 @@ void link_check_ready(Link *link) { - return; - } - -- SET_FOREACH(a, link->addresses, i) -+ SET_FOREACH(a, link->addresses) - if (!address_is_ready(a)) { - _cleanup_free_ char *str = NULL; - -@@ -1163,6 +1158,8 @@ void link_check_ready(Link *link) { - } - - if (link_has_carrier(link) || !link->network->configure_without_carrier) { -+ bool has_ndisc_address = false; -+ NDiscAddress *n; - - if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address_configured) { - log_link_debug(link, "%s(): IPv4LL is not configured.", __func__); -@@ -1175,8 +1172,14 @@ void link_check_ready(Link *link) { - return; - } - -+ SET_FOREACH(n, link->ndisc_addresses) -+ if (!n->marked) { -+ has_ndisc_address = true; -+ break; -+ } -+ - if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) && -- !link->dhcp_address && set_isempty(link->dhcp6_addresses) && set_isempty(link->ndisc_addresses) && -+ !link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address && - !(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address_configured)) { - log_link_debug(link, "%s(): DHCP4 or DHCP6 is enabled but no dynamic address is assigned yet.", __func__); - return; -@@ -1251,9 +1254,32 @@ static int link_set_bridge_fdb(Link *link) { - return 0; - } - -+static int link_set_bridge_mdb(Link *link) { -+ MdbEntry *mdb_entry; -+ int r; -+ -+ if (!link->network) -+ return 0; -+ -+ if (LIST_IS_EMPTY(link->network->static_mdb_entries)) -+ return 0; -+ -+ if (!link->network->bridge) { -+ log_link_error(link, "Cannot configure MDB entries on non-bridge port"); -+ return 0; -+ } -+ -+ LIST_FOREACH(static_mdb_entries, mdb_entry, link->network->static_mdb_entries) { -+ r = mdb_entry_configure(link, mdb_entry); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Failed to add entry to multicast group database: %m"); -+ } -+ -+ return 0; -+} -+ - static int static_address_ready_callback(Address *address) { - Address *a; -- Iterator i; - Link *link; - - assert(address); -@@ -1264,7 +1290,7 @@ static int static_address_ready_callback(Address *address) { - if (!link->addresses_configured) - return 0; - -- SET_FOREACH(a, link->static_addresses, i) -+ SET_FOREACH(a, link->static_addresses) - if (!address_is_ready(a)) { - _cleanup_free_ char *str = NULL; - -@@ -1274,7 +1300,7 @@ static int static_address_ready_callback(Address *address) { - } - - /* This should not be called again */ -- SET_FOREACH(a, link->static_addresses, i) -+ SET_FOREACH(a, link->static_addresses) - a->callback = NULL; - - link->addresses_ready = true; -@@ -1365,7 +1391,14 @@ static int link_request_set_addresses(Link *link) { - assert(link->network); - assert(link->state != _LINK_STATE_INVALID); - -+ if (link->address_remove_messages != 0) { -+ log_link_debug(link, "Removing old addresses, new addresses will be configured later."); -+ link->request_static_addresses = true; -+ return 0; -+ } -+ - /* Reset all *_configured flags we are configuring. */ -+ link->request_static_addresses = false; - link->addresses_configured = false; - link->addresses_ready = false; - link->neighbors_configured = false; -@@ -1554,9 +1587,8 @@ static bool link_reduces_vlan_mtu(Link *link) { - static uint32_t link_get_requested_mtu_by_stacked_netdevs(Link *link) { - uint32_t mtu = 0; - NetDev *dev; -- Iterator i; - -- HASHMAP_FOREACH(dev, link->network->stacked_netdevs, i) -+ HASHMAP_FOREACH(dev, link->network->stacked_netdevs) - if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0) - /* See vlan_dev_change_mtu() in kernel. */ - mtu = MAX(mtu, link_reduces_vlan_mtu(link) ? dev->mtu + 4 : dev->mtu); -@@ -2018,7 +2050,6 @@ static int link_set_group(Link *link) { - - static int link_handle_bound_to_list(Link *link) { - Link *l; -- Iterator i; - int r; - bool required_up = false; - bool link_is_up = false; -@@ -2031,7 +2062,7 @@ static int link_handle_bound_to_list(Link *link) { - if (link->flags & IFF_UP) - link_is_up = true; - -- HASHMAP_FOREACH (l, link->bound_to_links, i) -+ HASHMAP_FOREACH (l, link->bound_to_links) - if (link_has_carrier(l)) { - required_up = true; - break; -@@ -2051,7 +2082,6 @@ static int link_handle_bound_to_list(Link *link) { - } - - static int link_handle_bound_by_list(Link *link) { -- Iterator i; - Link *l; - int r; - -@@ -2060,7 +2090,7 @@ static int link_handle_bound_by_list(Link *link) { - if (hashmap_isempty(link->bound_by_links)) - return 0; - -- HASHMAP_FOREACH (l, link->bound_by_links, i) { -+ HASHMAP_FOREACH (l, link->bound_by_links) { - r = link_handle_bound_to_list(l); - if (r < 0) - return r; -@@ -2095,7 +2125,6 @@ static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) { - static int link_new_bound_by_list(Link *link) { - Manager *m; - Link *carrier; -- Iterator i; - int r; - bool list_updated = false; - -@@ -2104,7 +2133,7 @@ static int link_new_bound_by_list(Link *link) { - - m = link->manager; - -- HASHMAP_FOREACH(carrier, m->links, i) { -+ HASHMAP_FOREACH(carrier, m->links) { - if (!carrier->network) - continue; - -@@ -2123,7 +2152,7 @@ static int link_new_bound_by_list(Link *link) { - if (list_updated) - link_dirty(link); - -- HASHMAP_FOREACH(carrier, link->bound_by_links, i) { -+ HASHMAP_FOREACH(carrier, link->bound_by_links) { - r = link_put_carrier(carrier, link, &carrier->bound_to_links); - if (r < 0) - return r; -@@ -2137,7 +2166,6 @@ static int link_new_bound_by_list(Link *link) { - static int link_new_bound_to_list(Link *link) { - Manager *m; - Link *carrier; -- Iterator i; - int r; - bool list_updated = false; - -@@ -2152,7 +2180,7 @@ static int link_new_bound_to_list(Link *link) { - - m = link->manager; - -- HASHMAP_FOREACH (carrier, m->links, i) { -+ HASHMAP_FOREACH (carrier, m->links) { - if (strv_fnmatch(link->network->bind_carrier, carrier->ifname)) { - r = link_put_carrier(link, carrier, &link->bound_to_links); - if (r < 0) -@@ -2165,7 +2193,7 @@ static int link_new_bound_to_list(Link *link) { - if (list_updated) - link_dirty(link); - -- HASHMAP_FOREACH (carrier, link->bound_to_links, i) { -+ HASHMAP_FOREACH (carrier, link->bound_to_links) { - r = link_put_carrier(carrier, link, &carrier->bound_by_links); - if (r < 0) - return r; -@@ -2200,9 +2228,8 @@ static int link_new_carrier_maps(Link *link) { - - static void link_free_bound_to_list(Link *link) { - Link *bound_to; -- Iterator i; - -- HASHMAP_FOREACH (bound_to, link->bound_to_links, i) { -+ HASHMAP_FOREACH (bound_to, link->bound_to_links) { - hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex)); - - if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex))) -@@ -2214,9 +2241,8 @@ static void link_free_bound_to_list(Link *link) { - - static void link_free_bound_by_list(Link *link) { - Link *bound_by; -- Iterator i; - -- HASHMAP_FOREACH (bound_by, link->bound_by_links, i) { -+ HASHMAP_FOREACH (bound_by, link->bound_by_links) { - hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex)); - - if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) { -@@ -2400,7 +2426,6 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li - - static int link_enter_join_netdev(Link *link) { - NetDev *netdev; -- Iterator i; - int r; - - assert(link); -@@ -2473,7 +2498,7 @@ static int link_enter_join_netdev(Link *link) { - } - } - -- HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) { -+ HASHMAP_FOREACH(netdev, link->network->stacked_netdevs) { - - if (netdev->ifindex > 0) - /* Assume already enslaved. */ -@@ -2732,7 +2757,6 @@ static bool link_is_static_route_configured(Link *link, Route *route) { - - static bool link_address_is_dynamic(Link *link, Address *address) { - Route *route; -- Iterator i; - - assert(link); - assert(address); -@@ -2743,7 +2767,7 @@ static bool link_address_is_dynamic(Link *link, Address *address) { - /* Even when the address is leased from a DHCP server, networkd assign the address - * without lifetime when KeepConfiguration=dhcp. So, let's check that we have - * corresponding routes with RTPROT_DHCP. */ -- SET_FOREACH(route, link->routes_foreign, i) { -+ SET_FOREACH(route, link->routes_foreign) { - if (route->protocol != RTPROT_DHCP) - continue; - -@@ -2803,7 +2827,6 @@ static int link_drop_foreign_config(Link *link) { - Address *address; - Neighbor *neighbor; - Route *route; -- Iterator i; - int r; - - /* The kernel doesn't notify us about tentative addresses; -@@ -2814,7 +2837,7 @@ static int link_drop_foreign_config(Link *link) { - return r; - } - -- SET_FOREACH(address, link->addresses_foreign, i) { -+ SET_FOREACH(address, link->addresses_foreign) { - /* we consider IPv6LL addresses to be managed by the kernel */ - if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) - continue; -@@ -2836,7 +2859,7 @@ static int link_drop_foreign_config(Link *link) { - } - } - -- SET_FOREACH(neighbor, link->neighbors_foreign, i) { -+ SET_FOREACH(neighbor, link->neighbors_foreign) { - if (link_is_neighbor_configured(link, neighbor)) { - r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL); - if (r < 0) -@@ -2848,7 +2871,7 @@ static int link_drop_foreign_config(Link *link) { - } - } - -- SET_FOREACH(route, link->routes_foreign, i) { -+ SET_FOREACH(route, link->routes_foreign) { - /* do not touch routes managed by the kernel */ - if (route->protocol == RTPROT_KERNEL) - continue; -@@ -2884,39 +2907,68 @@ static int link_drop_foreign_config(Link *link) { - return 0; - } - -+static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { -+ int r; -+ -+ assert(m); -+ assert(link); -+ assert(link->ifname); -+ assert(link->address_remove_messages > 0); -+ -+ link->address_remove_messages--; -+ -+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) -+ return 1; -+ -+ r = sd_netlink_message_get_errno(m); -+ if (r < 0 && r != -EADDRNOTAVAIL) -+ log_link_message_warning_errno(link, m, r, "Could not drop address"); -+ else if (r >= 0) -+ (void) manager_rtnl_process_address(rtnl, m, link->manager); -+ -+ if (link->address_remove_messages == 0 && link->request_static_addresses) { -+ link_set_state(link, LINK_STATE_CONFIGURING); -+ r = link_request_set_addresses(link); -+ if (r < 0) -+ link_enter_failed(link); -+ } -+ -+ return 1; -+} -+ - static int link_drop_config(Link *link) { - Address *address, *pool_address; - Neighbor *neighbor; - Route *route; -- Iterator i; - int r; - -- SET_FOREACH(address, link->addresses, i) { -+ SET_FOREACH(address, link->addresses) { - /* we consider IPv6LL addresses to be managed by the kernel */ - if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) - continue; - -- r = address_remove(address, link, NULL); -+ r = address_remove(address, link, remove_static_address_handler); - if (r < 0) - return r; - -+ link->address_remove_messages++; -+ - /* If this address came from an address pool, clean up the pool */ -- LIST_FOREACH(addresses, pool_address, link->pool_addresses) { -+ LIST_FOREACH(addresses, pool_address, link->pool_addresses) - if (address_equal(address, pool_address)) { - LIST_REMOVE(addresses, link->pool_addresses, pool_address); - address_free(pool_address); - break; - } -- } - } - -- SET_FOREACH(neighbor, link->neighbors, i) { -+ SET_FOREACH(neighbor, link->neighbors) { - r = neighbor_remove(neighbor, link, NULL); - if (r < 0) - return r; - } - -- SET_FOREACH(route, link->routes, i) { -+ SET_FOREACH(route, link->routes) { - /* do not touch routes managed by the kernel */ - if (route->protocol == RTPROT_KERNEL) - continue; -@@ -2951,13 +3003,12 @@ static int link_configure_ipv4_dad(Link *link) { - - static int link_configure_traffic_control(Link *link) { - TrafficControl *tc; -- Iterator i; - int r; - - link->tc_configured = false; - link->tc_messages = 0; - -- ORDERED_HASHMAP_FOREACH(tc, link->network->tc_by_section, i) { -+ ORDERED_HASHMAP_FOREACH(tc, link->network->tc_by_section) { - r = traffic_control_configure(link, tc); - if (r < 0) - return r; -@@ -2973,13 +3024,12 @@ static int link_configure_traffic_control(Link *link) { - - static int link_configure_sr_iov(Link *link) { - SRIOV *sr_iov; -- Iterator i; - int r; - - link->sr_iov_configured = false; - link->sr_iov_messages = 0; - -- ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section, i) { -+ ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) { - r = sr_iov_configure(link, sr_iov); - if (r < 0) - return r; -@@ -3881,6 +3931,10 @@ static int link_carrier_gained(Link *link) { - if (r < 0) - return r; - -+ r = link_set_bridge_mdb(link); -+ if (r < 0) -+ return r; -+ - return 0; - } - -@@ -4181,7 +4235,6 @@ int link_update(Link *link, sd_netlink_message *m) { - - static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) { - bool space = false; -- Iterator i; - Link *link; - - assert(f); -@@ -4191,7 +4244,7 @@ static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) { - return; - - fputs(prefix, f); -- HASHMAP_FOREACH(link, h, i) { -+ HASHMAP_FOREACH(link, h) { - if (space) - fputc(' ', f); - -@@ -4276,7 +4329,6 @@ int link_save(Link *link) { - _cleanup_fclose_ FILE *f = NULL; - Route *route; - Address *a; -- Iterator i; - int r; - - assert(link); -@@ -4358,7 +4410,7 @@ int link_save(Link *link) { - if (link->network->ipv6_accept_ra_use_dns && link->ndisc_rdnss) { - NDiscRDNSS *dd; - -- SET_FOREACH(dd, link->ndisc_rdnss, i) -+ SET_FOREACH(dd, link->ndisc_rdnss) - serialize_in6_addrs(f, &dd->address, 1, &space); - } - -@@ -4396,7 +4448,7 @@ int link_save(Link *link) { - - fputs("DOMAINS=", f); - space = false; -- ORDERED_SET_FOREACH(p, link->search_domains ?: link->network->search_domains, i) -+ ORDERED_SET_FOREACH(p, link->search_domains ?: link->network->search_domains) - fputs_with_space(f, p, NULL, &space); - - if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) { -@@ -4411,7 +4463,7 @@ int link_save(Link *link) { - if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_YES) { - NDiscDNSSL *dd; - -- SET_FOREACH(dd, link->ndisc_dnssl, i) -+ SET_FOREACH(dd, link->ndisc_dnssl) - fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space); - } - -@@ -4421,7 +4473,7 @@ int link_save(Link *link) { - - fputs("ROUTE_DOMAINS=", f); - space = false; -- ORDERED_SET_FOREACH(p, link->route_domains ?: link->network->route_domains, i) -+ ORDERED_SET_FOREACH(p, link->route_domains ?: link->network->route_domains) - fputs_with_space(f, p, NULL, &space); - - if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) { -@@ -4436,7 +4488,7 @@ int link_save(Link *link) { - if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_ROUTE) { - NDiscDNSSL *dd; - -- SET_FOREACH(dd, link->ndisc_dnssl, i) -+ SET_FOREACH(dd, link->ndisc_dnssl) - fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space); - } - -@@ -4487,7 +4539,7 @@ int link_save(Link *link) { - - fputs("DNSSEC_NTA=", f); - space = false; -- SET_FOREACH(n, nta_anchors, i) -+ SET_FOREACH(n, nta_anchors) - fputs_with_space(f, n, NULL, &space); - fputc('\n', f); - } -@@ -4496,7 +4548,7 @@ int link_save(Link *link) { - - fputs("ADDRESSES=", f); - space = false; -- SET_FOREACH(a, link->addresses, i) { -+ SET_FOREACH(a, link->addresses) { - _cleanup_free_ char *address_str = NULL; - - r = in_addr_to_string(a->family, &a->in_addr, &address_str); -@@ -4512,7 +4564,7 @@ int link_save(Link *link) { - - fputs("ROUTES=", f); - space = false; -- SET_FOREACH(route, link->routes, i) { -+ SET_FOREACH(route, link->routes) { - _cleanup_free_ char *route_str = NULL; - - r = in_addr_to_string(route->family, &route->dst, &route_str); -@@ -4636,10 +4688,10 @@ int log_link_message_full_errno(Link *link, sd_netlink_message *m, int level, in - const char *err_msg = NULL; - - (void) sd_netlink_message_read_string(m, NLMSGERR_ATTR_MSG, &err_msg); -- return log_link_full(link, level, err, -- "%s: %s%s%s%m", -- msg, -- strempty(err_msg), -- err_msg && !endswith(err_msg, ".") ? "." : "", -- err_msg ? " " : ""); -+ return log_link_full_errno(link, level, err, -+ "%s: %s%s%s%m", -+ msg, -+ strempty(err_msg), -+ err_msg && !endswith(err_msg, ".") ? "." : "", -+ err_msg ? " " : ""); - } -diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h -index 7f99c0f..a0c5661 100644 ---- a/src/network/networkd-link.h -+++ b/src/network/networkd-link.h -@@ -75,6 +75,7 @@ typedef struct Link { - LinkAddressState address_state; - - unsigned address_messages; -+ unsigned address_remove_messages; - unsigned address_label_messages; - unsigned neighbor_messages; - unsigned route_messages; -@@ -111,6 +112,7 @@ typedef struct Link { - sd_ipv4ll *ipv4ll; - bool ipv4ll_address_configured:1; - -+ bool request_static_addresses:1; - bool addresses_configured:1; - bool addresses_ready:1; - bool neighbors_configured:1; -@@ -130,8 +132,8 @@ typedef struct Link { - sd_ndisc *ndisc; - Set *ndisc_rdnss; - Set *ndisc_dnssl; -- Set *ndisc_addresses, *ndisc_addresses_old; -- Set *ndisc_routes, *ndisc_routes_old; -+ Set *ndisc_addresses; -+ Set *ndisc_routes; - unsigned ndisc_addresses_messages; - unsigned ndisc_routes_messages; - bool ndisc_addresses_configured:1; -diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c -index 9e0b447..2be7c27 100644 ---- a/src/network/networkd-lldp-tx.c -+++ b/src/network/networkd-lldp-tx.c -@@ -267,7 +267,7 @@ static int lldp_send_packet( - - memcpy(sa.ll.sll_addr, address, ETH_ALEN); - -- fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC, IPPROTO_RAW); -+ fd = socket(AF_PACKET, SOCK_RAW|SOCK_CLOEXEC, IPPROTO_RAW); - if (fd < 0) - return -errno; - -@@ -332,7 +332,7 @@ static int link_send_lldp(Link *link) { - - static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) { - Link *link = userdata; -- usec_t current, delay, next; -+ usec_t delay; - int r; - - assert(s); -@@ -347,12 +347,10 @@ static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) { - if (link->lldp_tx_fast > 0) - link->lldp_tx_fast--; - -- assert_se(sd_event_now(sd_event_source_get_event(s), clock_boottime_or_monotonic(), ¤t) >= 0); -- - delay = link->lldp_tx_fast > 0 ? LLDP_FAST_TX_USEC : LLDP_TX_INTERVAL_USEC; -- next = usec_add(usec_add(current, delay), (usec_t) random_u64() % LLDP_JITTER_USEC); -+ delay = usec_add(delay, (usec_t) random_u64() % LLDP_JITTER_USEC); - -- r = sd_event_source_set_time(s, next); -+ r = sd_event_source_set_time_relative(s, delay); - if (r < 0) - return log_link_error_errno(link, r, "Failed to restart LLDP timer: %m"); - -diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c -index 9db59d9..8dbcdff 100644 ---- a/src/network/networkd-manager-bus.c -+++ b/src/network/networkd-manager-bus.c -@@ -20,7 +20,6 @@ - static int method_list_links(sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - Manager *manager = userdata; -- Iterator i; - Link *link; - int r; - -@@ -32,7 +31,7 @@ static int method_list_links(sd_bus_message *message, void *userdata, sd_bus_err - if (r < 0) - return r; - -- HASHMAP_FOREACH(link, manager->links, i) { -+ HASHMAP_FOREACH(link, manager->links) { - _cleanup_free_ char *path = NULL; - - path = link_bus_path(link); -@@ -201,7 +200,6 @@ static int bus_method_reconfigure_link(sd_bus_message *message, void *userdata, - - static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) { - Manager *manager = userdata; -- Iterator i; - Link *link; - int r; - -@@ -222,7 +220,7 @@ static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_err - if (r < 0) - return r; - -- HASHMAP_FOREACH(link, manager->links, i) { -+ HASHMAP_FOREACH(link, manager->links) { - r = link_reconfigure(link, false); - if (r < 0) - return r; -diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c -index a6c1a39..dbbc6b6 100644 ---- a/src/network/networkd-manager.c -+++ b/src/network/networkd-manager.c -@@ -36,11 +36,11 @@ - #include "path-util.h" - #include "set.h" - #include "signal-util.h" -+#include "stat-util.h" - #include "strv.h" - #include "sysctl-util.h" - #include "tmpfile-util.h" - #include "udev-util.h" --#include "virt.h" - - /* use 128 MB for receive socket kernel queue. */ - #define RCVBUF_SIZE (128*1024*1024) -@@ -81,12 +81,11 @@ static int setup_default_address_pool(Manager *m) { - - static int manager_reset_all(Manager *m) { - Link *link; -- Iterator i; - int r; - - assert(m); - -- HASHMAP_FOREACH(link, m->links, i) { -+ HASHMAP_FOREACH(link, m->links) { - r = link_carrier_reset(link); - if (r < 0) - log_link_warning_errno(link, r, "Could not reset carrier: %m"); -@@ -223,14 +222,16 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi - return 0; - } - -- if (!IN_SET(action, DEVICE_ACTION_ADD, DEVICE_ACTION_CHANGE, DEVICE_ACTION_MOVE)) { -- log_device_debug(device, "Ignoring udev %s event for device.", device_action_to_string(action)); -+ /* Ignore the "remove" uevent — let's remove a device only if rtnetlink says so. All other uevents -+ * are "positive" events in some form, i.e. inform us about a changed or new network interface, that -+ * still exists — and we are interested in that. */ -+ if (action == DEVICE_ACTION_REMOVE) - return 0; -- } - - r = sd_device_get_ifindex(device, &ifindex); - if (r < 0) { -- log_device_debug_errno(device, r, "Ignoring udev ADD event for device without ifindex or with invalid ifindex: %m"); -+ log_device_debug_errno(device, r, "Ignoring udev %s event for device without ifindex or with invalid ifindex: %m", -+ device_action_to_string(action)); - return 0; - } - -@@ -260,16 +261,19 @@ static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *devi - static int manager_connect_udev(Manager *m) { - int r; - -- /* udev does not initialize devices inside containers, -- * so we rely on them being already initialized before -- * entering the container */ -- if (detect_container() > 0) -+ /* udev does not initialize devices inside containers, so we rely on them being already -+ * initialized before entering the container. */ -+ if (path_is_read_only_fs("/sys") > 0) - return 0; - - r = sd_device_monitor_new(&m->device_monitor); - if (r < 0) - return log_error_errno(r, "Failed to initialize device monitor: %m"); - -+ r = sd_device_monitor_set_receive_buffer_size(m->device_monitor, RCVBUF_SIZE); -+ if (r < 0) -+ log_warning_errno(r, "Failed to increase buffer size for device monitor, ignoring: %m"); -+ - r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL); - if (r < 0) - return log_error_errno(r, "Could not add device monitor filter: %m"); -@@ -687,7 +691,7 @@ int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, - switch (type) { - case RTM_NEWNEIGH: - if (neighbor) -- log_link_debug(link, "Remembering neighbor: %s->%s", -+ log_link_debug(link, "Received remembered neighbor: %s->%s", - strnull(addr_str), strnull(lladdr_str)); - else { - /* A neighbor appeared that we did not request */ -@@ -1078,9 +1082,6 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi - assert_not_reached("Received rule message with unsupported address family"); - } - -- if (tmp->from_prefixlen == 0 && tmp->to_prefixlen == 0) -- return 0; -- - r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags); - if (r < 0) { - log_warning_errno(r, "rtnl: received rule message without valid flag, ignoring: %m"); -@@ -1177,9 +1178,12 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi - - switch (type) { - case RTM_NEWRULE: -- if (!rule) { -- log_debug("Remembering foreign routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u", -- from, tmp->from_prefixlen, to, tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); -+ if (rule) -+ log_debug("Received remembered routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, -+ tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); -+ else { -+ log_debug("Remembering foreign routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, -+ tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); - r = routing_policy_rule_add_foreign(m, tmp, &rule); - if (r < 0) { - log_warning_errno(r, "Could not remember foreign rule, ignoring: %m"); -@@ -1188,10 +1192,13 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, voi - } - break; - case RTM_DELRULE: -- log_debug("Forgetting routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u", -- from, tmp->from_prefixlen, to, tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); -- routing_policy_rule_free(rule); -- -+ if (rule) { -+ log_debug("Forgetting routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, -+ tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); -+ routing_policy_rule_free(rule); -+ } else -+ log_debug("Kernel removed a routing policy rule we don't remember: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32", ignoring.", -+ tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); - break; - - default: -@@ -1294,19 +1301,24 @@ int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, - - switch (type) { - case RTM_NEWNEXTHOP: -- if (!nexthop) { -- log_debug("Remembering foreign nexthop: %s, oif: %d, id: %d", gateway, tmp->oif, tmp->id); -+ if (nexthop) -+ log_link_debug(link, "Received remembered nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); -+ else { -+ log_link_debug(link, "Remembering foreign nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); - r = nexthop_add_foreign(link, tmp, &nexthop); - if (r < 0) { -- log_warning_errno(r, "Could not remember foreign nexthop, ignoring: %m"); -+ log_link_warning_errno(link, r, "Could not remember foreign nexthop, ignoring: %m"); - return 0; - } - } - break; - case RTM_DELNEXTHOP: -- log_debug("Forgetting foreign nexthop: %s, oif: %d, id: %d", gateway, tmp->oif, tmp->id); -- nexthop_free(nexthop); -- -+ if (nexthop) { -+ log_link_debug(link, "Forgetting nexthop: %s, oif: %d, id: %d", strna(gateway), tmp->oif, tmp->id); -+ nexthop_free(nexthop); -+ } else -+ log_link_debug(link, "Kernel removed a nexthop we don't remember: %s, oif: %d, id: %d, ignoring.", -+ strna(gateway), tmp->oif, tmp->id); - break; - - default: -@@ -1346,7 +1358,7 @@ static int manager_connect_genl(Manager *m) { - - r = sd_netlink_inc_rcvbuf(m->genl, RCVBUF_SIZE); - if (r < 0) -- return r; -+ log_warning_errno(r, "Failed to increase receive buffer size for general netlink socket, ignoring: %m"); - - r = sd_netlink_attach_event(m->genl, m->event, 0); - if (r < 0) -@@ -1368,9 +1380,14 @@ static int manager_connect_rtnl(Manager *m) { - if (r < 0) - return r; - -- r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE); -- if (r < 0) -- return r; -+ /* Bump receiver buffer, but only if we are not called via socket activation, as in that -+ * case systemd sets the receive buffer size for us, and the value in the .socket unit -+ * should take full effect. */ -+ if (fd < 0) { -+ r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE); -+ if (r < 0) -+ log_warning_errno(r, "Failed to increase receive buffer size for rtnl socket, ignoring: %m"); -+ } - - r = sd_netlink_attach_event(m->rtnl, m->event, 0); - if (r < 0) -@@ -1517,7 +1534,6 @@ static int manager_save(Manager *m) { - _cleanup_strv_free_ char **p = NULL; - _cleanup_fclose_ FILE *f = NULL; - Link *link; -- Iterator i; - int r; - - assert(m); -@@ -1544,7 +1560,7 @@ static int manager_save(Manager *m) { - if (!route_domains) - return -ENOMEM; - -- HASHMAP_FOREACH(link, m->links, i) { -+ HASHMAP_FOREACH(link, m->links) { - const struct in_addr *addresses; - - if (link->flags & IFF_LOOPBACK) -@@ -1721,14 +1737,13 @@ fail: - static int manager_dirty_handler(sd_event_source *s, void *userdata) { - Manager *m = userdata; - Link *link; -- Iterator i; - - assert(m); - - if (m->dirty) - manager_save(m); - -- SET_FOREACH(link, m->dirty_links, i) -+ SET_FOREACH(link, m->dirty_links) - (void) link_save_and_clean(link); - - return 1; -@@ -1825,14 +1840,13 @@ int manager_new(Manager **ret) { - void manager_free(Manager *m) { - AddressPool *pool; - Link *link; -- Iterator i; - - if (!m) - return; - - free(m->state_file); - -- HASHMAP_FOREACH(link, m->links, i) -+ HASHMAP_FOREACH(link, m->links) - (void) link_stop_clients(link, true); - - m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free); -@@ -1878,7 +1892,6 @@ void manager_free(Manager *m) { - - int manager_start(Manager *m) { - Link *link; -- Iterator i; - int r; - - assert(m); -@@ -1892,7 +1905,7 @@ int manager_start(Manager *m) { - - manager_save(m); - -- HASHMAP_FOREACH(link, m->links, i) -+ HASHMAP_FOREACH(link, m->links) - (void) link_save(link); - - return 0; -diff --git a/src/network/networkd-mdb.c b/src/network/networkd-mdb.c -new file mode 100644 -index 0000000..3dec19b ---- /dev/null -+++ b/src/network/networkd-mdb.c -@@ -0,0 +1,252 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include -+#include -+#include -+ -+#include "alloc-util.h" -+#include "netlink-util.h" -+#include "networkd-manager.h" -+#include "networkd-mdb.h" -+#include "util.h" -+#include "vlan-util.h" -+ -+#define STATIC_MDB_ENTRIES_PER_NETWORK_MAX 1024U -+ -+/* create a new MDB entry or get an existing one. */ -+static int mdb_entry_new_static( -+ Network *network, -+ const char *filename, -+ unsigned section_line, -+ MdbEntry **ret) { -+ -+ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; -+ _cleanup_(mdb_entry_freep) MdbEntry *mdb_entry = NULL; -+ int r; -+ -+ assert(network); -+ assert(ret); -+ assert(!!filename == (section_line > 0)); -+ -+ /* search entry in hashmap first. */ -+ if (filename) { -+ r = network_config_section_new(filename, section_line, &n); -+ if (r < 0) -+ return r; -+ -+ mdb_entry = hashmap_get(network->mdb_entries_by_section, n); -+ if (mdb_entry) { -+ *ret = TAKE_PTR(mdb_entry); -+ return 0; -+ } -+ } -+ -+ if (network->n_static_mdb_entries >= STATIC_MDB_ENTRIES_PER_NETWORK_MAX) -+ return -E2BIG; -+ -+ /* allocate space for an MDB entry. */ -+ mdb_entry = new(MdbEntry, 1); -+ if (!mdb_entry) -+ return -ENOMEM; -+ -+ /* init MDB structure. */ -+ *mdb_entry = (MdbEntry) { -+ .network = network, -+ }; -+ -+ LIST_PREPEND(static_mdb_entries, network->static_mdb_entries, mdb_entry); -+ network->n_static_mdb_entries++; -+ -+ if (filename) { -+ mdb_entry->section = TAKE_PTR(n); -+ -+ r = hashmap_ensure_allocated(&network->mdb_entries_by_section, &network_config_hash_ops); -+ if (r < 0) -+ return r; -+ -+ r = hashmap_put(network->mdb_entries_by_section, mdb_entry->section, mdb_entry); -+ if (r < 0) -+ return r; -+ } -+ -+ /* return allocated MDB structure. */ -+ *ret = TAKE_PTR(mdb_entry); -+ -+ return 0; -+} -+ -+/* parse the VLAN Id from config files. */ -+int config_parse_mdb_vlan_id( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ -+ Network *network = userdata; -+ _cleanup_(mdb_entry_free_or_set_invalidp) MdbEntry *mdb_entry = NULL; -+ int r; -+ -+ assert(filename); -+ assert(section); -+ assert(lvalue); -+ assert(rvalue); -+ assert(data); -+ -+ r = mdb_entry_new_static(network, filename, section_line, &mdb_entry); -+ if (r < 0) -+ return log_oom(); -+ -+ r = config_parse_vlanid(unit, filename, line, section, -+ section_line, lvalue, ltype, -+ rvalue, &mdb_entry->vlan_id, userdata); -+ if (r < 0) -+ return r; -+ -+ mdb_entry = NULL; -+ -+ return 0; -+} -+ -+/* parse the multicast group from config files. */ -+int config_parse_mdb_group_address( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ -+ Network *network = userdata; -+ _cleanup_(mdb_entry_free_or_set_invalidp) MdbEntry *mdb_entry = NULL; -+ int r; -+ -+ assert(filename); -+ assert(section); -+ assert(lvalue); -+ assert(rvalue); -+ assert(data); -+ -+ r = mdb_entry_new_static(network, filename, section_line, &mdb_entry); -+ if (r < 0) -+ return log_oom(); -+ -+ r = in_addr_from_string_auto(rvalue, &mdb_entry->family, &mdb_entry->group_addr); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Cannot parse multicast group address: %m"); -+ return 0; -+ } -+ -+ mdb_entry = NULL; -+ -+ return 0; -+} -+ -+/* remove and MDB entry. */ -+MdbEntry *mdb_entry_free(MdbEntry *mdb_entry) { -+ if (!mdb_entry) -+ return NULL; -+ -+ if (mdb_entry->network) { -+ LIST_REMOVE(static_mdb_entries, mdb_entry->network->static_mdb_entries, mdb_entry); -+ assert(mdb_entry->network->n_static_mdb_entries > 0); -+ mdb_entry->network->n_static_mdb_entries--; -+ -+ if (mdb_entry->section) -+ hashmap_remove(mdb_entry->network->mdb_entries_by_section, mdb_entry->section); -+ } -+ -+ network_config_section_free(mdb_entry->section); -+ -+ return mfree(mdb_entry); -+} -+ -+static int set_mdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { -+ int r; -+ -+ assert(link); -+ -+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) -+ return 1; -+ -+ r = sd_netlink_message_get_errno(m); -+ if (r < 0 && r != -EEXIST) { -+ log_link_message_warning_errno(link, m, r, "Could not add MDB entry"); -+ link_enter_failed(link); -+ return 1; -+ } -+ -+ return 1; -+} -+ -+int mdb_entry_verify(MdbEntry *mdb_entry) { -+ if (section_is_invalid(mdb_entry->section)) -+ return -EINVAL; -+ -+ if (in_addr_is_multicast(mdb_entry->family, &mdb_entry->group_addr) <= 0) { -+ log_error("No valid MulticastGroupAddress= assignment in this section"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* send a request to the kernel to add an MDB entry */ -+int mdb_entry_configure(Link *link, MdbEntry *mdb_entry) { -+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; -+ struct br_mdb_entry entry; -+ int r; -+ -+ assert(link); -+ assert(link->network); -+ assert(link->manager); -+ assert(mdb_entry); -+ -+ entry = (struct br_mdb_entry) { -+ .state = MDB_PERMANENT, -+ .ifindex = link->ifindex, -+ .vid = mdb_entry->vlan_id, -+ }; -+ -+ /* create new RTM message */ -+ r = sd_rtnl_message_new_mdb(link->manager->rtnl, &req, RTM_NEWMDB, link->network->bridge->ifindex); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Could not create RTM_NEWMDB message: %m"); -+ -+ switch (mdb_entry->family) { -+ case AF_INET: -+ entry.addr.u.ip4 = mdb_entry->group_addr.in.s_addr; -+ entry.addr.proto = htobe16(ETH_P_IP); -+ break; -+ -+ case AF_INET6: -+ entry.addr.u.ip6 = mdb_entry->group_addr.in6; -+ entry.addr.proto = htobe16(ETH_P_IPV6); -+ break; -+ -+ default: -+ assert_not_reached("Invalid address family"); -+ } -+ -+ r = sd_netlink_message_append_data(req, MDBA_SET_ENTRY, &entry, sizeof(entry)); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Could not append MDBA_SET_ENTRY attribute: %m"); -+ -+ r = netlink_call_async(link->manager->rtnl, NULL, req, set_mdb_handler, -+ link_netlink_destroy_callback, link); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); -+ -+ link_ref(link); -+ -+ return 1; -+} -diff --git a/src/network/networkd-mdb.h b/src/network/networkd-mdb.h -new file mode 100644 -index 0000000..9ac8a18 ---- /dev/null -+++ b/src/network/networkd-mdb.h -@@ -0,0 +1,32 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#include "conf-parser.h" -+#include "list.h" -+#include "macro.h" -+#include "networkd-util.h" -+ -+typedef struct Network Network; -+typedef struct MdbEntry MdbEntry; -+typedef struct Link Link; -+typedef struct NetworkConfigSection NetworkConfigSection; -+ -+struct MdbEntry { -+ Network *network; -+ NetworkConfigSection *section; -+ -+ int family; -+ union in_addr_union group_addr; -+ uint16_t vlan_id; -+ -+ LIST_FIELDS(MdbEntry, static_mdb_entries); -+}; -+ -+int mdb_entry_verify(MdbEntry *mdb_entry); -+MdbEntry *mdb_entry_free(MdbEntry *mdb_entry); -+int mdb_entry_configure(Link *link, MdbEntry *mdb_entry); -+ -+DEFINE_NETWORK_SECTION_FUNCTIONS(MdbEntry, mdb_entry_free); -+ -+CONFIG_PARSER_PROTOTYPE(config_parse_mdb_group_address); -+CONFIG_PARSER_PROTOTYPE(config_parse_mdb_vlan_id); -diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c -index 349f054..68a6664 100644 ---- a/src/network/networkd-ndisc.c -+++ b/src/network/networkd-ndisc.c -@@ -35,79 +35,215 @@ - - #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e) - --static int ndisc_remove_old(Link *link, bool force); -+static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force); - - static int ndisc_address_callback(Address *address) { -- Address *a; -- Iterator i; -+ struct in6_addr router = {}; -+ NDiscAddress *n; - - assert(address); - assert(address->link); - -+ SET_FOREACH(n, address->link->ndisc_addresses) -+ if (n->address == address) { -+ router = n->router; -+ break; -+ } -+ -+ if (IN6_IS_ADDR_UNSPECIFIED(&router)) { -+ _cleanup_free_ char *buf = NULL; -+ -+ (void) in_addr_to_string(address->family, &address->in_addr, &buf); -+ log_link_debug(address->link, "%s is called for %s/%u, but it is already removed, ignoring.", -+ __func__, strna(buf), address->prefixlen); -+ return 0; -+ } -+ - /* Make this called only once */ -- SET_FOREACH(a, address->link->ndisc_addresses, i) -- a->callback = NULL; -+ SET_FOREACH(n, address->link->ndisc_addresses) -+ if (IN6_ARE_ADDR_EQUAL(&n->router, &router)) -+ n->address->callback = NULL; - -- return ndisc_remove_old(address->link, true); -+ return ndisc_remove_old_one(address->link, &router, true); - } - --static int ndisc_remove_old(Link *link, bool force) { -- Address *address; -- Route *route; -+static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool force) { -+ NDiscAddress *na; -+ NDiscRoute *nr; - NDiscDNSSL *dnssl; - NDiscRDNSS *rdnss; -- Iterator i; - int k, r = 0; - - assert(link); -+ assert(router); - - if (!force) { -- bool set_callback = !set_isempty(link->ndisc_addresses); -+ bool set_callback = false; - - if (!link->ndisc_addresses_configured || !link->ndisc_routes_configured) - return 0; - -- SET_FOREACH(address, link->ndisc_addresses, i) -- if (address_is_ready(address)) { -- set_callback = false; -+ SET_FOREACH(na, link->ndisc_addresses) -+ if (!na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) { -+ set_callback = true; - break; - } - -+ if (set_callback) -+ SET_FOREACH(na, link->ndisc_addresses) -+ if (!na->marked && address_is_ready(na->address)) { -+ set_callback = false; -+ break; -+ } -+ - if (set_callback) { -- SET_FOREACH(address, link->ndisc_addresses, i) -- address->callback = ndisc_address_callback; -+ SET_FOREACH(na, link->ndisc_addresses) -+ if (!na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) -+ na->address->callback = ndisc_address_callback; -+ -+ if (DEBUG_LOGGING) { -+ _cleanup_free_ char *buf = NULL; -+ -+ (void) in_addr_to_string(AF_INET6, (union in_addr_union *) router, &buf); -+ log_link_debug(link, "No SLAAC address obtained from %s is ready. " -+ "The old NDisc information will be removed later.", -+ strna(buf)); -+ } - return 0; - } - } - -- if (!set_isempty(link->ndisc_addresses_old) || !set_isempty(link->ndisc_routes_old)) -- log_link_debug(link, "Removing old NDisc addresses and routes."); -+ if (DEBUG_LOGGING) { -+ _cleanup_free_ char *buf = NULL; -+ -+ (void) in_addr_to_string(AF_INET6, (union in_addr_union *) router, &buf); -+ log_link_debug(link, "Removing old NDisc information obtained from %s.", strna(buf)); -+ } - - link_dirty(link); - -- SET_FOREACH(address, link->ndisc_addresses_old, i) { -- k = address_remove(address, link, NULL); -- if (k < 0) -- r = k; -- } -+ SET_FOREACH(na, link->ndisc_addresses) -+ if (na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) { -+ k = address_remove(na->address, link, NULL); -+ if (k < 0) -+ r = k; -+ } - -- SET_FOREACH(route, link->ndisc_routes_old, i) { -- k = route_remove(route, link, NULL); -- if (k < 0) -- r = k; -- } -+ SET_FOREACH(nr, link->ndisc_routes) -+ if (nr->marked && IN6_ARE_ADDR_EQUAL(&nr->router, router)) { -+ k = route_remove(nr->route, link, NULL); -+ if (k < 0) -+ r = k; -+ } - -- SET_FOREACH(rdnss, link->ndisc_rdnss, i) -- if (rdnss->marked) -+ SET_FOREACH(rdnss, link->ndisc_rdnss) -+ if (rdnss->marked && IN6_ARE_ADDR_EQUAL(&rdnss->router, router)) - free(set_remove(link->ndisc_rdnss, rdnss)); - -- SET_FOREACH(dnssl, link->ndisc_dnssl, i) -- if (dnssl->marked) -+ SET_FOREACH(dnssl, link->ndisc_dnssl) -+ if (dnssl->marked && IN6_ARE_ADDR_EQUAL(&dnssl->router, router)) - free(set_remove(link->ndisc_dnssl, dnssl)); - - return r; - } - -+static int ndisc_remove_old(Link *link) { -+ _cleanup_set_free_free_ Set *routers = NULL; -+ _cleanup_free_ struct in6_addr *router = NULL; -+ struct in6_addr *a; -+ NDiscAddress *na; -+ NDiscRoute *nr; -+ NDiscDNSSL *dnssl; -+ NDiscRDNSS *rdnss; -+ int k, r; -+ -+ assert(link); -+ -+ routers = set_new(&in6_addr_hash_ops); -+ if (!routers) -+ return -ENOMEM; -+ -+ SET_FOREACH(na, link->ndisc_addresses) -+ if (!set_contains(routers, &na->router)) { -+ router = newdup(struct in6_addr, &na->router, 1); -+ if (!router) -+ return -ENOMEM; -+ -+ r = set_put(routers, router); -+ if (r < 0) -+ return r; -+ -+ assert(r > 0); -+ TAKE_PTR(router); -+ } -+ -+ SET_FOREACH(nr, link->ndisc_routes) -+ if (!set_contains(routers, &nr->router)) { -+ router = newdup(struct in6_addr, &nr->router, 1); -+ if (!router) -+ return -ENOMEM; -+ -+ r = set_put(routers, router); -+ if (r < 0) -+ return r; -+ -+ assert(r > 0); -+ TAKE_PTR(router); -+ } -+ -+ SET_FOREACH(rdnss, link->ndisc_rdnss) -+ if (!set_contains(routers, &rdnss->router)) { -+ router = newdup(struct in6_addr, &rdnss->router, 1); -+ if (!router) -+ return -ENOMEM; -+ -+ r = set_put(routers, router); -+ if (r < 0) -+ return r; -+ -+ assert(r > 0); -+ TAKE_PTR(router); -+ } -+ -+ SET_FOREACH(dnssl, link->ndisc_dnssl) -+ if (!set_contains(routers, &dnssl->router)) { -+ router = newdup(struct in6_addr, &dnssl->router, 1); -+ if (!router) -+ return -ENOMEM; -+ -+ r = set_put(routers, router); -+ if (r < 0) -+ return r; -+ -+ assert(r > 0); -+ TAKE_PTR(router); -+ } -+ -+ r = 0; -+ SET_FOREACH(a, routers) { -+ k = ndisc_remove_old_one(link, a, false); -+ if (k < 0) -+ r = k; -+ } -+ -+ return r; -+} -+ -+static void ndisc_route_hash_func(const NDiscRoute *x, struct siphash *state) { -+ route_hash_func(x->route, state); -+} -+ -+static int ndisc_route_compare_func(const NDiscRoute *a, const NDiscRoute *b) { -+ return route_compare_func(a->route, b->route); -+} -+ -+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( -+ ndisc_route_hash_ops, -+ NDiscRoute, -+ ndisc_route_hash_func, -+ ndisc_route_compare_func, -+ free); -+ - static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - -@@ -130,7 +266,7 @@ static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li - log_link_debug(link, "NDisc routes set."); - link->ndisc_routes_configured = true; - -- r = ndisc_remove_old(link, false); -+ r = ndisc_remove_old(link); - if (r < 0) { - link_enter_failed(link); - return 1; -@@ -142,6 +278,67 @@ static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li - return 1; - } - -+static int ndisc_route_configure(Route *route, Link *link, sd_ndisc_router *rt) { -+ _cleanup_free_ NDiscRoute *nr = NULL; -+ NDiscRoute *nr_exist; -+ struct in6_addr router; -+ Route *ret; -+ int r; -+ -+ assert(route); -+ assert(link); -+ assert(rt); -+ -+ r = route_configure(route, link, ndisc_route_handler, &ret); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Failed to set NDisc route: %m"); -+ -+ link->ndisc_routes_messages++; -+ -+ r = sd_ndisc_router_get_address(rt, &router); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); -+ -+ nr = new(NDiscRoute, 1); -+ if (!nr) -+ return log_oom(); -+ -+ *nr = (NDiscRoute) { -+ .router = router, -+ .route = ret, -+ }; -+ -+ nr_exist = set_get(link->ndisc_routes, nr); -+ if (nr_exist) { -+ nr_exist->marked = false; -+ nr_exist->router = router; -+ return 0; -+ } -+ -+ r = set_ensure_put(&link->ndisc_routes, &ndisc_route_hash_ops, nr); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Failed to store NDisc SLAAC route: %m"); -+ assert(r > 0); -+ TAKE_PTR(nr); -+ -+ return 0; -+} -+ -+static void ndisc_address_hash_func(const NDiscAddress *x, struct siphash *state) { -+ address_hash_func(x->address, state); -+} -+ -+static int ndisc_address_compare_func(const NDiscAddress *a, const NDiscAddress *b) { -+ return address_compare_func(a->address, b->address); -+} -+ -+DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( -+ ndisc_address_hash_ops, -+ NDiscAddress, -+ ndisc_address_hash_func, -+ ndisc_address_compare_func, -+ free); -+ - static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { - int r; - -@@ -165,7 +362,7 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * - log_link_debug(link, "NDisc SLAAC addresses set."); - link->ndisc_addresses_configured = true; - -- r = ndisc_remove_old(link, false); -+ r = ndisc_remove_old(link); - if (r < 0) { - link_enter_failed(link); - return 1; -@@ -181,34 +378,16 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * - return 1; - } - --static int ndisc_route_configure(Route *route, Link *link) { -- Route *ret; -- int r; -- -- assert(route); -- assert(link); -- -- r = route_configure(route, link, ndisc_route_handler, &ret); -- if (r < 0) -- return log_link_error_errno(link, r, "Failed to set NDisc route: %m"); -- -- link->ndisc_routes_messages++; -- -- r = set_ensure_put(&link->ndisc_routes, &route_hash_ops, ret); -- if (r < 0) -- return log_link_error_errno(link, r, "Failed to store NDisc route: %m"); -- -- (void) set_remove(link->ndisc_routes_old, ret); -- -- return 0; --} -- --static int ndisc_address_configure(Address *address, Link *link) { -+static int ndisc_address_configure(Address *address, Link *link, sd_ndisc_router *rt) { -+ _cleanup_free_ NDiscAddress *na = NULL; -+ NDiscAddress *na_exist; -+ struct in6_addr router; - Address *ret; - int r; - - assert(address); - assert(link); -+ assert(rt); - - r = address_configure(address, link, ndisc_address_handler, true, &ret); - if (r < 0) -@@ -216,11 +395,31 @@ static int ndisc_address_configure(Address *address, Link *link) { - - link->ndisc_addresses_messages++; - -- r = set_ensure_put(&link->ndisc_addresses, &address_hash_ops, ret); -+ r = sd_ndisc_router_get_address(rt, &router); - if (r < 0) -- return log_link_error_errno(link, r, "Failed to store NDisc SLAAC address: %m"); -+ return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); -+ -+ na = new(NDiscAddress, 1); -+ if (!na) -+ return log_oom(); -+ -+ *na = (NDiscAddress) { -+ .router = router, -+ .address = ret, -+ }; -+ -+ na_exist = set_get(link->ndisc_addresses, na); -+ if (na_exist) { -+ na_exist->marked = false; -+ na_exist->router = router; -+ return 0; -+ } - -- (void) set_remove(link->ndisc_addresses_old, ret); -+ r = set_ensure_put(&link->ndisc_addresses, &ndisc_address_hash_ops, na); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Failed to store NDisc SLAAC address: %m"); -+ assert(r > 0); -+ TAKE_PTR(na); - - return 0; - } -@@ -286,7 +485,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { - route->lifetime = time_now + lifetime * USEC_PER_SEC; - route->mtu = mtu; - -- r = ndisc_route_configure(route, link); -+ r = ndisc_route_configure(route, link, rt); - if (r < 0) - return log_link_error_errno(link, r, "Could not set default route: %m"); - -@@ -300,7 +499,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { - - route_gw->gw = gateway; - -- r = ndisc_route_configure(route_gw, link); -+ r = ndisc_route_configure(route_gw, link, rt); - if (r < 0) - return log_link_error_errno(link, r, "Could not set gateway: %m"); - } -@@ -369,7 +568,6 @@ static int make_stableprivate_address(Link *link, const struct in6_addr *prefix, - static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address, uint8_t prefixlen, Set **ret) { - _cleanup_set_free_free_ Set *addresses = NULL; - IPv6Token *j; -- Iterator i; - int r; - - assert(link); -@@ -380,18 +578,18 @@ static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address, - if (!addresses) - return log_oom(); - -- ORDERED_SET_FOREACH(j, link->network->ipv6_tokens, i) { -+ ORDERED_SET_FOREACH(j, link->network->ipv6_tokens) { - _cleanup_free_ struct in6_addr *new_address = NULL; - - if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE -- && IN6_ARE_ADDR_EQUAL(&j->prefix, address)) { -+ && (IN6_IS_ADDR_UNSPECIFIED(&j->prefix) || IN6_ARE_ADDR_EQUAL(&j->prefix, address))) { - /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop - does not actually attempt Duplicate Address Detection; the counter will be incremented - only when the address generation algorithm produces an invalid address, and the loop - may exit with an address which ends up being unusable due to duplication on the link. - */ - for (; j->dad_counter < DAD_CONFLICTS_IDGEN_RETRIES_RFC7217; j->dad_counter++) { -- r = make_stableprivate_address(link, &j->prefix, prefixlen, j->dad_counter, &new_address); -+ r = make_stableprivate_address(link, address, prefixlen, j->dad_counter, &new_address); - if (r < 0) - return r; - if (r > 0) -@@ -448,7 +646,6 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r - struct in6_addr addr, *a; - unsigned prefixlen; - usec_t time_now; -- Iterator i; - int r; - - assert(link); -@@ -491,7 +688,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r - address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR; - address->cinfo.ifa_prefered = lifetime_preferred; - -- SET_FOREACH(a, addresses, i) { -+ SET_FOREACH(a, addresses) { - Address *existing_address; - - /* see RFC4862 section 5.5.3.e */ -@@ -514,7 +711,7 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r - - address->in_addr.in6 = *a; - -- r = ndisc_address_configure(address, link); -+ r = ndisc_address_configure(address, link, rt); - if (r < 0) - return log_link_error_errno(link, r, "Could not set SLAAC address: %m"); - } -@@ -560,7 +757,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { - if (r < 0) - return log_link_error_errno(link, r, "Failed to get prefix address: %m"); - -- r = ndisc_route_configure(route, link); -+ r = ndisc_route_configure(route, link, rt); - if (r < 0) - return log_link_error_errno(link, r, "Could not set prefix route: %m");; - -@@ -617,7 +814,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { - if (r < 0) - return log_link_error_errno(link, r, "Failed to get route address: %m"); - -- r = ndisc_route_configure(route, link); -+ r = ndisc_route_configure(route, link, rt); - if (r < 0) - return log_link_error_errno(link, r, "Could not set additional route: %m"); - -@@ -642,14 +839,18 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( - static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { - uint32_t lifetime; - const struct in6_addr *a; -+ struct in6_addr router; - NDiscRDNSS *rdnss; - usec_t time_now; -- Iterator i; - int n, r; - - assert(link); - assert(rt); - -+ r = sd_ndisc_router_get_address(rt, &router); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); -+ - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); -@@ -662,8 +863,9 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { - if (n < 0) - return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m"); - -- SET_FOREACH(rdnss, link->ndisc_rdnss, i) -- rdnss->marked = true; -+ SET_FOREACH(rdnss, link->ndisc_rdnss) -+ if (IN6_ARE_ADDR_EQUAL(&rdnss->router, &router)) -+ rdnss->marked = true; - - if (lifetime == 0) - return 0; -@@ -682,6 +884,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { - rdnss = set_get(link->ndisc_rdnss, &d); - if (rdnss) { - rdnss->marked = false; -+ rdnss->router = router; - rdnss->valid_until = time_now + lifetime * USEC_PER_SEC; - continue; - } -@@ -692,6 +895,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { - - *x = (NDiscRDNSS) { - .address = a[j], -+ .router = router, - .valid_until = time_now + lifetime * USEC_PER_SEC, - }; - -@@ -721,16 +925,20 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( - - static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { - _cleanup_strv_free_ char **l = NULL; -+ struct in6_addr router; - uint32_t lifetime; - usec_t time_now; - NDiscDNSSL *dnssl; -- Iterator i; - char **j; - int r; - - assert(link); - assert(rt); - -+ r = sd_ndisc_router_get_address(rt, &router); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); -+ - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); - if (r < 0) - return log_link_error_errno(link, r, "Failed to get RA timestamp: %m"); -@@ -743,8 +951,9 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { - if (r < 0) - return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m"); - -- SET_FOREACH(dnssl, link->ndisc_dnssl, i) -- dnssl->marked = true; -+ SET_FOREACH(dnssl, link->ndisc_dnssl) -+ if (IN6_ARE_ADDR_EQUAL(&dnssl->router, &router)) -+ dnssl->marked = true; - - if (lifetime == 0) - return 0; -@@ -767,10 +976,12 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { - dnssl = set_get(link->ndisc_dnssl, s); - if (dnssl) { - dnssl->marked = false; -+ dnssl->router = router; - dnssl->valid_until = time_now + lifetime * USEC_PER_SEC; - continue; - } - -+ s->router = router; - s->valid_until = time_now + lifetime * USEC_PER_SEC; - - r = set_ensure_consume(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops, TAKE_PTR(s)); -@@ -865,9 +1076,10 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { - } - - static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { -- Address *address; -- Route *route; -+ struct in6_addr router; - uint64_t flags; -+ NDiscAddress *na; -+ NDiscRoute *nr; - int r; - - assert(link); -@@ -880,17 +1092,17 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { - - link_dirty(link); - -- while ((address = set_steal_first(link->ndisc_addresses))) { -- r = set_ensure_put(&link->ndisc_addresses_old, &address_hash_ops, address); -- if (r < 0) -- return log_link_error_errno(link, r, "Failed to store old NDisc SLAAC address: %m"); -- } -+ r = sd_ndisc_router_get_address(rt, &router); -+ if (r < 0) -+ return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); - -- while ((route = set_steal_first(link->ndisc_routes))) { -- r = set_ensure_put(&link->ndisc_routes_old, &route_hash_ops, route); -- if (r < 0) -- return log_link_error_errno(link, r, "Failed to store old NDisc route: %m"); -- } -+ SET_FOREACH(na, link->ndisc_addresses) -+ if (IN6_ARE_ADDR_EQUAL(&na->router, &router)) -+ na->marked = true; -+ -+ SET_FOREACH(nr, link->ndisc_routes) -+ if (IN6_ARE_ADDR_EQUAL(&nr->router, &router)) -+ nr->marked = true; - - r = sd_ndisc_router_get_flags(rt, &flags); - if (r < 0) -@@ -933,7 +1145,7 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { - else - log_link_debug(link, "Setting NDisc routes."); - -- r = ndisc_remove_old(link, false); -+ r = ndisc_remove_old(link); - if (r < 0) - return r; - -@@ -1008,7 +1220,6 @@ int ndisc_configure(Link *link) { - void ndisc_vacuum(Link *link) { - NDiscRDNSS *r; - NDiscDNSSL *d; -- Iterator i; - usec_t time_now; - bool updated = false; - -@@ -1018,13 +1229,13 @@ void ndisc_vacuum(Link *link) { - - time_now = now(clock_boottime_or_monotonic()); - -- SET_FOREACH(r, link->ndisc_rdnss, i) -+ SET_FOREACH(r, link->ndisc_rdnss) - if (r->valid_until < time_now) { - free(set_remove(link->ndisc_rdnss, r)); - updated = true; - } - -- SET_FOREACH(d, link->ndisc_dnssl, i) -+ SET_FOREACH(d, link->ndisc_dnssl) - if (d->valid_until < time_now) { - free(set_remove(link->ndisc_dnssl, d)); - updated = true; -@@ -1176,30 +1387,43 @@ int config_parse_address_generation_type( - if (r < 0) - return log_oom(); - -- if ((p = startswith(rvalue, "static:"))) -- token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC; -- else if ((p = startswith(rvalue, "prefixstable:"))) -+ if ((p = startswith(rvalue, "prefixstable"))) { - token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE; -- else { -+ if (*p == ':') -+ p++; -+ else if (*p == '\0') -+ p = NULL; -+ else { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Invalid IPv6 token mode in %s=, ignoring assignment: %s", -+ lvalue, rvalue); -+ return 0; -+ } -+ } else { - token->address_generation_type = IPV6_TOKEN_ADDRESS_GENERATION_STATIC; -- p = rvalue; -+ p = startswith(rvalue, "static:"); -+ if (!p) -+ p = rvalue; - } - -- r = in_addr_from_string(AF_INET6, p, &buffer); -- if (r < 0) { -- log_syntax(unit, LOG_WARNING, filename, line, r, -- "Failed to parse IPv6 %s, ignoring: %s", lvalue, rvalue); -- return 0; -- } -- -- if (in_addr_is_null(AF_INET6, &buffer)) { -- log_syntax(unit, LOG_WARNING, filename, line, 0, -- "IPv6 %s cannot be the ANY address, ignoring: %s", lvalue, rvalue); -- return 0; -+ if (p) { -+ r = in_addr_from_string(AF_INET6, p, &buffer); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse IP address in %s=, ignoring assignment: %s", -+ lvalue, rvalue); -+ return 0; -+ } -+ if (token->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_STATIC && -+ in_addr_is_null(AF_INET6, &buffer)) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s", -+ lvalue, rvalue); -+ return 0; -+ } -+ token->prefix = buffer.in6; - } - -- token->prefix = buffer.in6; -- - r = ordered_set_ensure_allocated(&network->ipv6_tokens, &ipv6_token_hash_ops); - if (r < 0) - return log_oom(); -diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h -index c459f42..927f555 100644 ---- a/src/network/networkd-ndisc.h -+++ b/src/network/networkd-ndisc.h -@@ -2,7 +2,9 @@ - #pragma once - - #include "conf-parser.h" -+#include "networkd-address.h" - #include "networkd-link.h" -+#include "networkd-route.h" - #include "time-util.h" - - typedef struct IPv6Token IPv6Token; -@@ -23,9 +25,24 @@ typedef enum IPv6AcceptRAStartDHCP6Client { - _IPV6_ACCEPT_RA_START_DHCP6_CLIENT_INVALID = -1, - } IPv6AcceptRAStartDHCP6Client; - -+typedef struct NDiscAddress { -+ /* Used when GC'ing old DNS servers when configuration changes. */ -+ bool marked; -+ struct in6_addr router; -+ Address *address; -+} NDiscAddress; -+ -+typedef struct NDiscRoute { -+ /* Used when GC'ing old DNS servers when configuration changes. */ -+ bool marked; -+ struct in6_addr router; -+ Route *route; -+} NDiscRoute; -+ - typedef struct NDiscRDNSS { - /* Used when GC'ing old DNS servers when configuration changes. */ - bool marked; -+ struct in6_addr router; - usec_t valid_until; - struct in6_addr address; - } NDiscRDNSS; -@@ -33,6 +50,7 @@ typedef struct NDiscRDNSS { - typedef struct NDiscDNSSL { - /* Used when GC'ing old domains when configuration changes. */ - bool marked; -+ struct in6_addr router; - usec_t valid_until; - /* The domain name follows immediately. */ - } NDiscDNSSL; -diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c -index a895f72..70fddd5 100644 ---- a/src/network/networkd-network-bus.c -+++ b/src/network/networkd-network-bus.c -@@ -18,7 +18,6 @@ static int property_get_ether_addrs( - - char buf[ETHER_ADDR_TO_STRING_MAX]; - const struct ether_addr *p; -- Iterator i; - Set *s; - int r; - -@@ -32,7 +31,7 @@ static int property_get_ether_addrs( - if (r < 0) - return r; - -- SET_FOREACH(p, s, i) { -+ SET_FOREACH(p, s) { - r = sd_bus_message_append(reply, "s", ether_addr_to_string(p, buf)); - if (r < 0) - return r; -@@ -88,7 +87,6 @@ int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - Network *network; -- Iterator i; - int r; - - assert(bus); -@@ -96,7 +94,7 @@ int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char - assert(m); - assert(nodes); - -- ORDERED_HASHMAP_FOREACH(network, m->networks, i) { -+ ORDERED_HASHMAP_FOREACH(network, m->networks) { - char *p; - - p = network_bus_path(network); -diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf -index 3f1652b..845fafe 100644 ---- a/src/network/networkd-network-gperf.gperf -+++ b/src/network/networkd-network-gperf.gperf -@@ -39,7 +39,7 @@ Match.Type, config_parse_match_strv, - Match.WLANInterfaceType, config_parse_match_strv, 0, offsetof(Network, match_wlan_iftype) - Match.SSID, config_parse_match_strv, 0, offsetof(Network, match_ssid) - Match.BSSID, config_parse_hwaddrs, 0, offsetof(Network, match_bssid) --Match.Name, config_parse_match_ifnames, 1, offsetof(Network, match_name) -+Match.Name, config_parse_match_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(Network, match_name) - Match.Property, config_parse_match_property, 0, offsetof(Network, match_property) - Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions) - Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, conditions) -@@ -265,6 +265,8 @@ BridgeFDB.VLANId, config_parse_fdb_vlan_id, - BridgeFDB.Destination, config_parse_fdb_destination, 0, 0 - BridgeFDB.VNI, config_parse_fdb_vxlan_vni, 0, 0 - BridgeFDB.AssociatedWith, config_parse_fdb_ntf_flags, 0, 0 -+BridgeMDB.MulticastGroupAddress, config_parse_mdb_group_address, 0, 0 -+BridgeMDB.VLANId, config_parse_mdb_vlan_id, 0, 0 - BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0 - BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0 - BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0 -diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c -index d34155b..8187690 100644 ---- a/src/network/networkd-network.c -+++ b/src/network/networkd-network.c -@@ -121,12 +121,11 @@ static int network_resolve_netdev_one(Network *network, const char *name, NetDev - - static int network_resolve_stacked_netdevs(Network *network) { - void *name, *kind; -- Iterator i; - int r; - - assert(network); - -- HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names, i) { -+ HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names) { - _cleanup_(netdev_unrefp) NetDev *netdev = NULL; - - r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev); -@@ -158,9 +157,9 @@ int network_verify(Network *network) { - Prefix *prefix, *prefix_next; - Route *route, *route_next; - FdbEntry *fdb, *fdb_next; -+ MdbEntry *mdb, *mdb_next; - TrafficControl *tc; - SRIOV *sr_iov; -- Iterator i; - - assert(network); - assert(network->filename); -@@ -307,6 +306,10 @@ int network_verify(Network *network) { - if (section_is_invalid(fdb->section)) - fdb_entry_free(fdb); - -+ LIST_FOREACH_SAFE(static_mdb_entries, mdb, mdb_next, network->static_mdb_entries) -+ if (mdb_entry_verify(mdb) < 0) -+ mdb_entry_free(mdb); -+ - LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors) - if (neighbor_section_verify(neighbor) < 0) - neighbor_free(neighbor); -@@ -328,11 +331,11 @@ int network_verify(Network *network) { - routing_policy_rule_free(rule); - - bool has_root = false, has_clsact = false; -- ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section, i) -+ ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section) - if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0) - traffic_control_free(tc); - -- ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section, i) -+ ORDERED_HASHMAP_FOREACH(sr_iov, network->sr_iov_by_section) - if (sr_iov_section_verify(sr_iov) < 0) - sr_iov_free(sr_iov); - -@@ -483,6 +486,9 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi - .keep_configuration = _KEEP_CONFIGURATION_INVALID, - .can_triple_sampling = -1, - .can_termination = -1, -+ .can_listen_only = -1, -+ .can_fd_mode = -1, -+ .can_non_iso = -1, - .ip_service_type = -1, - }; - -@@ -507,6 +513,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi - "IPv6NDPProxyAddress\0" - "Bridge\0" - "BridgeFDB\0" -+ "BridgeMDB\0" - "BridgeVLAN\0" - "IPv6PrefixDelegation\0" - "IPv6Prefix\0" -@@ -597,7 +604,6 @@ int network_load(Manager *manager, OrderedHashmap **networks) { - int network_reload(Manager *manager) { - OrderedHashmap *new_networks = NULL; - Network *n, *old; -- Iterator i; - int r; - - assert(manager); -@@ -606,7 +612,7 @@ int network_reload(Manager *manager) { - if (r < 0) - goto failure; - -- ORDERED_HASHMAP_FOREACH(n, new_networks, i) { -+ ORDERED_HASHMAP_FOREACH(n, new_networks) { - r = network_get_by_name(manager, n->name, &old); - if (r < 0) - continue; /* The .network file is new. */ -@@ -642,6 +648,7 @@ static Network *network_free(Network *network) { - RoutingPolicyRule *rule; - AddressLabel *label; - FdbEntry *fdb_entry; -+ MdbEntry *mdb_entry; - Neighbor *neighbor; - Address *address; - NextHop *nexthop; -@@ -715,6 +722,9 @@ static Network *network_free(Network *network) { - while ((fdb_entry = network->static_fdb_entries)) - fdb_entry_free(fdb_entry); - -+ while ((mdb_entry = network->static_mdb_entries)) -+ mdb_entry_free(mdb_entry); -+ - while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses)) - ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address); - -@@ -737,6 +747,7 @@ static Network *network_free(Network *network) { - hashmap_free(network->routes_by_section); - hashmap_free(network->nexthops_by_section); - hashmap_free(network->fdb_entries_by_section); -+ hashmap_free(network->mdb_entries_by_section); - hashmap_free(network->neighbors_by_section); - hashmap_free(network->address_labels_by_section); - hashmap_free(network->prefixes_by_section); -@@ -795,12 +806,11 @@ int network_get(Manager *manager, unsigned short iftype, sd_device *device, - enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid, - Network **ret) { - Network *network; -- Iterator i; - - assert(manager); - assert(ret); - -- ORDERED_HASHMAP_FOREACH(network, manager->networks, i) -+ ORDERED_HASHMAP_FOREACH(network, manager->networks) - if (net_match_config(network->match_mac, network->match_permanent_mac, - network->match_path, network->match_driver, - network->match_type, network->match_name, network->match_property, -@@ -850,6 +860,7 @@ bool network_has_static_ipv6_configurations(Network *network) { - Address *address; - Route *route; - FdbEntry *fdb; -+ MdbEntry *mdb; - Neighbor *neighbor; - - assert(network); -@@ -866,6 +877,10 @@ bool network_has_static_ipv6_configurations(Network *network) { - if (fdb->family == AF_INET6) - return true; - -+ LIST_FOREACH(static_mdb_entries, mdb, network->static_mdb_entries) -+ if (mdb->family == AF_INET6) -+ return true; -+ - LIST_FOREACH(neighbors, neighbor, network->neighbors) - if (neighbor->family == AF_INET6) - return true; -diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h -index 5dcb3c5..5ba0bc7 100644 ---- a/src/network/networkd-network.h -+++ b/src/network/networkd-network.h -@@ -23,6 +23,7 @@ - #include "networkd-ipv6-proxy-ndp.h" - #include "networkd-lldp-rx.h" - #include "networkd-lldp-tx.h" -+#include "networkd-mdb.h" - #include "networkd-ndisc.h" - #include "networkd-neighbor.h" - #include "networkd-nexthop.h" -@@ -288,6 +289,7 @@ struct Network { - LIST_HEAD(Route, static_routes); - LIST_HEAD(NextHop, static_nexthops); - LIST_HEAD(FdbEntry, static_fdb_entries); -+ LIST_HEAD(MdbEntry, static_mdb_entries); - LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); - LIST_HEAD(Neighbor, neighbors); - LIST_HEAD(AddressLabel, address_labels); -@@ -299,6 +301,7 @@ struct Network { - unsigned n_static_routes; - unsigned n_static_nexthops; - unsigned n_static_fdb_entries; -+ unsigned n_static_mdb_entries; - unsigned n_ipv6_proxy_ndp_addresses; - unsigned n_neighbors; - unsigned n_address_labels; -@@ -310,6 +313,7 @@ struct Network { - Hashmap *routes_by_section; - Hashmap *nexthops_by_section; - Hashmap *fdb_entries_by_section; -+ Hashmap *mdb_entries_by_section; - Hashmap *neighbors_by_section; - Hashmap *address_labels_by_section; - Hashmap *prefixes_by_section; -diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c -index e0c490b..003a50b 100644 ---- a/src/network/networkd-radv.c -+++ b/src/network/networkd-radv.c -@@ -681,7 +681,9 @@ int radv_add_prefix(Link *link, const struct in6_addr *prefix, uint8_t prefix_le - int r; - - assert(link); -- assert(link->radv); -+ -+ if (!link->radv) -+ return 0; - - r = sd_radv_prefix_new(&p); - if (r < 0) -diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c -index 541bf1e..b82c4e7 100644 ---- a/src/network/networkd-route.c -+++ b/src/network/networkd-route.c -@@ -9,6 +9,7 @@ - #include "netlink-util.h" - #include "networkd-ipv4ll.h" - #include "networkd-manager.h" -+#include "networkd-ndisc.h" - #include "networkd-route.h" - #include "parse-util.h" - #include "set.h" -@@ -142,6 +143,8 @@ void route_free(Route *route) { - network_config_section_free(route->section); - - if (route->link) { -+ NDiscRoute *n; -+ - set_remove(route->link->routes, route); - set_remove(route->link->routes_foreign, route); - set_remove(route->link->dhcp_routes, route); -@@ -150,8 +153,9 @@ void route_free(Route *route) { - set_remove(route->link->dhcp6_routes_old, route); - set_remove(route->link->dhcp6_pd_routes, route); - set_remove(route->link->dhcp6_pd_routes_old, route); -- set_remove(route->link->ndisc_routes, route); -- set_remove(route->link->ndisc_routes_old, route); -+ SET_FOREACH(n, route->link->ndisc_routes) -+ if (n->route == route) -+ free(set_remove(route->link->ndisc_routes, n)); - } - - ordered_set_free_free(route->multipath_routes); -@@ -161,7 +165,7 @@ void route_free(Route *route) { - free(route); - } - --static void route_hash_func(const Route *route, struct siphash *state) { -+void route_hash_func(const Route *route, struct siphash *state) { - assert(route); - - siphash24_compress(&route->family, sizeof(route->family), state); -@@ -196,7 +200,7 @@ static void route_hash_func(const Route *route, struct siphash *state) { - } - } - --static int route_compare_func(const Route *a, const Route *b) { -+int route_compare_func(const Route *a, const Route *b) { - int r; - - r = CMP(a->family, b->family); -@@ -570,7 +574,6 @@ static int append_nexthops(Route *route, sd_netlink_message *req) { - struct rtnexthop *rtnh; - MultipathRoute *m; - size_t offset; -- Iterator i; - int r; - - if (ordered_set_isempty(route->multipath_routes)) -@@ -586,7 +589,7 @@ static int append_nexthops(Route *route, sd_netlink_message *req) { - }; - offset = (uint8_t *) RTA_DATA(rta) - (uint8_t *) rta; - -- ORDERED_SET_FOREACH(m, route->multipath_routes, i) { -+ ORDERED_SET_FOREACH(m, route->multipath_routes) { - r = append_nexthop_one(route, m, &rta, offset); - if (r < 0) - return r; -diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h -index 3beee9b..75651fa 100644 ---- a/src/network/networkd-route.h -+++ b/src/network/networkd-route.h -@@ -62,6 +62,8 @@ struct Route { - LIST_FIELDS(Route, routes); - }; - -+void route_hash_func(const Route *route, struct siphash *state); -+int route_compare_func(const Route *a, const Route *b); - extern const struct hash_ops route_hash_ops; - - int route_new(Route **ret); -diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c -index 36dad52..3b95ea7 100644 ---- a/src/network/networkd-routing-policy-rule.c -+++ b/src/network/networkd-routing-policy-rule.c -@@ -333,37 +333,48 @@ static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_messa - return 1; - } - --int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *link, link_netlink_message_handler_t callback) { -+int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; - int r; - -- assert(routing_policy_rule); -+ assert(rule); - assert(link); - assert(link->manager); - assert(link->manager->rtnl); - assert(link->ifindex > 0); -- assert(IN_SET(routing_policy_rule->family, AF_INET, AF_INET6)); -+ assert(IN_SET(rule->family, AF_INET, AF_INET6)); -+ -+ if (DEBUG_LOGGING) { -+ _cleanup_free_ char *from = NULL, *to = NULL; -+ -+ (void) in_addr_to_string(rule->family, &rule->from, &from); -+ (void) in_addr_to_string(rule->family, &rule->to, &to); - -- r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_DELRULE, routing_policy_rule->family); -+ log_link_debug(link, -+ "Removing routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, -+ rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table); -+ } -+ -+ r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_DELRULE, rule->family); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate RTM_DELRULE message: %m"); - -- if (in_addr_is_null(routing_policy_rule->family, &routing_policy_rule->from) == 0) { -- r = netlink_message_append_in_addr_union(m, FRA_SRC, routing_policy_rule->family, &routing_policy_rule->from); -+ if (in_addr_is_null(rule->family, &rule->from) == 0) { -+ r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from); - if (r < 0) - return log_link_error_errno(link, r, "Could not append FRA_SRC attribute: %m"); - -- r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, routing_policy_rule->from_prefixlen); -+ r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, rule->from_prefixlen); - if (r < 0) - return log_link_error_errno(link, r, "Could not set source prefix length: %m"); - } - -- if (in_addr_is_null(routing_policy_rule->family, &routing_policy_rule->to) == 0) { -- r = netlink_message_append_in_addr_union(m, FRA_DST, routing_policy_rule->family, &routing_policy_rule->to); -+ if (in_addr_is_null(rule->family, &rule->to) == 0) { -+ r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to); - if (r < 0) - return log_link_error_errno(link, r, "Could not append FRA_DST attribute: %m"); - -- r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, routing_policy_rule->to_prefixlen); -+ r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, rule->to_prefixlen); - if (r < 0) - return log_link_error_errno(link, r, "Could not set destination prefix length: %m"); - } -@@ -473,8 +484,8 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl - (void) in_addr_to_string(rule->family, &rule->to, &to); - - log_link_debug(link, -- "Configuring routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u", -- from, rule->from_prefixlen, to, rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table); -+ "Configuring routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32, -+ rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table); - } - - r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family); -@@ -529,18 +540,16 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl - r = sd_netlink_message_append_u32(m, FRA_FWMARK, rule->fwmark); - if (r < 0) - return log_link_error_errno(link, r, "Could not append FRA_FWMARK attribute: %m"); -- } - -- if (rule->fwmask > 0) { - r = sd_netlink_message_append_u32(m, FRA_FWMASK, rule->fwmask); - if (r < 0) - return log_link_error_errno(link, r, "Could not append FRA_FWMASK attribute: %m"); - } - - if (rule->iif) { -- r = sd_netlink_message_append_string(m, FRA_IFNAME, rule->iif); -+ r = sd_netlink_message_append_string(m, FRA_IIFNAME, rule->iif); - if (r < 0) -- return log_link_error_errno(link, r, "Could not append FRA_IFNAME attribute: %m"); -+ return log_link_error_errno(link, r, "Could not append FRA_IIFNAME attribute: %m"); - } - - if (rule->oif) { -@@ -644,31 +653,39 @@ int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { - return 0; - } - --static int parse_fwmark_fwmask(const char *s, uint32_t *fwmark, uint32_t *fwmask) { -- _cleanup_free_ char *f = NULL; -- char *p; -+static int parse_fwmark_fwmask(const char *s, uint32_t *ret_fwmark, uint32_t *ret_fwmask) { -+ _cleanup_free_ char *fwmark_str = NULL; -+ uint32_t fwmark, fwmask = 0; -+ const char *slash; - int r; - - assert(s); -+ assert(ret_fwmark); -+ assert(ret_fwmask); - -- f = strdup(s); -- if (!f) -- return -ENOMEM; -- -- p = strchr(f, '/'); -- if (p) -- *p++ = '\0'; -+ slash = strchr(s, '/'); -+ if (slash) { -+ fwmark_str = strndup(s, slash - s); -+ if (!fwmark_str) -+ return -ENOMEM; -+ } - -- r = safe_atou32(f, fwmark); -+ r = safe_atou32(fwmark_str ?: s, &fwmark); - if (r < 0) -- return log_error_errno(r, "Failed to parse RPDB rule firewall mark, ignoring: %s", f); -+ return r; - -- if (p) { -- r = safe_atou32(p, fwmask); -- if (r < 0) -- return log_error_errno(r, "Failed to parse RPDB rule mask, ignoring: %s", f); -+ if (fwmark > 0) { -+ if (slash) { -+ r = safe_atou32(slash + 1, &fwmask); -+ if (r < 0) -+ return r; -+ } else -+ fwmask = UINT32_MAX; - } - -+ *ret_fwmark = fwmark; -+ *ret_fwmask = fwmask; -+ - return 0; - } - -@@ -1166,46 +1183,33 @@ int config_parse_routing_policy_rule_suppress_prefixlen( - return 0; - } - --static int routing_policy_rule_read_full_file(const char *state_file, char **ret) { -- _cleanup_free_ char *s = NULL; -- size_t size; -- int r; -- -- assert(state_file); -- -- r = read_full_file(state_file, &s, &size); -- if (r == -ENOENT) -- return -ENODATA; -- if (r < 0) -- return r; -- if (size <= 0) -- return -ENODATA; -- -- *ret = TAKE_PTR(s); -- -- return size; --} -- - int routing_policy_serialize_rules(Set *rules, FILE *f) { - RoutingPolicyRule *rule = NULL; -- Iterator i; - int r; - - assert(f); - -- SET_FOREACH(rule, rules, i) { -+ SET_FOREACH(rule, rules) { - _cleanup_free_ char *from_str = NULL, *to_str = NULL; -- bool space = false; - const char *family_str; -+ bool space = false; - - fputs("RULE=", f); - -+ family_str = af_to_name(rule->family); -+ if (family_str) { -+ fprintf(f, "family=%s", -+ family_str); -+ space = true; -+ } -+ - if (!in_addr_is_null(rule->family, &rule->from)) { - r = in_addr_to_string(rule->family, &rule->from, &from_str); - if (r < 0) - return r; - -- fprintf(f, "from=%s/%hhu", -+ fprintf(f, "%sfrom=%s/%hhu", -+ space ? " " : "", - from_str, rule->from_prefixlen); - space = true; - } -@@ -1221,12 +1225,6 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) { - space = true; - } - -- family_str = af_to_name(rule->family); -- if (family_str) -- fprintf(f, "%sfamily=%s", -- space ? " " : "", -- family_str); -- - if (rule->tos != 0) { - fprintf(f, "%stos=%hhu", - space ? " " : "", -@@ -1234,14 +1232,19 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) { - space = true; - } - -- fprintf(f, "%spriority=%"PRIu32, -- space ? " " : "", -- rule->priority); -+ if (rule->priority != 0) { -+ fprintf(f, "%spriority=%"PRIu32, -+ space ? " " : "", -+ rule->priority); -+ space = true; -+ } - - if (rule->fwmark != 0) { -- fprintf(f, "%sfwmark=%"PRIu32"/%"PRIu32, -+ fprintf(f, "%sfwmark=%"PRIu32, - space ? " " : "", -- rule->fwmark, rule->fwmask); -+ rule->fwmark); -+ if (rule->fwmask != UINT32_MAX) -+ fprintf(f, "/%"PRIu32, rule->fwmask); - space = true; - } - -@@ -1295,14 +1298,35 @@ int routing_policy_serialize_rules(Set *rules, FILE *f) { - space = true; - } - -- fprintf(f, "%stable=%"PRIu32 "\n", -+ fprintf(f, "%sinvert_rule=%s table=%"PRIu32"\n", - space ? " " : "", -+ yes_no(rule->invert_rule), - rule->table); - } - - return 0; - } - -+static int routing_policy_rule_read_full_file(const char *state_file, char **ret) { -+ _cleanup_free_ char *s = NULL; -+ size_t size; -+ int r; -+ -+ assert(state_file); -+ -+ r = read_full_file(state_file, &s, &size); -+ if (r == -ENOENT) -+ return -ENODATA; -+ if (r < 0) -+ return r; -+ if (size <= 0) -+ return -ENODATA; -+ -+ *ret = TAKE_PTR(s); -+ -+ return size; -+} -+ - int routing_policy_load_rules(const char *state_file, Set **rules) { - _cleanup_strv_free_ char **l = NULL; - _cleanup_free_ char *data = NULL; -@@ -1334,19 +1358,34 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { - return r; - - for (;;) { -- _cleanup_free_ char *word = NULL, *a = NULL, *b = NULL; -+ _cleanup_free_ char *a = NULL; -+ char *b; - -- r = extract_first_word(&p, &word, NULL, 0); -+ r = extract_first_word(&p, &a, NULL, 0); - if (r < 0) - return r; - if (r == 0) - break; - -- r = split_pair(word, "=", &a, &b); -- if (r < 0) -+ b = strchr(a, '='); -+ if (!b) { -+ log_warning_errno(r, "Failed to parse RPDB rule, ignoring: %s", a); - continue; -+ } -+ *b++ = '\0'; - -- if (STR_IN_SET(a, "from", "to")) { -+ if (streq(a, "family")) { -+ r = af_from_name(b); -+ if (r < 0) { -+ log_warning_errno(r, "Failed to parse RPDB rule family, ignoring: %s", b); -+ continue; -+ } -+ if (rule->family != AF_UNSPEC && rule->family != r) { -+ log_warning("RPDB rule family is already specified, ignoring assignment: %s", b); -+ continue; -+ } -+ rule->family = r; -+ } if (STR_IN_SET(a, "from", "to")) { - union in_addr_union *buffer; - uint8_t *prefixlen; - -@@ -1358,41 +1397,36 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { - prefixlen = &rule->from_prefixlen; - } - -- r = in_addr_prefix_from_string_auto(b, &rule->family, buffer, prefixlen); -- if (r < 0) { -- log_error_errno(r, "RPDB rule prefix is invalid, ignoring assignment: %s", b); -- continue; -- } -- -- } else if (streq(a, "family")) { -- r = af_from_name(b); -+ if (rule->family == AF_UNSPEC) -+ r = in_addr_prefix_from_string_auto(b, &rule->family, buffer, prefixlen); -+ else -+ r = in_addr_prefix_from_string(b, rule->family, buffer, prefixlen); - if (r < 0) { -- log_error_errno(r, "Failed to parse RPDB rule family, ignoring: %s", b); -+ log_warning_errno(r, "RPDB rule prefix is invalid, ignoring assignment: %s", b); - continue; - } -- rule->family = r; - } else if (streq(a, "tos")) { - r = safe_atou8(b, &rule->tos); - if (r < 0) { -- log_error_errno(r, "Failed to parse RPDB rule TOS, ignoring: %s", b); -+ log_warning_errno(r, "Failed to parse RPDB rule TOS, ignoring: %s", b); - continue; - } - } else if (streq(a, "table")) { - r = safe_atou32(b, &rule->table); - if (r < 0) { -- log_error_errno(r, "Failed to parse RPDB rule table, ignoring: %s", b); -+ log_warning_errno(r, "Failed to parse RPDB rule table, ignoring: %s", b); - continue; - } - } else if (streq(a, "priority")) { - r = safe_atou32(b, &rule->priority); - if (r < 0) { -- log_error_errno(r, "Failed to parse RPDB rule priority, ignoring: %s", b); -+ log_warning_errno(r, "Failed to parse RPDB rule priority, ignoring: %s", b); - continue; - } - } else if (streq(a, "fwmark")) { - r = parse_fwmark_fwmask(b, &rule->fwmark, &rule->fwmask); - if (r < 0) { -- log_error_errno(r, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a); -+ log_warning_errno(r, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a); - continue; - } - } else if (streq(a, "iif")) { -@@ -1406,13 +1440,13 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { - } else if (streq(a, "protocol")) { - r = safe_atou8(b, &rule->protocol); - if (r < 0) { -- log_error_errno(r, "Failed to parse RPDB rule protocol, ignoring: %s", b); -+ log_warning_errno(r, "Failed to parse RPDB rule protocol, ignoring: %s", b); - continue; - } - } else if (streq(a, "sourceport")) { - r = parse_ip_port_range(b, &low, &high); - if (r < 0) { -- log_error_errno(r, "Invalid routing policy rule source port range, ignoring assignment: '%s'", b); -+ log_warning_errno(r, "Invalid routing policy rule source port range, ignoring assignment: '%s'", b); - continue; - } - -@@ -1421,7 +1455,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { - } else if (streq(a, "destinationport")) { - r = parse_ip_port_range(b, &low, &high); - if (r < 0) { -- log_error_errno(r, "Invalid routing policy rule destination port range, ignoring assignment: '%s'", b); -+ log_warning_errno(r, "Invalid routing policy rule destination port range, ignoring assignment: '%s'", b); - continue; - } - -@@ -1432,7 +1466,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { - - r = parse_uid_range(b, &lower, &upper); - if (r < 0) { -- log_error_errno(r, "Invalid routing policy rule uid range, ignoring assignment: '%s'", b); -+ log_warning_errno(r, "Invalid routing policy rule uid range, ignoring assignment: '%s'", b); - continue; - } - -@@ -1441,14 +1475,22 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { - } else if (streq(a, "suppress_prefixlen")) { - r = parse_ip_prefix_length(b, &rule->suppress_prefixlen); - if (r == -ERANGE) { -- log_error_errno(r, "Prefix length outside of valid range 0-128, ignoring: %s", b); -+ log_warning_errno(r, "Prefix length outside of valid range 0-128, ignoring: %s", b); - continue; - } - if (r < 0) { -- log_error_errno(r, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", b); -+ log_warning_errno(r, "Failed to parse RPDB rule suppress_prefixlen, ignoring: %s", b); - continue; - } -- } -+ } else if (streq(a, "invert_rule")) { -+ r = parse_boolean(b); -+ if (r < 0) { -+ log_warning_errno(r, "Failed to parse RPDB rule invert_rule, ignoring: %s", b); -+ continue; -+ } -+ rule->invert_rule = r; -+ } else -+ log_warning("Unknown RPDB rule, ignoring: %s", a); - } - - r = set_ensure_put(rules, &routing_policy_rule_hash_ops, rule); -@@ -1465,13 +1507,12 @@ int routing_policy_load_rules(const char *state_file, Set **rules) { - - static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) { - RoutingPolicyRule *link_rule; -- Iterator i; - Link *link; - - assert(m); - assert(rule); - -- HASHMAP_FOREACH(link, m->links, i) { -+ HASHMAP_FOREACH(link, m->links) { - if (!link->network) - continue; - -@@ -1485,13 +1526,12 @@ static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule - - void routing_policy_rule_purge(Manager *m, Link *link) { - RoutingPolicyRule *rule, *existing; -- Iterator i; - int r; - - assert(m); - assert(link); - -- SET_FOREACH(rule, m->rules_saved, i) { -+ SET_FOREACH(rule, m->rules_saved) { - existing = set_get(m->rules_foreign, rule); - if (!existing) - continue; /* Saved rule does not exist anymore. */ -diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h -index 21ca0e8..af954e8 100644 ---- a/src/network/networkd-routing-policy-rule.h -+++ b/src/network/networkd-routing-policy-rule.h -@@ -62,8 +62,8 @@ void routing_policy_rule_free(RoutingPolicyRule *rule); - DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free); - int routing_policy_rule_section_verify(RoutingPolicyRule *rule); - --int routing_policy_rule_configure(RoutingPolicyRule *address, Link *link, link_netlink_message_handler_t callback); --int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *link, link_netlink_message_handler_t callback); -+int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback); -+int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback); - - int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret); - int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret); -diff --git a/src/network/networkd-speed-meter.c b/src/network/networkd-speed-meter.c -index c4fc56b..ecf0346 100644 ---- a/src/network/networkd-speed-meter.c -+++ b/src/network/networkd-speed-meter.c -@@ -46,7 +46,6 @@ static int speed_meter_handler(sd_event_source *s, uint64_t usec, void *userdata - Manager *manager = userdata; - sd_netlink_message *i; - usec_t usec_now; -- Iterator j; - Link *link; - int r; - -@@ -64,7 +63,7 @@ static int speed_meter_handler(sd_event_source *s, uint64_t usec, void *userdata - manager->speed_meter_usec_old = manager->speed_meter_usec_new; - manager->speed_meter_usec_new = usec_now; - -- HASHMAP_FOREACH(link, manager->links, j) -+ HASHMAP_FOREACH(link, manager->links) - link->stats_updated = false; - - r = sd_rtnl_message_new_link(manager->rtnl, &req, RTM_GETLINK, 0); -diff --git a/src/network/test-routing-policy-rule.c b/src/network/test-routing-policy-rule.c -index d84d746..7875592 100644 ---- a/src/network/test-routing-policy-rule.c -+++ b/src/network/test-routing-policy-rule.c -@@ -62,31 +62,34 @@ int main(int argc, char **argv) { - test_setup_logging(LOG_DEBUG); - - test_rule_serialization("basic parsing", -- "RULE=from=1.2.3.4/32 to=2.3.4.5/32 family=AF_INET tos=5 priority=0 fwmark=1/2 table=10", NULL); -+ "RULE=family=AF_INET from=1.2.3.4/32 to=2.3.4.5/32 tos=5 priority=10 fwmark=1/2 invert_rule=yes table=10", NULL); - - test_rule_serialization("ignored values", - "RULE=something=to=ignore from=1.2.3.4/32 from=1.2.3.4/32" - " \t to=2.3.4.5/24 to=2.3.4.5/32 tos=5 fwmark=2 fwmark=1 table=10 table=20", -- "RULE=from=1.2.3.4/32" -- " to=2.3.4.5/32 family=AF_INET tos=5 priority=0 fwmark=1/0 table=20"); -+ "RULE=family=AF_INET from=1.2.3.4/32 to=2.3.4.5/32 tos=5 fwmark=1 invert_rule=no table=20"); - - test_rule_serialization("ipv6", -- "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 table=6", NULL); -+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 invert_rule=yes table=6", NULL); - -- assert_se(asprintf(&p, "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 table=%d", RT_TABLE_MAIN) >= 0); -+ assert_se(asprintf(&p, "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 invert_rule=no table=%d", RT_TABLE_MAIN) >= 0); - test_rule_serialization("default table", - "RULE=from=1::2/64 to=2::3/64", p); - - test_rule_serialization("incoming interface", - "RULE=from=1::2/64 to=2::3/64 table=1 iif=lo", -- "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 iif=lo table=1"); -+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 iif=lo invert_rule=no table=1"); - - test_rule_serialization("outgoing interface", -- "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 oif=eth0 table=1", NULL); -+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 oif=eth0 invert_rule=no table=1", NULL); - - test_rule_serialization("freeing interface names", - "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 iif=e0 iif=e1 oif=e0 oif=e1 table=1", -- "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 iif=e1 oif=e1 table=1"); -+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 iif=e1 oif=e1 invert_rule=no table=1"); -+ -+ test_rule_serialization("ignoring invalid family", -+ "RULE=from=1::2/64 to=2::3/64 family=AF_UNSEPC family=AF_INET table=1", -+ "RULE=family=AF_INET6 from=1::2/64 to=2::3/64 invert_rule=no table=1"); - - return 0; - } -diff --git a/src/network/wait-online/manager.c b/src/network/wait-online/manager.c -index 6ab26d3..e84eed4 100644 ---- a/src/network/wait-online/manager.c -+++ b/src/network/wait-online/manager.c -@@ -66,7 +66,6 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange - - bool manager_configured(Manager *m) { - bool one_ready = false; -- Iterator i; - const char *ifname; - void *p; - Link *l; -@@ -74,7 +73,7 @@ bool manager_configured(Manager *m) { - - if (!hashmap_isempty(m->interfaces)) { - /* wait for all the links given on the command line to appear */ -- HASHMAP_FOREACH_KEY(p, ifname, m->interfaces, i) { -+ HASHMAP_FOREACH_KEY(p, ifname, m->interfaces) { - LinkOperationalStateRange *range = p; - - l = hashmap_get(m->links_by_name, ifname); -@@ -106,7 +105,7 @@ bool manager_configured(Manager *m) { - - /* wait for all links networkd manages to be in admin state 'configured' - * and at least one link to gain a carrier */ -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - if (manager_ignore_link(m, l)) { - log_link_debug(l, "link is ignored"); - continue; -@@ -255,7 +254,6 @@ static int manager_rtnl_listen(Manager *m) { - - static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - Manager *m = userdata; -- Iterator i; - Link *l; - int r; - -@@ -263,7 +261,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void * - - sd_network_monitor_flush(m->network_monitor); - -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - r = link_update_monitor(l); - if (r < 0 && r != -ENODATA) - log_link_warning_errno(l, r, "Failed to update link state, ignoring: %m"); -diff --git a/src/nspawn/meson.build b/src/nspawn/meson.build -index c049ac6..ae3d72f 100644 ---- a/src/nspawn/meson.build -+++ b/src/nspawn/meson.build -@@ -3,6 +3,8 @@ - libnspawn_core_sources = files(''' - nspawn-cgroup.c - nspawn-cgroup.h -+ nspawn-creds.c -+ nspawn-creds.h - nspawn-def.h - nspawn-expose-ports.c - nspawn-expose-ports.h -diff --git a/src/nspawn/nspawn-creds.c b/src/nspawn/nspawn-creds.c -new file mode 100644 -index 0000000..41a38d3 ---- /dev/null -+++ b/src/nspawn/nspawn-creds.c -@@ -0,0 +1,25 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include "alloc-util.h" -+#include "macro.h" -+#include "memory-util.h" -+#include "nspawn-creds.h" -+ -+static void credential_free(Credential *cred) { -+ assert(cred); -+ -+ cred->id = mfree(cred->id); -+ cred->data = erase_and_free(cred->data); -+ cred->size = 0; -+} -+ -+void credential_free_all(Credential *creds, size_t n) { -+ size_t i; -+ -+ assert(creds || n == 0); -+ -+ for (i = 0; i < n; i++) -+ credential_free(creds + i); -+ -+ free(creds); -+} -diff --git a/src/nspawn/nspawn-creds.h b/src/nspawn/nspawn-creds.h -new file mode 100644 -index 0000000..b3c90bb ---- /dev/null -+++ b/src/nspawn/nspawn-creds.h -@@ -0,0 +1,12 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#include -+ -+typedef struct Credential { -+ char *id; -+ void *data; -+ size_t size; -+} Credential; -+ -+void credential_free_all(Credential *creds, size_t n); -diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c -index 5599c6a..c49ed76 100644 ---- a/src/nspawn/nspawn-mount.c -+++ b/src/nspawn/nspawn-mount.c -@@ -301,7 +301,7 @@ int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_onl - CustomMount *m; - int k; - -- k = strv_split_extract(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ k = strv_split_full(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS); - if (k < 0) - return k; - if (k < 2) -diff --git a/src/nspawn/nspawn-oci.c b/src/nspawn/nspawn-oci.c -index e3ade92..60a5909 100644 ---- a/src/nspawn/nspawn-oci.c -+++ b/src/nspawn/nspawn-oci.c -@@ -1695,6 +1695,9 @@ static int oci_seccomp_arch_from_string(const char *name, uint32_t *ret) { - { "SCMP_ARCH_PPC", SCMP_ARCH_PPC }, - { "SCMP_ARCH_PPC64", SCMP_ARCH_PPC64 }, - { "SCMP_ARCH_PPC64LE", SCMP_ARCH_PPC64LE }, -+#ifdef SCMP_ARCH_RISCV64 -+ { "SCMP_ARCH_RISCV64", SCMP_ARCH_RISCV64 }, -+#endif - { "SCMP_ARCH_S390", SCMP_ARCH_S390 }, - { "SCMP_ARCH_S390X", SCMP_ARCH_S390X }, - { "SCMP_ARCH_X32", SCMP_ARCH_X32 }, -diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c -index 79110d9..1ab5055 100644 ---- a/src/nspawn/nspawn-seccomp.c -+++ b/src/nspawn/nspawn-seccomp.c -@@ -21,7 +21,7 @@ - - #if HAVE_SECCOMP - --static int seccomp_add_default_syscall_filter( -+static int add_syscall_filters( - scmp_filter_ctx ctx, - uint32_t arch, - uint64_t cap_list_retain, -@@ -139,6 +139,7 @@ static int seccomp_add_default_syscall_filter( - */ - }; - -+ _cleanup_strv_free_ char **added = NULL; - char **p; - int r; - -@@ -146,18 +147,37 @@ static int seccomp_add_default_syscall_filter( - if (allow_list[i].capability != 0 && (cap_list_retain & (1ULL << allow_list[i].capability)) == 0) - continue; - -- r = seccomp_add_syscall_filter_item(ctx, allow_list[i].name, SCMP_ACT_ALLOW, syscall_deny_list, false); -+ r = seccomp_add_syscall_filter_item(ctx, -+ allow_list[i].name, -+ SCMP_ACT_ALLOW, -+ syscall_deny_list, -+ false, -+ &added); - if (r < 0) - return log_error_errno(r, "Failed to add syscall filter item %s: %m", allow_list[i].name); - } - - STRV_FOREACH(p, syscall_allow_list) { -- r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_deny_list, true); -+ r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_deny_list, true, &added); - if (r < 0) - log_warning_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", - *p, seccomp_arch_to_string(arch)); - } - -+ /* The default action is ENOSYS. Respond with EPERM to all other "known" but not allow-listed -+ * syscalls. */ -+ r = seccomp_add_syscall_filter_item(ctx, "@known", SCMP_ACT_ERRNO(EPERM), added, true, NULL); -+ if (r < 0) -+ log_warning_errno(r, "Failed to add rule for @known set on %s, ignoring: %m", -+ seccomp_arch_to_string(arch)); -+ -+#if (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 5) || SCMP_VER_MAJOR > 2 -+ /* We have a large filter here, so let's turn on the binary tree mode if possible. */ -+ r = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_OPTIMIZE, 2); -+ if (r < 0) -+ return r; -+#endif -+ - return 0; - } - -@@ -175,11 +195,13 @@ int setup_seccomp(uint64_t cap_list_retain, char **syscall_allow_list, char **sy - - log_debug("Applying allow list on architecture: %s", seccomp_arch_to_string(arch)); - -- r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ERRNO(EPERM)); -+ /* We install ENOSYS as the default action, but it will only apply to syscalls which are not -+ * in the @known set, see above. */ -+ r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ERRNO(ENOSYS)); - if (r < 0) - return log_error_errno(r, "Failed to allocate seccomp object: %m"); - -- r = seccomp_add_default_syscall_filter(seccomp, arch, cap_list_retain, syscall_allow_list, syscall_deny_list); -+ r = add_syscall_filters(seccomp, arch, cap_list_retain, syscall_allow_list, syscall_deny_list); - if (r < 0) - return r; - -diff --git a/src/nspawn/nspawn-seccomp.h b/src/nspawn/nspawn-seccomp.h -index 4174323..6a48e64 100644 ---- a/src/nspawn/nspawn-seccomp.h -+++ b/src/nspawn/nspawn-seccomp.h -@@ -3,4 +3,4 @@ - - #include - --int setup_seccomp(uint64_t cap_list_retain, char **syscall_allow_ist, char **syscall_deny_list); -+int setup_seccomp(uint64_t cap_list_retain, char **syscall_allow_list, char **syscall_deny_list); -diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c -index d341fa2..bd8062d 100644 ---- a/src/nspawn/nspawn-settings.c -+++ b/src/nspawn/nspawn-settings.c -@@ -233,14 +233,10 @@ int config_parse_expose_port( - assert(rvalue); - - r = expose_port_parse(&s->expose_ports, rvalue); -- if (r == -EEXIST) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Duplicate port specification, ignoring: %s", rvalue); -- return 0; -- } -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse host port %s: %m", rvalue); -- return 0; -- } -+ if (r == -EEXIST) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Duplicate port specification, ignoring: %s", rvalue); -+ else if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse host port %s: %m", rvalue); - - return 0; - } -@@ -268,8 +264,10 @@ int config_parse_capability( - _cleanup_free_ char *word = NULL; - - r = extract_first_word(&rvalue, &word, NULL, 0); -+ if (r == -ENOMEM) -+ return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract capability string, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract capability string, ignoring: %s", rvalue); - return 0; - } - if (r == 0) -@@ -280,7 +278,7 @@ int config_parse_capability( - else { - r = capability_from_name(word); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse capability, ignoring: %s", word); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse capability, ignoring: %s", word); - continue; - } - -@@ -315,10 +313,8 @@ int config_parse_pivot_root( - assert(rvalue); - - r = pivot_root_parse(&settings->pivot_root_new, &settings->pivot_root_old, rvalue); -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid pivot root mount specification %s: %m", rvalue); -- return 0; -- } -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid pivot root mount specification %s: %m", rvalue); - - return 0; - } -@@ -343,10 +339,8 @@ int config_parse_bind( - assert(rvalue); - - r = bind_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue, ltype); -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid bind mount specification %s: %m", rvalue); -- return 0; -- } -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid bind mount specification %s: %m", rvalue); - - return 0; - } -@@ -371,10 +365,8 @@ int config_parse_tmpfs( - assert(rvalue); - - r = tmpfs_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue); -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid temporary file system specification %s: %m", rvalue); -- return 0; -- } -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid temporary file system specification %s: %m", rvalue); - - return 0; - } -@@ -399,10 +391,8 @@ int config_parse_inaccessible( - assert(rvalue); - - r = inaccessible_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue); -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid inaccessible file system specification %s: %m", rvalue); -- return 0; -- } -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid inaccessible file system specification %s: %m", rvalue); - - return 0; - } -@@ -428,7 +418,7 @@ int config_parse_overlay( - - r = overlay_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue, ltype); - if (r < 0) -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid overlay file system specification %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid overlay file system specification %s, ignoring: %m", rvalue); - - return 0; - } -@@ -453,10 +443,8 @@ int config_parse_veth_extra( - assert(rvalue); - - r = veth_extra_parse(&settings->network_veth_extra, rvalue); -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid extra virtual Ethernet link specification %s: %m", rvalue); -- return 0; -- } -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid extra virtual Ethernet link specification %s: %m", rvalue); - - return 0; - } -@@ -482,13 +470,11 @@ int config_parse_network_zone( - - j = strjoin("vz-", rvalue); - if (!ifname_valid(j)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid network zone name, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid network zone name, ignoring: %s", rvalue); - return 0; - } - -- free_and_replace(settings->network_zone, j); -- -- return 0; -+ return free_and_replace(settings->network_zone, j); - } - - int config_parse_boot( -@@ -512,11 +498,11 @@ int config_parse_boot( - - r = parse_boolean(rvalue); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Boot= parameter %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse Boot= parameter %s, ignoring: %m", rvalue); - return 0; - } - -- if (r > 0) { -+ if (r) { - if (settings->start_mode == START_PID2) - goto conflict; - -@@ -532,7 +518,7 @@ int config_parse_boot( - return 0; - - conflict: -- log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); - return 0; - } - -@@ -557,11 +543,11 @@ int config_parse_pid2( - - r = parse_boolean(rvalue); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse ProcessTwo= parameter %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse ProcessTwo= parameter %s, ignoring: %m", rvalue); - return 0; - } - -- if (r > 0) { -+ if (r) { - if (settings->start_mode == START_BOOT) - goto conflict; - -@@ -577,7 +563,7 @@ int config_parse_pid2( - return 0; - - conflict: -- log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); - return 0; - } - -@@ -629,7 +615,7 @@ int config_parse_private_users( - - r = safe_atou32(range, &rn); - if (r < 0 || rn <= 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "UID/GID range invalid, ignoring: %s", range); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "UID/GID range invalid, ignoring: %s", range); - return 0; - } - } else { -@@ -639,7 +625,7 @@ int config_parse_private_users( - - r = parse_uid(shift, &sh); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "UID/GID shift invalid, ignoring: %s", range); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "UID/GID shift invalid, ignoring: %s", range); - return 0; - } - -@@ -680,11 +666,12 @@ int config_parse_syscall_filter( - - r = extract_first_word(&items, &word, NULL, 0); - if (r == 0) -- break; -+ return 0; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse SystemCallFilter= parameter %s, ignoring: %m", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse SystemCallFilter= parameter %s, ignoring: %m", rvalue); - return 0; - } - -@@ -695,8 +682,6 @@ int config_parse_syscall_filter( - if (r < 0) - return log_oom(); - } -- -- return 0; - } - - int config_parse_hostname( -@@ -717,7 +702,7 @@ int config_parse_hostname( - assert(s); - - if (!hostname_is_valid(rvalue, false)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid hostname, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid hostname, ignoring: %s", rvalue); - return 0; - } - -@@ -752,11 +737,11 @@ int config_parse_oom_score_adjust( - - r = parse_oom_score_adjust(rvalue, &oa); - if (r == -ERANGE) { -- log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue); - return 0; - } - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue); - return 0; - } - -@@ -809,6 +794,8 @@ static const char *const resolv_conf_mode_table[_RESOLV_CONF_MODE_MAX] = { - DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolv_conf_mode, ResolvConfMode, RESOLV_CONF_AUTO); - - int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try) { -+ int r; -+ - assert(s); - assert(ret_mode); - assert(ret_try); -@@ -816,9 +803,6 @@ int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try) { - if (streq(s, "auto")) { - *ret_mode = LINK_AUTO; - *ret_try = false; -- } else if (streq(s, "no")) { -- *ret_mode = LINK_NO; -- *ret_try = false; - } else if (streq(s, "guest")) { - *ret_mode = LINK_GUEST; - *ret_try = false; -@@ -831,8 +815,16 @@ int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try) { - } else if (streq(s, "try-host")) { - *ret_mode = LINK_HOST; - *ret_try = true; -- } else -- return -EINVAL; -+ } else { -+ /* Also support boolean values, to make things less confusing. */ -+ r = parse_boolean(s); -+ if (r < 0) -+ return r; -+ -+ /* Let's consider "true" to be equivalent to "auto". */ -+ *ret_mode = r ? LINK_AUTO : LINK_NO; -+ *ret_try = false; -+ } - - return 0; - } -@@ -856,10 +848,8 @@ int config_parse_link_journal( - assert(settings); - - r = parse_link_journal(rvalue, &settings->link_journal, &settings->link_journal_try); -- if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse link journal mode, ignoring: %s", rvalue); -- return 0; -- } -+ if (r < 0) -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse link journal mode, ignoring: %s", rvalue); - - return 0; - } -diff --git a/src/nspawn/nspawn-settings.h b/src/nspawn/nspawn-settings.h -index ab31c05..b8fa145 100644 ---- a/src/nspawn/nspawn-settings.h -+++ b/src/nspawn/nspawn-settings.h -@@ -116,9 +116,10 @@ typedef enum SettingsMask { - SETTING_USE_CGNS = UINT64_C(1) << 27, - SETTING_CLONE_NS_FLAGS = UINT64_C(1) << 28, - SETTING_CONSOLE_MODE = UINT64_C(1) << 29, -- SETTING_RLIMIT_FIRST = UINT64_C(1) << 30, /* we define one bit per resource limit here */ -- SETTING_RLIMIT_LAST = UINT64_C(1) << (30 + _RLIMIT_MAX - 1), -- _SETTINGS_MASK_ALL = (UINT64_C(1) << (30 + _RLIMIT_MAX)) -1, -+ SETTING_CREDENTIALS = UINT64_C(1) << 30, -+ SETTING_RLIMIT_FIRST = UINT64_C(1) << 31, /* we define one bit per resource limit here */ -+ SETTING_RLIMIT_LAST = UINT64_C(1) << (31 + _RLIMIT_MAX - 1), -+ _SETTINGS_MASK_ALL = (UINT64_C(1) << (31 + _RLIMIT_MAX)) -1, - _SETTING_FORCE_ENUM_WIDTH = UINT64_MAX - } SettingsMask; - -diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c -index d0e575f..fa2002d 100644 ---- a/src/nspawn/nspawn-setuid.c -+++ b/src/nspawn/nspawn-setuid.c -@@ -88,13 +88,12 @@ int change_uid_gid_raw( - - int change_uid_gid(const char *user, char **_home) { - char *x, *u, *g, *h; -- const char *word, *state; - _cleanup_free_ gid_t *gids = NULL; - _cleanup_free_ char *home = NULL, *line = NULL; - _cleanup_fclose_ FILE *f = NULL; - _cleanup_close_ int fd = -1; - unsigned n_gids = 0; -- size_t sz = 0, l; -+ size_t sz = 0; - uid_t uid; - gid_t gid; - pid_t pid; -@@ -208,16 +207,19 @@ int change_uid_gid(const char *user, char **_home) { - x += strcspn(x, WHITESPACE); - x += strspn(x, WHITESPACE); - -- FOREACH_WORD(word, l, x, state) { -- char c[l+1]; -+ for (const char *p = x;;) { -+ _cleanup_free_ char *word = NULL; - -- memcpy(c, word, l); -- c[l] = 0; -+ r = extract_first_word(&p, &word, NULL, 0); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse group data from getent: %m"); -+ if (r == 0) -+ break; - - if (!GREEDY_REALLOC(gids, sz, n_gids+1)) - return log_oom(); - -- r = parse_gid(c, &gids[n_gids++]); -+ r = parse_gid(word, &gids[n_gids++]); - if (r < 0) - return log_error_errno(r, "Failed to parse group data from getent: %m"); - } -diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c -index 3b9493f..2646975 100644 ---- a/src/nspawn/nspawn.c -+++ b/src/nspawn/nspawn.c -@@ -36,6 +36,7 @@ - #include "dev-setup.h" - #include "dissect-image.h" - #include "env-util.h" -+#include "escape.h" - #include "fd-util.h" - #include "fdset.h" - #include "fileio.h" -@@ -45,6 +46,7 @@ - #include "hexdecoct.h" - #include "hostname-util.h" - #include "id128-util.h" -+#include "io-util.h" - #include "log.h" - #include "loop-util.h" - #include "loopback-setup.h" -@@ -58,6 +60,7 @@ - #include "namespace-util.h" - #include "netlink-util.h" - #include "nspawn-cgroup.h" -+#include "nspawn-creds.h" - #include "nspawn-def.h" - #include "nspawn-expose-ports.h" - #include "nspawn-mount.h" -@@ -101,10 +104,8 @@ - #include "user-util.h" - #include "util.h" - --/* nspawn is listening on the socket at the path in the constant nspawn_notify_socket_path -- * nspawn_notify_socket_path is relative to the container -- * the init process in the container pid can send messages to nspawn following the sd_notify(3) protocol */ --#define NSPAWN_NOTIFY_SOCKET_PATH "/run/systemd/nspawn/notify" -+/* The notify socket inside the container it can use to talk to nspawn using the sd_notify(3) protocol */ -+#define NSPAWN_NOTIFY_SOCKET_PATH "/run/host/notify" - - #define EXIT_FORCE_RESTART 133 - -@@ -221,6 +222,8 @@ static DeviceNode* arg_extra_nodes = NULL; - static size_t arg_n_extra_nodes = 0; - static char **arg_sysctl = NULL; - static ConsoleMode arg_console_mode = _CONSOLE_MODE_INVALID; -+static Credential *arg_credentials = NULL; -+static size_t arg_n_credentials = 0; - - STATIC_DESTRUCTOR_REGISTER(arg_directory, freep); - STATIC_DESTRUCTOR_REGISTER(arg_template, freep); -@@ -408,7 +411,13 @@ static int help(void) { - "%3$sInput/Output:%4$s\n" - " --console=MODE Select how stdin/stdout/stderr and /dev/console are\n" - " set up for the container.\n" -- " -P --pipe Equivalent to --console=pipe\n" -+ " -P --pipe Equivalent to --console=pipe\n\n" -+ "%3$sCredentials:%4$s\n" -+ " --set-credential=ID:VALUE\n" -+ " Pass a credential with literal value to container.\n" -+ " --load-credential=ID:PATH\n" -+ " Load credential to pass to container from file or\n" -+ " AF_UNIX stream socket.\n" - "\nSee the %2$s for details.\n" - , program_invocation_short_name - , link -@@ -677,6 +686,8 @@ static int parse_argv(int argc, char *argv[]) { - ARG_NO_PAGER, - ARG_VERITY_DATA, - ARG_ROOT_HASH_SIG, -+ ARG_SET_CREDENTIAL, -+ ARG_LOAD_CREDENTIAL, - }; - - static const struct option options[] = { -@@ -744,6 +755,8 @@ static int parse_argv(int argc, char *argv[]) { - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "verity-data", required_argument, NULL, ARG_VERITY_DATA }, - { "root-hash-sig", required_argument, NULL, ARG_ROOT_HASH_SIG }, -+ { "set-credential", required_argument, NULL, ARG_SET_CREDENTIAL }, -+ { "load-credential", required_argument, NULL, ARG_LOAD_CREDENTIAL }, - {} - }; - -@@ -1498,6 +1511,105 @@ static int parse_argv(int argc, char *argv[]) { - arg_pager_flags |= PAGER_DISABLE; - break; - -+ case ARG_SET_CREDENTIAL: { -+ _cleanup_free_ char *word = NULL, *data = NULL; -+ const char *p = optarg; -+ Credential *a; -+ size_t i; -+ int l; -+ -+ r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse --set-credential= parameter: %m"); -+ if (r == 0 || !p) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for --set-credential=: %s", optarg); -+ -+ if (!credential_name_valid(word)) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", word); -+ -+ for (i = 0; i < arg_n_credentials; i++) -+ if (streq(arg_credentials[i].id, word)) -+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", word); -+ -+ l = cunescape(p, UNESCAPE_ACCEPT_NUL, &data); -+ if (l < 0) -+ return log_error_errno(l, "Failed to unescape credential data: %s", p); -+ -+ a = reallocarray(arg_credentials, arg_n_credentials + 1, sizeof(Credential)); -+ if (!a) -+ return log_oom(); -+ -+ a[arg_n_credentials++] = (Credential) { -+ .id = TAKE_PTR(word), -+ .data = TAKE_PTR(data), -+ .size = l, -+ }; -+ -+ arg_credentials = a; -+ -+ arg_settings_mask |= SETTING_CREDENTIALS; -+ break; -+ } -+ -+ case ARG_LOAD_CREDENTIAL: { -+ ReadFullFileFlags flags = READ_FULL_FILE_SECURE; -+ _cleanup_(erase_and_freep) char *data = NULL; -+ _cleanup_free_ char *word = NULL, *j = NULL; -+ const char *p = optarg; -+ Credential *a; -+ size_t size, i; -+ -+ r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse --set-credential= parameter: %m"); -+ if (r == 0 || !p) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing value for --set-credential=: %s", optarg); -+ -+ if (!credential_name_valid(word)) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential name is not valid: %s", word); -+ -+ for (i = 0; i < arg_n_credentials; i++) -+ if (streq(arg_credentials[i].id, word)) -+ return log_error_errno(SYNTHETIC_ERRNO(EEXIST), "Duplicate credential '%s', refusing.", word); -+ -+ if (path_is_absolute(p)) -+ flags |= READ_FULL_FILE_CONNECT_SOCKET; -+ else { -+ const char *e; -+ -+ e = getenv("CREDENTIALS_DIRECTORY"); -+ if (!e) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Credential not available (no credentials passed at all): %s", word); -+ -+ j = path_join(e, p); -+ if (!j) -+ return log_oom(); -+ } -+ -+ r = read_full_file_full(AT_FDCWD, j ?: p, flags, &data, &size); -+ if (r < 0) -+ return log_error_errno(r, "Failed to read credential '%s': %m", j ?: p); -+ -+ a = reallocarray(arg_credentials, arg_n_credentials + 1, sizeof(Credential)); -+ if (!a) -+ return log_oom(); -+ -+ a[arg_n_credentials++] = (Credential) { -+ .id = TAKE_PTR(word), -+ .data = TAKE_PTR(data), -+ .size = size, -+ }; -+ -+ arg_credentials = a; -+ -+ arg_settings_mask |= SETTING_CREDENTIALS; -+ break; -+ } -+ - case '?': - return -EINVAL; - -@@ -2230,6 +2342,66 @@ static int setup_keyring(void) { - return 0; - } - -+static int setup_credentials(const char *root) { -+ const char *q; -+ int r; -+ -+ if (arg_n_credentials <= 0) -+ return 0; -+ -+ r = userns_mkdir(root, "/run/host", 0755, 0, 0); -+ if (r < 0) -+ return log_error_errno(r, "Failed to create /run/host: %m"); -+ -+ r = userns_mkdir(root, "/run/host/credentials", 0700, 0, 0); -+ if (r < 0) -+ return log_error_errno(r, "Failed to create /run/host/credentials: %m"); -+ -+ q = prefix_roota(root, "/run/host/credentials"); -+ r = mount_verbose(LOG_ERR, NULL, q, "ramfs", MS_NOSUID|MS_NOEXEC|MS_NODEV, "mode=0700"); -+ if (r < 0) -+ return r; -+ -+ for (size_t i = 0; i < arg_n_credentials; i++) { -+ _cleanup_free_ char *j = NULL; -+ _cleanup_close_ int fd = -1; -+ -+ j = path_join(q, arg_credentials[i].id); -+ if (!j) -+ return log_oom(); -+ -+ fd = open(j, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC|O_NOFOLLOW, 0600); -+ if (fd < 0) -+ return log_error_errno(errno, "Failed to create credential file %s: %m", j); -+ -+ r = loop_write(fd, arg_credentials[i].data, arg_credentials[i].size, /* do_poll= */ false); -+ if (r < 0) -+ return log_error_errno(r, "Failed to write credential to file %s: %m", j); -+ -+ if (fchmod(fd, 0400) < 0) -+ return log_error_errno(errno, "Failed to adjust access mode of %s: %m", j); -+ -+ if (arg_userns_mode != USER_NAMESPACE_NO) { -+ if (fchown(fd, arg_uid_shift, arg_uid_shift) < 0) -+ return log_error_errno(errno, "Failed to adjust ownership of %s: %m", j); -+ } -+ } -+ -+ if (chmod(q, 0500) < 0) -+ return log_error_errno(errno, "Failed to adjust access mode of %s: %m", q); -+ -+ r = userns_lchown(q, 0, 0); -+ if (r < 0) -+ return r; -+ -+ /* Make both mount and superblock read-only now */ -+ r = mount_verbose(LOG_ERR, NULL, q, NULL, MS_REMOUNT|MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); -+ if (r < 0) -+ return r; -+ -+ return mount_verbose(LOG_ERR, NULL, q, NULL, MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, "mode=0500"); -+} -+ - static int setup_kmsg(int kmsg_socket) { - _cleanup_(unlink_and_freep) char *from = NULL; - _cleanup_free_ char *fifo = NULL; -@@ -2517,19 +2689,15 @@ static int setup_propagate(const char *root) { - p = strjoina("/run/systemd/nspawn/propagate/", arg_machine); - (void) mkdir_p(p, 0600); - -- r = userns_mkdir(root, "/run/systemd", 0755, 0, 0); -+ r = userns_mkdir(root, "/run/host", 0755, 0, 0); - if (r < 0) -- return log_error_errno(r, "Failed to create /run/systemd: %m"); -+ return log_error_errno(r, "Failed to create /run/host: %m"); - -- r = userns_mkdir(root, "/run/systemd/nspawn", 0755, 0, 0); -+ r = userns_mkdir(root, "/run/host/incoming", 0600, 0, 0); - if (r < 0) -- return log_error_errno(r, "Failed to create /run/systemd/nspawn: %m"); -+ return log_error_errno(r, "Failed to create /run/host/incoming: %m"); - -- r = userns_mkdir(root, "/run/systemd/nspawn/incoming", 0600, 0, 0); -- if (r < 0) -- return log_error_errno(r, "Failed to create /run/systemd/nspawn/incoming: %m"); -- -- q = prefix_roota(root, "/run/systemd/nspawn/incoming"); -+ q = prefix_roota(root, "/run/host/incoming"); - r = mount_verbose(LOG_ERR, p, q, NULL, MS_BIND, NULL); - if (r < 0) - return r; -@@ -2538,8 +2706,7 @@ static int setup_propagate(const char *root) { - if (r < 0) - return r; - -- /* machined will MS_MOVE into that directory, and that's only -- * supported for non-shared mounts. */ -+ /* machined will MS_MOVE into that directory, and that's only supported for non-shared mounts. */ - return mount_verbose(LOG_ERR, NULL, q, NULL, MS_SLAVE, NULL); - } - -@@ -2948,6 +3115,7 @@ static int inner_child( - NULL, /* LISTEN_FDS */ - NULL, /* LISTEN_PID */ - NULL, /* NOTIFY_SOCKET */ -+ NULL, /* CREDENTIALS_DIRECTORY */ - NULL - }; - const char *exec_target; -@@ -3198,6 +3366,13 @@ static int inner_child( - if (asprintf((char **)(envp + n_env++), "NOTIFY_SOCKET=%s", NSPAWN_NOTIFY_SOCKET_PATH) < 0) - return log_oom(); - -+ if (arg_n_credentials > 0) { -+ envp[n_env] = strdup("CREDENTIALS_DIRECTORY=/run/host/credentials"); -+ if (!envp[n_env]) -+ return log_oom(); -+ n_env++; -+ } -+ - env_use = strv_env_merge(3, envp, os_release_pairs, arg_setenv); - if (!env_use) - return log_oom(); -@@ -3259,7 +3434,7 @@ static int inner_child( - * binary. */ - dollar_path = strv_env_get(env_use, "PATH"); - if (dollar_path) { -- if (putenv((char*) dollar_path) != 0) -+ if (setenv("PATH", dollar_path, 1) < 0) - return log_error_errno(errno, "Failed to update $PATH: %m"); - } - -@@ -3278,7 +3453,7 @@ static int inner_child( - return log_error_errno(errno, "execv(%s) failed: %m", exec_target); - } - --static int setup_sd_notify_child(void) { -+static int setup_notify_child(void) { - _cleanup_close_ int fd = -1; - union sockaddr_union sa = { - .un.sun_family = AF_UNIX, -@@ -3369,14 +3544,13 @@ static int outer_child( - * uid shift known. That way we can mount VFAT file systems shifted to the right place right away. This - * makes sure ESP partitions and userns are compatible. */ - -- r = dissected_image_mount(dissected_image, directory, arg_uid_shift, -- DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP| -- (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK)| -- (arg_start_mode == START_BOOT ? DISSECT_IMAGE_VALIDATE_OS : 0)); -- if (r == -EUCLEAN) -- return log_error_errno(r, "File system check for image failed: %m"); -+ r = dissected_image_mount_and_warn( -+ dissected_image, directory, arg_uid_shift, -+ DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP| -+ (arg_read_only ? DISSECT_IMAGE_READ_ONLY : DISSECT_IMAGE_FSCK)| -+ (arg_start_mode == START_BOOT ? DISSECT_IMAGE_VALIDATE_OS : 0)); - if (r < 0) -- return log_error_errno(r, "Failed to mount image root file system: %m"); -+ return r; - } - - r = determine_uid_shift(directory); -@@ -3531,7 +3705,7 @@ static int outer_child( - - (void) dev_setup(directory, arg_uid_shift, arg_uid_shift); - -- p = prefix_roota(directory, "/run"); -+ p = prefix_roota(directory, "/run/host"); - (void) make_inaccessible_nodes(p, arg_uid_shift, arg_uid_shift); - - r = setup_pts(directory); -@@ -3546,6 +3720,10 @@ static int outer_child( - if (r < 0) - return r; - -+ r = setup_credentials(directory); -+ if (r < 0) -+ return r; -+ - r = mount_custom( - directory, - arg_custom_mounts, -@@ -3572,6 +3750,14 @@ static int outer_child( - if (r < 0) - return r; - -+ /* The same stuff as the $container env var, but nicely readable for the entire payload */ -+ p = prefix_roota(directory, "/run/host/container-manager"); -+ (void) write_string_file(p, arg_container_service_name, WRITE_STRING_FILE_CREATE); -+ -+ /* The same stuff as the $container_uuid env var */ -+ p = prefix_roota(directory, "/run/host/container-uuid"); -+ (void) write_string_filef(p, WRITE_STRING_FILE_CREATE, SD_ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(arg_uuid)); -+ - if (!arg_use_cgns) { - r = mount_cgroups( - directory, -@@ -3589,7 +3775,7 @@ static int outer_child( - if (r < 0) - return log_error_errno(r, "Failed to move root directory: %m"); - -- fd = setup_sd_notify_child(); -+ fd = setup_notify_child(); - if (fd < 0) - return fd; - -@@ -3802,7 +3988,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r - return 0; - } - --static int setup_sd_notify_parent(sd_event *event, int fd, pid_t *inner_child_pid, sd_event_source **notify_event_source) { -+static int setup_notify_parent(sd_event *event, int fd, pid_t *inner_child_pid, sd_event_source **notify_event_source) { - int r; - - r = sd_event_add_io(event, notify_event_source, fd, EPOLLIN, nspawn_dispatch_notify_fd, inner_child_pid); -@@ -4633,7 +4819,7 @@ static int run_container( - return log_error_errno(r, "Failed to attach bus to event loop: %m"); - } - -- r = setup_sd_notify_parent(event, notify_socket, PID_TO_PTR(*pid), ¬ify_event_source); -+ r = setup_notify_parent(event, notify_socket, PID_TO_PTR(*pid), ¬ify_event_source); - if (r < 0) - return r; - -@@ -5223,6 +5409,7 @@ static int run(int argc, char *argv[]) { - arg_image, - arg_root_hash, arg_root_hash_size, - arg_verity_data, -+ NULL, - dissect_image_flags, - &dissected_image); - if (r == -ENOPKG) { -@@ -5338,6 +5525,7 @@ finish: - expose_port_free_all(arg_expose_ports); - rlimit_free_all(arg_rlimit); - device_node_array_free(arg_extra_nodes, arg_n_extra_nodes); -+ credential_free_all(arg_credentials, arg_n_credentials); - - if (r < 0) - return r; -diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c -index 43ab521..a8e6ce9 100644 ---- a/src/nss-resolve/nss-resolve.c -+++ b/src/nss-resolve/nss-resolve.c -@@ -7,10 +7,6 @@ - #include - #include - --#include "sd-bus.h" -- --#include "bus-common-errors.h" --#include "bus-locator.h" - #include "errno-util.h" - #include "in-addr-util.h" - #include "macro.h" -@@ -18,67 +14,36 @@ - #include "resolved-def.h" - #include "signal-util.h" - #include "string-util.h" -+#include "strv.h" -+#include "varlink.h" - - NSS_GETHOSTBYNAME_PROTOTYPES(resolve); - NSS_GETHOSTBYADDR_PROTOTYPES(resolve); - --static bool bus_error_shall_fallback(sd_bus_error *e) { -- return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) || -- sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) || -- sd_bus_error_has_name(e, SD_BUS_ERROR_NO_REPLY) || -- sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED) || -- sd_bus_error_has_name(e, SD_BUS_ERROR_DISCONNECTED) || -- sd_bus_error_has_name(e, SD_BUS_ERROR_TIMEOUT); -+static bool error_shall_fallback(const char *error_id) { -+ return STR_IN_SET(error_id, -+ VARLINK_ERROR_DISCONNECTED, -+ VARLINK_ERROR_TIMEOUT, -+ VARLINK_ERROR_PROTOCOL, -+ VARLINK_ERROR_INTERFACE_NOT_FOUND, -+ VARLINK_ERROR_METHOD_NOT_FOUND, -+ VARLINK_ERROR_METHOD_NOT_IMPLEMENTED); - } - --static int count_addresses(sd_bus_message *m, int af, const char **canonical) { -- int c = 0, r; -- -- assert(m); -- assert(canonical); -- -- r = sd_bus_message_enter_container(m, 'a', "(iiay)"); -- if (r < 0) -- return r; -- -- while ((r = sd_bus_message_enter_container(m, 'r', "iiay")) > 0) { -- int family, ifindex; -- -- assert_cc(sizeof(int32_t) == sizeof(int)); -- -- r = sd_bus_message_read(m, "ii", &ifindex, &family); -- if (r < 0) -- return r; -- -- r = sd_bus_message_skip(m, "ay"); -- if (r < 0) -- return r; -- -- r = sd_bus_message_exit_container(m); -- if (r < 0) -- return r; -- -- if (af != AF_UNSPEC && family != af) -- continue; -- -- c++; -- } -- if (r < 0) -- return r; -- -- r = sd_bus_message_exit_container(m); -- if (r < 0) -- return r; -+static int connect_to_resolved(Varlink **ret) { -+ _cleanup_(varlink_unrefp) Varlink *link = NULL; -+ int r; - -- r = sd_bus_message_read(m, "s", canonical); -+ r = varlink_connect_address(&link, "/run/systemd/resolve/io.systemd.Resolve"); - if (r < 0) - return r; - -- r = sd_bus_message_rewind(m, true); -+ r = varlink_set_relative_timeout(link, SD_RESOLVED_QUERY_TIMEOUT_USEC); - if (r < 0) - return r; - -- return c; -+ *ret = TAKE_PTR(link); -+ return 0; - } - - static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) { -@@ -95,20 +60,111 @@ static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) { - return IN6_IS_ADDR_LINKLOCAL(&in6) ? ifindex : 0; - } - --static bool avoid_deadlock(void) { -+static int json_dispatch_ifindex(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { -+ int *ifi = userdata; -+ intmax_t t; - -- /* Check whether this lookup might have a chance of deadlocking because we are called from the service manager -- * code activating systemd-resolved.service. After all, we shouldn't synchronously do lookups to -- * systemd-resolved if we are required to finish before it can be started. This of course won't detect all -- * possible dead locks of this kind, but it should work for the most obvious cases. */ -+ assert(variant); -+ assert(ifi); - -- if (geteuid() != 0) /* Ignore the env vars unless we are privileged. */ -- return false; -+ if (!json_variant_is_integer(variant)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name)); - -- return streq_ptr(getenv("SYSTEMD_ACTIVATION_UNIT"), "systemd-resolved.service") && -- streq_ptr(getenv("SYSTEMD_ACTIVATION_SCOPE"), "system"); -+ t = json_variant_integer(variant); -+ if (t <= 0 || t > INT_MAX) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is out of bounds for an interface index.", strna(name)); -+ -+ *ifi = (int) t; -+ return 0; -+} -+ -+static int json_dispatch_family(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { -+ int *family = userdata; -+ intmax_t t; -+ -+ assert(variant); -+ assert(family); -+ -+ if (!json_variant_is_integer(variant)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name)); -+ -+ t = json_variant_integer(variant); -+ if (t < 0 || t > INT_MAX) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid family.", strna(name)); -+ -+ *family = (int) t; -+ return 0; -+} -+ -+typedef struct ResolveHostnameReply { -+ JsonVariant *addresses; -+ char *name; -+ uint64_t flags; -+} ResolveHostnameReply; -+ -+static void resolve_hostname_reply_destroy(ResolveHostnameReply *p) { -+ assert(p); -+ -+ json_variant_unref(p->addresses); -+ free(p->name); - } - -+static const JsonDispatch resolve_hostname_reply_dispatch_table[] = { -+ { "addresses", JSON_VARIANT_ARRAY, json_dispatch_variant, offsetof(ResolveHostnameReply, addresses), JSON_MANDATORY }, -+ { "name", JSON_VARIANT_STRING, json_dispatch_string, offsetof(ResolveHostnameReply, name), 0 }, -+ { "flags", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(ResolveHostnameReply, flags), 0 }, -+ {} -+}; -+ -+typedef struct AddressParameters { -+ int ifindex; -+ int family; -+ union in_addr_union address; -+ size_t address_size; -+} AddressParameters; -+ -+static int json_dispatch_address(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { -+ AddressParameters *p = userdata; -+ union in_addr_union buf = {}; -+ JsonVariant *i; -+ size_t n, k = 0; -+ -+ assert(variant); -+ assert(p); -+ -+ if (!json_variant_is_array(variant)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array.", strna(name)); -+ -+ n = json_variant_elements(variant); -+ if (!IN_SET(n, 4, 16)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name)); -+ -+ JSON_VARIANT_ARRAY_FOREACH(i, variant) { -+ intmax_t b; -+ -+ if (!json_variant_is_integer(i)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an integer.", k, strna(name)); -+ -+ b = json_variant_integer(i); -+ if (b < 0 || b > 0xff) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is out of range 0…255.", k, strna(name)); -+ -+ buf.bytes[k++] = (uint8_t) b; -+ } -+ -+ p->address = buf; -+ p->address_size = k; -+ -+ return 0; -+} -+ -+static const JsonDispatch address_parameters_dispatch_table[] = { -+ { "ifindex", JSON_VARIANT_INTEGER, json_dispatch_ifindex, offsetof(AddressParameters, ifindex), 0 }, -+ { "family", JSON_VARIANT_INTEGER, json_dispatch_family, offsetof(AddressParameters, family), JSON_MANDATORY }, -+ { "address", JSON_VARIANT_ARRAY, json_dispatch_address, 0, JSON_MANDATORY }, -+ {} -+}; -+ - enum nss_status _nss_resolve_gethostbyname4_r( - const char *name, - struct gaih_addrtuple **pat, -@@ -116,14 +172,15 @@ enum nss_status _nss_resolve_gethostbyname4_r( - int *errnop, int *h_errnop, - int32_t *ttlp) { - -- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; -- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -- struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL; -- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; -- const char *canonical = NULL; -- size_t l, ms, idx; -+ _cleanup_(resolve_hostname_reply_destroy) ResolveHostnameReply p = {}; -+ _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL; -+ struct gaih_addrtuple *r_tuple = NULL, *r_tuple_first = NULL; -+ _cleanup_(varlink_unrefp) Varlink *link = NULL; -+ const char *canonical = NULL, *error_id = NULL; -+ JsonVariant *entry, *rparams; -+ size_t l, ms, idx, c = 0; - char *r_name; -- int c, r, i = 0; -+ int r; - - PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); -@@ -134,50 +191,53 @@ enum nss_status _nss_resolve_gethostbyname4_r( - assert(errnop); - assert(h_errnop); - -- if (avoid_deadlock()) { -- r = -EDEADLK; -- goto fail; -- } -- -- r = sd_bus_open_system(&bus); -- if (r < 0) -- goto fail; -- -- r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveHostname"); -- if (r < 0) -- goto fail; -- -- r = sd_bus_message_set_auto_start(req, false); -+ r = connect_to_resolved(&link); - if (r < 0) - goto fail; - -- r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0); -+ r = json_build(&cparams, JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR("name", JSON_BUILD_STRING(name)))); - if (r < 0) - goto fail; - -- r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); -+ r = varlink_call(link, "io.systemd.Resolve.ResolveHostname", cparams, &rparams, &error_id, NULL); - if (r < 0) { -- if (!bus_error_shall_fallback(&error)) -+ if (!error_shall_fallback(error_id)) - goto not_found; - -- /* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails, -- allowing falling back to other nss modules. Treat all other error conditions as -- NOTFOUND. This includes DNSSEC errors and suchlike. (We don't use UNAVAIL in this -- case so that the nsswitch.conf configuration can distinguish such executed but -- negative replies from complete failure to talk to resolved). */ -+ /* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails, allowing falling -+ back to other nss modules. Treat all other error conditions as NOTFOUND. This includes -+ DNSSEC errors and suchlike. (We don't use UNAVAIL in this case so that the nsswitch.conf -+ configuration can distinguish such executed but negative replies from complete failure to -+ talk to resolved). */ - goto fail; - } - -- c = count_addresses(reply, AF_UNSPEC, &canonical); -- if (c < 0) { -- r = c; -+ r = json_dispatch(rparams, resolve_hostname_reply_dispatch_table, NULL, 0, &p); -+ if (r < 0) - goto fail; -- } -- if (c == 0) -+ if (json_variant_is_blank_object(p.addresses)) - goto not_found; - -- if (isempty(canonical)) -- canonical = name; -+ JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) { -+ AddressParameters q = {}; -+ -+ r = json_dispatch(entry, address_parameters_dispatch_table, NULL, 0, &q); -+ if (r < 0) -+ goto fail; -+ -+ if (!IN_SET(q.family, AF_INET, AF_INET6)) -+ continue; -+ -+ if (q.address_size != FAMILY_ADDRESS_SIZE(q.family)) { -+ r = -EINVAL; -+ goto fail; -+ } -+ -+ c++; -+ } -+ -+ canonical = p.name ?: name; - - l = strlen(canonical); - ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c; -@@ -196,56 +256,29 @@ enum nss_status _nss_resolve_gethostbyname4_r( - /* Second, append addresses */ - r_tuple_first = (struct gaih_addrtuple*) (buffer + idx); - -- r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); -- if (r < 0) -- goto fail; -- -- while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { -- int family, ifindex; -- const void *a; -- size_t sz; -- -- assert_cc(sizeof(int32_t) == sizeof(int)); -- -- r = sd_bus_message_read(reply, "ii", &ifindex, &family); -- if (r < 0) -- goto fail; -- -- if (ifindex < 0) { -- r = -EINVAL; -- goto fail; -- } -+ JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) { -+ AddressParameters q = {}; - -- r = sd_bus_message_read_array(reply, 'y', &a, &sz); -+ r = json_dispatch(entry, address_parameters_dispatch_table, NULL, 0, &q); - if (r < 0) - goto fail; - -- r = sd_bus_message_exit_container(reply); -- if (r < 0) -- goto fail; -- -- if (!IN_SET(family, AF_INET, AF_INET6)) -+ if (!IN_SET(q.family, AF_INET, AF_INET6)) - continue; - -- if (sz != FAMILY_ADDRESS_SIZE(family)) { -- r = -EINVAL; -- goto fail; -- } -- - r_tuple = (struct gaih_addrtuple*) (buffer + idx); -- r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple))); -+ r_tuple->next = (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple))); - r_tuple->name = r_name; -- r_tuple->family = family; -- r_tuple->scopeid = ifindex_to_scopeid(family, a, ifindex); -- memcpy(r_tuple->addr, a, sz); -+ r_tuple->family = q.family; -+ r_tuple->scopeid = ifindex_to_scopeid(q.family, &q.address, q.ifindex); -+ memcpy(r_tuple->addr, &q.address, q.address_size); - - idx += ALIGN(sizeof(struct gaih_addrtuple)); -- i++; - } -- if (r < 0) -- goto fail; - -- assert(i == c); -+ assert(r_tuple); -+ r_tuple->next = NULL; /* Override last next pointer */ -+ - assert(idx == ms); - - if (*pat) -@@ -283,13 +316,14 @@ enum nss_status _nss_resolve_gethostbyname3_r( - int32_t *ttlp, - char **canonp) { - -- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; -- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -+ _cleanup_(resolve_hostname_reply_destroy) ResolveHostnameReply p = {}; -+ _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL; - char *r_name, *r_aliases, *r_addr, *r_addr_list; -- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; -- size_t l, idx, ms, alen; -- const char *canonical; -- int c, r, i = 0; -+ _cleanup_(varlink_unrefp) Varlink *link = NULL; -+ const char *canonical, *error_id = NULL; -+ size_t l, idx, ms, alen, i = 0, c = 0; -+ JsonVariant *entry, *rparams; -+ int r; - - PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); -@@ -308,50 +342,53 @@ enum nss_status _nss_resolve_gethostbyname3_r( - goto fail; - } - -- if (avoid_deadlock()) { -- r = -EDEADLK; -- goto fail; -- } -- -- r = sd_bus_open_system(&bus); -- if (r < 0) -- goto fail; -- -- r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveHostname"); -- if (r < 0) -- goto fail; -- -- r = sd_bus_message_set_auto_start(req, false); -+ r = connect_to_resolved(&link); - if (r < 0) - goto fail; - -- r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0); -+ r = json_build(&cparams, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("name", JSON_BUILD_STRING(name)), -+ JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af)))); - if (r < 0) - goto fail; - -- r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); -+ r = varlink_call(link, "io.systemd.Resolve.ResolveHostname", cparams, &rparams, &error_id, NULL); - if (r < 0) { -- if (!bus_error_shall_fallback(&error)) -+ if (!error_shall_fallback(error_id)) - goto not_found; - - goto fail; - } - -- c = count_addresses(reply, af, &canonical); -- if (c < 0) { -- r = c; -+ r = json_dispatch(rparams, resolve_hostname_reply_dispatch_table, NULL, 0, &p); -+ if (r < 0) - goto fail; -- } -- if (c == 0) -+ if (json_variant_is_blank_object(p.addresses)) - goto not_found; - -- if (isempty(canonical)) -- canonical = name; -+ JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) { -+ AddressParameters q = {}; -+ -+ r = json_dispatch(entry, address_parameters_dispatch_table, NULL, 0, &q); -+ if (r < 0) -+ goto fail; -+ -+ if (!IN_SET(q.family, AF_INET, AF_INET6)) -+ continue; -+ -+ if (q.address_size != FAMILY_ADDRESS_SIZE(q.family)) { -+ r = -EINVAL; -+ goto fail; -+ } -+ -+ c++; -+ } -+ -+ canonical = p.name ?: name; - - alen = FAMILY_ADDRESS_SIZE(af); - l = strlen(canonical); - -- ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*); -+ ms = ALIGN(l+1) + c*ALIGN(alen) + (c+2) * sizeof(char*); - - if (buflen < ms) { - UNPROTECT_ERRNO; -@@ -373,45 +410,24 @@ enum nss_status _nss_resolve_gethostbyname3_r( - /* Third, append addresses */ - r_addr = buffer + idx; - -- r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); -- if (r < 0) -- goto fail; -- -- while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { -- int ifindex, family; -- const void *a; -- size_t sz; -- -- r = sd_bus_message_read(reply, "ii", &ifindex, &family); -- if (r < 0) -- goto fail; -- -- if (ifindex < 0) { -- r = -EINVAL; -- goto fail; -- } -- -- r = sd_bus_message_read_array(reply, 'y', &a, &sz); -- if (r < 0) -- goto fail; -+ JSON_VARIANT_ARRAY_FOREACH(entry, p.addresses) { -+ AddressParameters q = {}; - -- r = sd_bus_message_exit_container(reply); -+ r = json_dispatch(entry, address_parameters_dispatch_table, NULL, 0, &q); - if (r < 0) - goto fail; - -- if (family != af) -+ if (q.family != af) - continue; - -- if (sz != alen) { -+ if (q.address_size != alen) { - r = -EINVAL; - goto fail; - } - -- memcpy(r_addr + i*ALIGN(alen), a, alen); -+ memcpy(r_addr + i*ALIGN(alen), &q.address, alen); - i++; - } -- if (r < 0) -- goto fail; - - assert(i == c); - idx += c * ALIGN(alen); -@@ -456,6 +472,40 @@ not_found: - return NSS_STATUS_NOTFOUND; - } - -+typedef struct ResolveAddressReply { -+ JsonVariant *names; -+ uint64_t flags; -+} ResolveAddressReply; -+ -+static void resolve_address_reply_destroy(ResolveAddressReply *p) { -+ assert(p); -+ -+ json_variant_unref(p->names); -+} -+ -+static const JsonDispatch resolve_address_reply_dispatch_table[] = { -+ { "names", JSON_VARIANT_ARRAY, json_dispatch_variant, offsetof(ResolveAddressReply, names), JSON_MANDATORY }, -+ { "flags", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(ResolveAddressReply, flags), 0 }, -+ {} -+}; -+ -+typedef struct NameParameters { -+ int ifindex; -+ char *name; -+} NameParameters; -+ -+static void name_parameters_destroy(NameParameters *p) { -+ assert(p); -+ -+ free(p->name); -+} -+ -+static const JsonDispatch name_parameters_dispatch_table[] = { -+ { "ifindex", JSON_VARIANT_INTEGER, json_dispatch_ifindex, offsetof(NameParameters, ifindex), 0 }, -+ { "name", JSON_VARIANT_UNSIGNED, json_dispatch_string, offsetof(NameParameters, name), JSON_MANDATORY }, -+ {} -+}; -+ - enum nss_status _nss_resolve_gethostbyaddr2_r( - const void* addr, socklen_t len, - int af, -@@ -464,14 +514,15 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( - int *errnop, int *h_errnop, - int32_t *ttlp) { - -- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; -- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -+ _cleanup_(resolve_address_reply_destroy) ResolveAddressReply p = {}; -+ _cleanup_(json_variant_unrefp) JsonVariant *cparams = NULL; - char *r_name, *r_aliases, *r_addr, *r_addr_list; -- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; -+ _cleanup_(varlink_unrefp) Varlink *link = NULL; -+ JsonVariant *entry, *rparams; -+ const char *n, *error_id; - unsigned c = 0, i = 0; - size_t ms = 0, idx; -- const char *n; -- int r, ifindex; -+ int r; - - PROTECT_ERRNO; - BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); -@@ -494,70 +545,42 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( - goto fail; - } - -- if (avoid_deadlock()) { -- r = -EDEADLK; -- goto fail; -- } -- -- r = sd_bus_open_system(&bus); -- if (r < 0) -- goto fail; -- -- r = bus_message_new_method_call(bus, &req, bus_resolve_mgr, "ResolveAddress"); -- if (r < 0) -- goto fail; -- -- r = sd_bus_message_set_auto_start(req, false); -- if (r < 0) -- goto fail; -- -- r = sd_bus_message_append(req, "ii", 0, af); -- if (r < 0) -- goto fail; -- -- r = sd_bus_message_append_array(req, 'y', addr, len); -+ r = connect_to_resolved(&link); - if (r < 0) - goto fail; - -- r = sd_bus_message_append(req, "t", (uint64_t) 0); -+ r = json_build(&cparams, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(addr, len)), -+ JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af)))); - if (r < 0) - goto fail; - -- r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); -+ r = varlink_call(link, "io.systemd.Resolve.ResolveAddress", cparams, &rparams, &error_id, NULL); - if (r < 0) { -- if (!bus_error_shall_fallback(&error)) -+ if (!error_shall_fallback(error_id)) - goto not_found; - - goto fail; - } - -- r = sd_bus_message_enter_container(reply, 'a', "(is)"); -+ r = json_dispatch(rparams, resolve_address_reply_dispatch_table, NULL, 0, &p); - if (r < 0) - goto fail; -+ if (json_variant_is_blank_object(p.names)) -+ goto not_found; - -- while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) { -+ JSON_VARIANT_ARRAY_FOREACH(entry, p.names) { -+ _cleanup_(name_parameters_destroy) NameParameters q = {}; - -- if (ifindex < 0) { -- r = -EINVAL; -+ r = json_dispatch(entry, name_parameters_dispatch_table, NULL, 0, &q); -+ if (r < 0) - goto fail; -- } - -- c++; -- ms += ALIGN(strlen(n) + 1); -+ ms += ALIGN(strlen(q.name) + 1); - } -- if (r < 0) -- goto fail; -- -- r = sd_bus_message_rewind(reply, false); -- if (r < 0) -- goto fail; -- -- if (c <= 0) -- goto not_found; - -- ms += ALIGN(len) + /* the address */ -- 2 * sizeof(char*) + /* pointers to the address, plus trailing NULL */ -- c * sizeof(char*); /* pointers to aliases, plus trailing NULL */ -+ ms += ALIGN(len) + /* the address */ -+ 2 * sizeof(char*) + /* pointers to the address, plus trailing NULL */ -+ json_variant_elements(p.names) * sizeof(char*); /* pointers to aliases, plus trailing NULL */ - - if (buflen < ms) { - UNPROTECT_ERRNO; -@@ -584,22 +607,25 @@ enum nss_status _nss_resolve_gethostbyaddr2_r( - /* Fourth, place aliases */ - i = 0; - r_name = buffer + idx; -- while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) { -- char *p; -+ JSON_VARIANT_ARRAY_FOREACH(entry, p.names) { -+ _cleanup_(name_parameters_destroy) NameParameters q = {}; - size_t l; -+ char *z; - -- l = strlen(n); -- p = buffer + idx; -- memcpy(p, n, l+1); -+ r = json_dispatch(entry, name_parameters_dispatch_table, NULL, 0, &q); -+ if (r < 0) -+ goto fail; -+ -+ l = strlen(q.name); -+ z = buffer + idx; -+ memcpy(z, n, l+1); - - if (i > 0) -- ((char**) r_aliases)[i-1] = p; -+ ((char**) r_aliases)[i-1] = z; - i++; - - idx += ALIGN(l+1); - } -- if (r < 0) -- goto fail; - - ((char**) r_aliases)[c-1] = NULL; - assert(idx == ms); -diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c -index 5dc5aac..0e8c13f 100644 ---- a/src/nss-systemd/nss-systemd.c -+++ b/src/nss-systemd/nss-systemd.c -@@ -6,13 +6,13 @@ - #include "env-util.h" - #include "errno-util.h" - #include "fd-util.h" --#include "group-record-nss.h" - #include "macro.h" - #include "nss-systemd.h" - #include "nss-util.h" - #include "pthread-util.h" - #include "signal-util.h" - #include "strv.h" -+#include "user-record-nss.h" - #include "user-util.h" - #include "userdb-glue.h" - #include "userdb.h" -diff --git a/src/nss-systemd/userdb-glue.c b/src/nss-systemd/userdb-glue.c -index 8e5b3eb..2ac299d 100644 ---- a/src/nss-systemd/userdb-glue.c -+++ b/src/nss-systemd/userdb-glue.c -@@ -2,9 +2,9 @@ - - #include "env-util.h" - #include "fd-util.h" --#include "group-record-nss.h" - #include "nss-systemd.h" - #include "strv.h" -+#include "user-record-nss.h" - #include "user-record.h" - #include "userdb-glue.h" - #include "userdb.h" -diff --git a/src/partition/growfs.c b/src/partition/growfs.c -index 98a7e4d..3f34ad3 100644 ---- a/src/partition/growfs.c -+++ b/src/partition/growfs.c -@@ -11,7 +11,8 @@ - #include - - #include "blockdev-util.h" --#include "crypt-util.h" -+#include "btrfs-util.h" -+#include "cryptsetup-util.h" - #include "device-nodes.h" - #include "dissect-image.h" - #include "escape.h" -@@ -30,11 +31,15 @@ static bool arg_dry_run = false; - #if HAVE_LIBCRYPTSETUP - static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_devno) { - _cleanup_free_ char *devpath = NULL, *main_devpath = NULL; -- _cleanup_(crypt_freep) struct crypt_device *cd = NULL; -+ _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; - _cleanup_close_ int main_devfd = -1; - uint64_t size; - int r; - -+ r = dlopen_cryptsetup(); -+ if (r < 0) -+ return log_error_errno(r, "Cannot resize LUKS device: %m"); -+ - r = device_path_make_major_minor(S_IFBLK, main_devno, &main_devpath); - if (r < 0) - return log_error_errno(r, "Failed to format device major/minor path: %m"); -@@ -52,20 +57,20 @@ static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_ - if (r < 0) - return log_error_errno(r, "Failed to format major/minor path: %m"); - -- r = crypt_init(&cd, devpath); -+ r = sym_crypt_init(&cd, devpath); - if (r < 0) - return log_error_errno(r, "crypt_init(\"%s\") failed: %m", devpath); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - -- r = crypt_load(cd, CRYPT_LUKS, NULL); -+ r = sym_crypt_load(cd, CRYPT_LUKS, NULL); - if (r < 0) - return log_debug_errno(r, "Failed to load LUKS metadata for %s: %m", devpath); - - if (arg_dry_run) - return 0; - -- r = crypt_resize(cd, main_devpath, 0); -+ r = sym_crypt_resize(cd, main_devpath, 0); - if (r < 0) - return log_error_errno(r, "crypt_resize() of %s failed: %m", devpath); - -@@ -85,15 +90,15 @@ static int maybe_resize_underlying_device(const char *mountpath, dev_t main_devn - int r; - - #if HAVE_LIBCRYPTSETUP -- crypt_set_log_callback(NULL, cryptsetup_log_glue, NULL); -- if (DEBUG_LOGGING) -- crypt_set_debug_level(CRYPT_DEBUG_ALL); -+ cryptsetup_enable_logging(NULL); - #endif - - r = get_block_device_harder(mountpath, &devno); - if (r < 0) - return log_error_errno(r, "Failed to determine underlying block device of \"%s\": %m", - mountpath); -+ if (devno == 0) -+ return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" not backed by block device.", arg_target); - - log_debug("Underlying device %d:%d, main dev %d:%d, %s", - major(devno), minor(devno), -@@ -210,8 +215,12 @@ static int run(int argc, char *argv[]) { - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "\"%s\" is not a mount point: %m", arg_target); - - r = get_block_device(arg_target, &devno); -+ if (r == -EUCLEAN) -+ return btrfs_log_dev_root(LOG_ERR, r, arg_target); - if (r < 0) - return log_error_errno(r, "Failed to determine block device of \"%s\": %m", arg_target); -+ if (devno == 0) -+ return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" not backed by block device.", arg_target); - - r = maybe_resize_underlying_device(arg_target, devno); - if (r < 0) -diff --git a/src/partition/makefs.c b/src/partition/makefs.c -index 97f50c9..30dcef2 100644 ---- a/src/partition/makefs.c -+++ b/src/partition/makefs.c -@@ -1,6 +1,7 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - - #include -+#include - #include - #include - #include -@@ -11,40 +12,15 @@ - #include "dissect-image.h" - #include "fd-util.h" - #include "main-func.h" -+#include "mkfs-util.h" - #include "process-util.h" - #include "signal-util.h" - #include "string-util.h" - --static int makefs(const char *type, const char *device) { -- const char *mkfs; -- pid_t pid; -- int r; -- -- if (streq(type, "swap")) -- mkfs = "/sbin/mkswap"; -- else -- mkfs = strjoina("/sbin/mkfs.", type); -- if (access(mkfs, X_OK) != 0) -- return log_error_errno(errno, "%s is not executable: %m", mkfs); -- -- r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); -- if (r < 0) -- return r; -- if (r == 0) { -- const char *cmdline[3] = { mkfs, device, NULL }; -- -- /* Child */ -- -- execv(cmdline[0], (char**) cmdline); -- _exit(EXIT_FAILURE); -- } -- -- return wait_for_terminate_and_check(mkfs, pid, WAIT_LOG); --} -- - static int run(int argc, char *argv[]) { -- _cleanup_free_ char *device = NULL, *type = NULL, *detected = NULL; -+ _cleanup_free_ char *device = NULL, *fstype = NULL, *detected = NULL; - _cleanup_close_ int lock_fd = -1; -+ sd_id128_t uuid; - struct stat st; - int r; - -@@ -55,8 +31,8 @@ static int run(int argc, char *argv[]) { - "This program expects two arguments."); - - /* type and device must be copied because makefs calls safe_fork, which clears argv[] */ -- type = strdup(argv[1]); -- if (!type) -+ fstype = strdup(argv[1]); -+ if (!fstype) - return log_oom(); - - device = strdup(argv[2]); -@@ -85,7 +61,11 @@ static int run(int argc, char *argv[]) { - return 0; - } - -- return makefs(type, device); -+ r = sd_id128_randomize(&uuid); -+ if (r < 0) -+ return log_error_errno(r, "Failed to generate UUID for file system: %m"); -+ -+ return make_filesystem(device, fstype, basename(device), uuid, true); - } - - DEFINE_MAIN_FUNCTION(run); -diff --git a/src/partition/repart.c b/src/partition/repart.c -index 2e5f5d1..83582b4 100644 ---- a/src/partition/repart.c -+++ b/src/partition/repart.c -@@ -24,22 +24,32 @@ - #include "btrfs-util.h" - #include "conf-files.h" - #include "conf-parser.h" -+#include "cryptsetup-util.h" - #include "def.h" - #include "efivars.h" - #include "errno-util.h" - #include "fd-util.h" -+#include "fileio.h" - #include "format-table.h" - #include "format-util.h" - #include "fs-util.h" - #include "gpt.h" - #include "id128-util.h" -+#include "json.h" - #include "list.h" - #include "locale-util.h" -+#include "loop-util.h" - #include "main-func.h" -+#include "mkdir.h" -+#include "mkfs-util.h" -+#include "mount-util.h" - #include "parse-util.h" - #include "path-util.h" - #include "pretty-print.h" - #include "proc-cmdline.h" -+#include "process-util.h" -+#include "random-util.h" -+#include "resize-fs.h" - #include "sort-util.h" - #include "specifier.h" - #include "stat-util.h" -@@ -47,6 +57,7 @@ - #include "string-util.h" - #include "strv.h" - #include "terminal-util.h" -+#include "user-util.h" - #include "utf8.h" - - /* If not configured otherwise use a minimal partition size of 10M */ -@@ -55,6 +66,12 @@ - /* Hard lower limit for new partition sizes */ - #define HARD_MIN_SIZE 4096 - -+/* libfdisk takes off slightly more than 1M of the disk size when creating a GPT disk label */ -+#define GPT_METADATA_SIZE (1044*1024) -+ -+/* LUKS2 takes off 16M of the partition size with its metadata by default */ -+#define LUKS2_METADATA_SIZE (16*1024*1024) -+ - /* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks - * are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B - * sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll -@@ -79,9 +96,15 @@ static sd_id128_t arg_seed = SD_ID128_NULL; - static bool arg_randomize = false; - static int arg_pretty = -1; - static uint64_t arg_size = UINT64_MAX; -+static bool arg_size_auto = false; -+static bool arg_json = false; -+static JsonFormatFlags arg_json_format_flags = 0; -+static void *arg_key = NULL; -+static size_t arg_key_size = 0; - - STATIC_DESTRUCTOR_REGISTER(arg_root, freep); - STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep); -+STATIC_DESTRUCTOR_REGISTER(arg_key, erase_and_freep); - - typedef struct Partition Partition; - typedef struct FreeArea FreeArea; -@@ -118,6 +141,10 @@ struct Partition { - int copy_blocks_fd; - uint64_t copy_blocks_size; - -+ char *format; -+ char **copy_files; -+ bool encrypt; -+ - LIST_FIELDS(Partition, partitions); - }; - -@@ -201,6 +228,9 @@ static Partition* partition_free(Partition *p) { - free(p->copy_blocks_path); - safe_close(p->copy_blocks_fd); - -+ free(p->format); -+ strv_free(p->copy_files); -+ - return mfree(p); - } - -@@ -349,8 +379,25 @@ static uint64_t partition_min_size(const Partition *p) { - - sz = p->current_size != UINT64_MAX ? p->current_size : HARD_MIN_SIZE; - -- if (p->copy_blocks_size != UINT64_MAX) -- sz = MAX(p->copy_blocks_size, sz); -+ if (!PARTITION_EXISTS(p)) { -+ uint64_t d = 0; -+ -+ if (p->encrypt) -+ d += round_up_size(LUKS2_METADATA_SIZE, 4096); -+ -+ if (p->copy_blocks_size != UINT64_MAX) -+ d += round_up_size(p->copy_blocks_size, 4096); -+ else if (p->format || p->encrypt) { -+ uint64_t f; -+ -+ /* If we shall synthesize a file system, take minimal fs size into account (assumed to be 4K if not known) */ -+ f = p->format ? minimal_size_by_fs_name(p->format) : UINT64_MAX; -+ d += f == UINT64_MAX ? 4096 : f; -+ } -+ -+ if (d > sz) -+ sz = d; -+ } - - return MAX(p->size_min != UINT64_MAX ? p->size_min : DEFAULT_MIN_SIZE, sz); - } -@@ -864,6 +911,20 @@ static int config_parse_type( - return 0; - } - -+static const Specifier specifier_table[] = { -+ { 'm', specifier_machine_id, NULL }, -+ { 'b', specifier_boot_id, NULL }, -+ { 'H', specifier_host_name, NULL }, -+ { 'l', specifier_short_host_name, NULL }, -+ { 'v', specifier_kernel_release, NULL }, -+ { 'a', specifier_architecture, NULL }, -+ { 'o', specifier_os_id, NULL }, -+ { 'w', specifier_os_version_id, NULL }, -+ { 'B', specifier_os_build_id, NULL }, -+ { 'W', specifier_os_variant_id, NULL }, -+ {} -+}; -+ - static int config_parse_label( - const char *unit, - const char *filename, -@@ -876,20 +937,6 @@ static int config_parse_label( - void *data, - void *userdata) { - -- static const Specifier specifier_table[] = { -- { 'm', specifier_machine_id, NULL }, -- { 'b', specifier_boot_id, NULL }, -- { 'H', specifier_host_name, NULL }, -- { 'l', specifier_short_host_name, NULL }, -- { 'v', specifier_kernel_release, NULL }, -- { 'a', specifier_architecture, NULL }, -- { 'o', specifier_os_id, NULL }, -- { 'w', specifier_os_version_id, NULL }, -- { 'B', specifier_os_build_id, NULL }, -- { 'W', specifier_os_variant_id, NULL }, -- {} -- }; -- - _cleanup_free_ char16_t *recoded = NULL; - _cleanup_free_ char *resolved = NULL; - char **label = data; -@@ -900,7 +947,7 @@ static int config_parse_label( - - r = specifier_printf(rvalue, specifier_table, NULL, &resolved); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, -+ log_syntax(unit, LOG_WARNING, filename, line, r, - "Failed to expand specifiers in Label=, ignoring: %s", rvalue); - return 0; - } -@@ -997,21 +1044,120 @@ static int config_parse_size4096( - return 0; - } - -+static int config_parse_fstype( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ -+ char **fstype = data; -+ -+ assert(rvalue); -+ assert(data); -+ -+ if (!filename_is_valid(rvalue)) -+ return log_syntax(unit, LOG_ERR, filename, line, 0, -+ "File system type is not valid, refusing: %s", rvalue); -+ -+ return free_and_strdup_warn(fstype, rvalue); -+} -+ -+static int config_parse_copy_files( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ -+ _cleanup_free_ char *source = NULL, *buffer = NULL, *resolved_source = NULL, *resolved_target = NULL; -+ const char *p = rvalue, *target; -+ Partition *partition = data; -+ int r; -+ -+ assert(rvalue); -+ assert(partition); -+ -+ r = extract_first_word(&p, &source, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r < 0) -+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract source path: %s", rvalue); -+ if (r == 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "No argument specified: %s", rvalue); -+ return 0; -+ } -+ -+ r = extract_first_word(&p, &buffer, ":", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r < 0) -+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract target path: %s", rvalue); -+ if (r == 0) -+ target = source; /* No target, then it's the same as the source */ -+ else -+ target = buffer; -+ -+ if (!isempty(p)) -+ return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Too many arguments: %s", rvalue); -+ -+ r = specifier_printf(source, specifier_table, NULL, &resolved_source); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to expand specifiers in CopyFiles= source, ignoring: %s", rvalue); -+ return 0; -+ } -+ -+ if (!path_is_absolute(resolved_source) || !path_is_normalized(resolved_source)) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Invalid path name in CopyFiles= source, ignoring: %s", resolved_source); -+ return 0; -+ } -+ -+ r = specifier_printf(target, specifier_table, NULL, &resolved_target); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to expand specifiers in CopyFiles= target, ignoring: %s", resolved_target); -+ return 0; -+ } -+ -+ if (!path_is_absolute(resolved_target) || !path_is_normalized(resolved_target)) { -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Invalid path name in CopyFiles= source, ignoring: %s", resolved_target); -+ return 0; -+ } -+ -+ r = strv_consume_pair(&partition->copy_files, TAKE_PTR(resolved_source), TAKE_PTR(resolved_target)); -+ if (r < 0) -+ return log_oom(); -+ -+ return 0; -+} -+ - static int partition_read_definition(Partition *p, const char *path) { - - ConfigTableItem table[] = { -- { "Partition", "Type", config_parse_type, 0, &p->type_uuid }, -- { "Partition", "Label", config_parse_label, 0, &p->new_label }, -- { "Partition", "UUID", config_parse_id128, 0, &p->new_uuid }, -- { "Partition", "Priority", config_parse_int32, 0, &p->priority }, -- { "Partition", "Weight", config_parse_weight, 0, &p->weight }, -- { "Partition", "PaddingWeight", config_parse_weight, 0, &p->padding_weight }, -- { "Partition", "SizeMinBytes", config_parse_size4096, 1, &p->size_min }, -- { "Partition", "SizeMaxBytes", config_parse_size4096, -1, &p->size_max }, -- { "Partition", "PaddingMinBytes", config_parse_size4096, 1, &p->padding_min }, -- { "Partition", "PaddingMaxBytes", config_parse_size4096, -1, &p->padding_max }, -- { "Partition", "FactoryReset", config_parse_bool, 0, &p->factory_reset }, -- { "Partition", "CopyBlocks", config_parse_path, 0, &p->copy_blocks_path }, -+ { "Partition", "Type", config_parse_type, 0, &p->type_uuid }, -+ { "Partition", "Label", config_parse_label, 0, &p->new_label }, -+ { "Partition", "UUID", config_parse_id128, 0, &p->new_uuid }, -+ { "Partition", "Priority", config_parse_int32, 0, &p->priority }, -+ { "Partition", "Weight", config_parse_weight, 0, &p->weight }, -+ { "Partition", "PaddingWeight", config_parse_weight, 0, &p->padding_weight }, -+ { "Partition", "SizeMinBytes", config_parse_size4096, 1, &p->size_min }, -+ { "Partition", "SizeMaxBytes", config_parse_size4096, -1, &p->size_max }, -+ { "Partition", "PaddingMinBytes", config_parse_size4096, 1, &p->padding_min }, -+ { "Partition", "PaddingMaxBytes", config_parse_size4096, -1, &p->padding_max }, -+ { "Partition", "FactoryReset", config_parse_bool, 0, &p->factory_reset }, -+ { "Partition", "CopyBlocks", config_parse_path, 0, &p->copy_blocks_path }, -+ { "Partition", "Format", config_parse_fstype, 0, &p->format }, -+ { "Partition", "CopyFiles", config_parse_copy_files, 0, p }, -+ { "Partition", "Encrypt", config_parse_bool, 0, &p->encrypt }, - {} - }; - int r; -@@ -1037,6 +1183,21 @@ static int partition_read_definition(Partition *p, const char *path) { - return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), - "Type= not defined, refusing."); - -+ if (p->copy_blocks_path && (p->format || !strv_isempty(p->copy_files))) -+ return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), -+ "Format= and CopyBlocks= cannot be combined, refusing."); -+ -+ if (!strv_isempty(p->copy_files) && streq_ptr(p->format, "swap")) -+ return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), -+ "Format=swap and CopyFiles= cannot be combined, refusing."); -+ -+ if (!p->format && (!strv_isempty(p->copy_files) || (p->encrypt && !p->copy_blocks_path))) { -+ /* Pick "ext4" as file system if we are configured to copy files or encrypt the device */ -+ p->format = strdup("ext4"); -+ if (!p->format) -+ return log_oom(); -+ } -+ - return 0; - } - -@@ -1188,23 +1349,23 @@ static int fdisk_set_disklabel_id_by_uuid(struct fdisk_context *c, sd_id128_t id - return fdisk_set_ask(c, NULL, NULL); - } - --#define DISK_UUID_TOKEN "disk-uuid" -- --static int disk_acquire_uuid(Context *context, sd_id128_t *ret) { -+static int derive_uuid(sd_id128_t base, const char *token, sd_id128_t *ret) { - union { - unsigned char md[SHA256_DIGEST_LENGTH]; - sd_id128_t id; - } result; - -- assert(context); -+ assert(token); - assert(ret); - -- /* Calculate the HMAC-SHA256 of the string "disk-uuid", keyed off the machine ID. We use the machine -- * ID as key (and not as cleartext!) since it's the machine ID we don't want to leak. */ -+ /* Derive a new UUID from the specified UUID in a stable and reasonably safe way. Specifically, we -+ * calculate the HMAC-SHA256 of the specified token string, keyed by the supplied base (typically the -+ * machine ID). We use the machine ID as key (and not as cleartext!) of the HMAC operation since it's -+ * the machine ID we don't want to leak. */ - - if (!HMAC(EVP_sha256(), -- &context->seed, sizeof(context->seed), -- (const unsigned char*) DISK_UUID_TOKEN, strlen(DISK_UUID_TOKEN), -+ &base, sizeof(base), -+ (const unsigned char*) token, strlen(token), - result.md, NULL)) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "HMAC-SHA256 calculation failed."); - -@@ -1231,6 +1392,11 @@ static int context_load_partition_table( - assert(context); - assert(node); - assert(backing_fd); -+ assert(!context->fdisk_context); -+ assert(!context->free_areas); -+ assert(context->start == UINT64_MAX); -+ assert(context->end == UINT64_MAX); -+ assert(context->total == UINT64_MAX); - - c = fdisk_new_context(); - if (!c) -@@ -1246,6 +1412,24 @@ static int context_load_partition_table( - - r = fdisk_assign_device(c, procfs_path, arg_dry_run); - } -+ if (r == -EINVAL && arg_size_auto) { -+ struct stat st; -+ -+ /* libfdisk returns EINVAL if opening a file of size zero. Let's check for that, and accept -+ * it if automatic sizing is requested. */ -+ -+ if (*backing_fd < 0) -+ r = stat(node, &st); -+ else -+ r = fstat(*backing_fd, &st); -+ if (r < 0) -+ return log_error_errno(errno, "Failed to stat block device '%s': %m", node); -+ -+ if (S_ISREG(st.st_mode) && st.st_size == 0) -+ return /* from_scratch = */ true; -+ -+ r = -EINVAL; -+ } - if (r < 0) - return log_error_errno(r, "Failed to open device '%s': %m", node); - -@@ -1301,15 +1485,11 @@ static int context_load_partition_table( - } - - if (from_scratch) { -- r = fdisk_enable_wipe(c, true); -- if (r < 0) -- return log_error_errno(r, "Failed to enable wiping of disk signature: %m"); -- - r = fdisk_create_disklabel(c, "gpt"); - if (r < 0) - return log_error_errno(r, "Failed to create GPT disk label: %m"); - -- r = disk_acquire_uuid(context, &disk_uuid); -+ r = derive_uuid(context->seed, "disk-uuid", &disk_uuid); - if (r < 0) - return log_error_errno(r, "Failed to acquire disk GPT uuid: %m"); - -@@ -1329,7 +1509,7 @@ static int context_load_partition_table( - return log_error_errno(r, "Failed to parse current GPT disk label UUID: %m"); - - if (sd_id128_is_null(disk_uuid)) { -- r = disk_acquire_uuid(context, &disk_uuid); -+ r = derive_uuid(context->seed, "disk-uuid", &disk_uuid); - if (r < 0) - return log_error_errno(r, "Failed to acquire disk GPT uuid: %m"); - -@@ -1560,7 +1740,8 @@ static void context_unload_partition_table(Context *context) { - p->padding_area = NULL; - p->allocated_to_area = NULL; - -- p->current_uuid = p->new_uuid = SD_ID128_NULL; -+ p->current_uuid = SD_ID128_NULL; -+ p->current_label = mfree(p->current_label); - } - - context->start = UINT64_MAX; -@@ -1620,12 +1801,23 @@ static int context_dump_partitions(Context *context, const char *node) { - Partition *p; - int r; - -- t = table_new("type", "label", "uuid", "file", "node", "offset", "raw size", "size", "raw padding", "padding"); -+ if (!arg_json && context->n_partitions == 0) { -+ log_info("Empty partition table."); -+ return 0; -+ } -+ -+ t = table_new("type", "label", "uuid", "file", "node", "offset", "old size", "raw size", "size", "old padding", "raw padding", "padding", "activity"); - if (!t) - return log_oom(); - -- if (!DEBUG_LOGGING) -- (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4, (size_t) 7, (size_t) 9, (size_t) -1); -+ if (!DEBUG_LOGGING) { -+ if (arg_json) -+ (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4, -+ (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 9, (size_t) 10, (size_t) 12, (size_t) -1); -+ else -+ (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4, -+ (size_t) 8, (size_t) 11, (size_t) -1); -+ } - - (void) table_set_align_percent(t, table_get_cell(t, 0, 4), 100); - (void) table_set_align_percent(t, table_get_cell(t, 0, 5), 100); -@@ -1633,11 +1825,16 @@ static int context_dump_partitions(Context *context, const char *node) { - LIST_FOREACH(partitions, p, context->partitions) { - _cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL; - char uuid_buffer[ID128_UUID_STRING_MAX]; -- const char *label; -+ const char *label, *activity = NULL; - - if (p->dropped) - continue; - -+ if (p->current_size == UINT64_MAX) -+ activity = "create"; -+ else if (p->current_size != p->new_size) -+ activity = "resize"; -+ - label = partition_label(p); - partname = p->partno != UINT64_MAX ? fdisk_partname(node, p->partno+1) : NULL; - -@@ -1660,17 +1857,20 @@ static int context_dump_partitions(Context *context, const char *node) { - TABLE_STRING, label ?: "-", TABLE_SET_COLOR, label ? NULL : ansi_grey(), - TABLE_UUID, sd_id128_is_null(p->new_uuid) ? p->current_uuid : p->new_uuid, - TABLE_STRING, p->definition_path ? basename(p->definition_path) : "-", TABLE_SET_COLOR, p->definition_path ? NULL : ansi_grey(), -- TABLE_STRING, partname ?: "no", TABLE_SET_COLOR, partname ? NULL : ansi_highlight(), -+ TABLE_STRING, partname ?: "-", TABLE_SET_COLOR, partname ? NULL : ansi_highlight(), - TABLE_UINT64, p->offset, -+ TABLE_UINT64, p->current_size == UINT64_MAX ? 0 : p->current_size, - TABLE_UINT64, p->new_size, - TABLE_STRING, size_change, TABLE_SET_COLOR, !p->partitions_next && sum_size > 0 ? ansi_underline() : NULL, -+ TABLE_UINT64, p->current_padding == UINT64_MAX ? 0 : p->current_padding, - TABLE_UINT64, p->new_padding, -- TABLE_STRING, padding_change, TABLE_SET_COLOR, !p->partitions_next && sum_padding > 0 ? ansi_underline() : NULL); -+ TABLE_STRING, padding_change, TABLE_SET_COLOR, !p->partitions_next && sum_padding > 0 ? ansi_underline() : NULL, -+ TABLE_STRING, activity ?: "unknown"); - if (r < 0) - return table_log_add_error(r); - } - -- if (sum_padding > 0 || sum_size > 0) { -+ if (!arg_json && (sum_padding > 0 || sum_size > 0)) { - char s[FORMAT_BYTES_MAX]; - const char *a, *b; - -@@ -1686,14 +1886,20 @@ static int context_dump_partitions(Context *context, const char *node) { - TABLE_EMPTY, - TABLE_EMPTY, - TABLE_EMPTY, -+ TABLE_EMPTY, - TABLE_STRING, a, - TABLE_EMPTY, -- TABLE_STRING, b); -+ TABLE_EMPTY, -+ TABLE_STRING, b, -+ TABLE_EMPTY); - if (r < 0) - return table_log_add_error(r); - } - -- r = table_print(t, stdout); -+ if (arg_json) -+ r = table_print_json(t, stdout, arg_json_format_flags); -+ else -+ r = table_print(t, stdout); - if (r < 0) - return log_error_errno(r, "Failed to dump table: %m"); - -@@ -1915,32 +2121,29 @@ static bool context_changed(const Context *context) { - return false; - } - --static int context_wipe_partition(Context *context, Partition *p) { -+static int context_wipe_range(Context *context, uint64_t offset, uint64_t size) { - _cleanup_(blkid_free_probep) blkid_probe probe = NULL; - int r; - - assert(context); -- assert(p); -- assert(!PARTITION_EXISTS(p)); /* Safety check: never wipe existing partitions */ -+ assert(offset != UINT64_MAX); -+ assert(size != UINT64_MAX); - - probe = blkid_new_probe(); - if (!probe) - return log_oom(); - -- assert(p->offset != UINT64_MAX); -- assert(p->new_size != UINT64_MAX); -- - errno = 0; -- r = blkid_probe_set_device(probe, fdisk_get_devfd(context->fdisk_context), p->offset, p->new_size); -+ r = blkid_probe_set_device(probe, fdisk_get_devfd(context->fdisk_context), offset, size); - if (r < 0) -- return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to allocate device probe for partition %" PRIu64 ".", p->partno); -+ return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to allocate device probe for wiping."); - - errno = 0; - if (blkid_probe_enable_superblocks(probe, true) < 0 || - blkid_probe_set_superblocks_flags(probe, BLKID_SUBLKS_MAGIC|BLKID_SUBLKS_BADCSUM) < 0 || - blkid_probe_enable_partitions(probe, true) < 0 || - blkid_probe_set_partitions_flags(probe, BLKID_PARTS_MAGIC) < 0) -- return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to enable superblock and partition probing for partition %" PRIu64 ".", p->partno); -+ return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to enable superblock and partition probing."); - - for (;;) { - errno = 0; -@@ -1955,11 +2158,32 @@ static int context_wipe_partition(Context *context, Partition *p) { - return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to wipe file system signature."); - } - -- log_info("Successfully wiped file system signatures from partition %" PRIu64 ".", p->partno); - return 0; - } - --static int context_discard_range(Context *context, uint64_t offset, uint64_t size) { -+static int context_wipe_partition(Context *context, Partition *p) { -+ int r; -+ -+ assert(context); -+ assert(p); -+ assert(!PARTITION_EXISTS(p)); /* Safety check: never wipe existing partitions */ -+ -+ assert(p->offset != UINT64_MAX); -+ assert(p->new_size != UINT64_MAX); -+ -+ r = context_wipe_range(context, p->offset, p->new_size); -+ if (r < 0) -+ return r; -+ -+ log_info("Successfully wiped file system signatures from future partition %" PRIu64 ".", p->partno); -+ return 0; -+} -+ -+static int context_discard_range( -+ Context *context, -+ uint64_t offset, -+ uint64_t size) { -+ - struct stat st; - int fd; - -@@ -2027,7 +2251,7 @@ static int context_discard_partition(Context *context, Partition *p) { - - r = context_discard_range(context, p->offset, p->new_size); - if (r == -EOPNOTSUPP) { -- log_info("Storage does not support discarding, not discarding data in new partition %" PRIu64 ".", p->partno); -+ log_info("Storage does not support discard, not discarding data in future partition %" PRIu64 ".", p->partno); - return 0; - } - if (r == 0) { -@@ -2035,9 +2259,9 @@ static int context_discard_partition(Context *context, Partition *p) { - return 0; - } - if (r < 0) -- return log_error_errno(r, "Failed to discard data for new partition %" PRIu64 ".", p->partno); -+ return log_error_errno(r, "Failed to discard data for future partition %" PRIu64 ".", p->partno); - -- log_info("Successfully discarded data from partition %" PRIu64 ".", p->partno); -+ log_info("Successfully discarded data from future partition %" PRIu64 ".", p->partno); - return 1; - } - -@@ -2078,9 +2302,9 @@ static int context_discard_gap_after(Context *context, Partition *p) { - r = context_discard_range(context, gap, next - gap); - if (r == -EOPNOTSUPP) { - if (p) -- log_info("Storage does not support discarding, not discarding gap after partition %" PRIu64 ".", p->partno); -+ log_info("Storage does not support discard, not discarding gap after partition %" PRIu64 ".", p->partno); - else -- log_info("Storage does not support discarding, not discarding gap at beginning of disk."); -+ log_info("Storage does not support discard, not discarding gap at beginning of disk."); - return 0; - } - if (r == 0) /* Too short */ -@@ -2115,17 +2339,15 @@ static int context_wipe_and_discard(Context *context, bool from_scratch) { - if (!p->allocated_to_area) - continue; - -- if (!from_scratch) { -- r = context_discard_partition(context, p); -- if (r < 0) -- return r; -- } -- - r = context_wipe_partition(context, p); - if (r < 0) - return r; - - if (!from_scratch) { -+ r = context_discard_partition(context, p); -+ if (r < 0) -+ return r; -+ - r = context_discard_gap_after(context, p); - if (r < 0) - return r; -@@ -2141,16 +2363,143 @@ static int context_wipe_and_discard(Context *context, bool from_scratch) { - return 0; - } - -+static int partition_encrypt( -+ Partition *p, -+ const char *node, -+ struct crypt_device **ret_cd, -+ char **ret_volume, -+ int *ret_fd) { -+ -+ _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; -+ _cleanup_(erase_and_freep) void *volume_key = NULL; -+ _cleanup_free_ char *dm_name = NULL, *vol = NULL; -+ char suuid[ID128_UUID_STRING_MAX]; -+ size_t volume_key_size = 256 / 8; -+ sd_id128_t uuid; -+ int r; -+ -+ assert(p); -+ assert(p->encrypt); -+ -+ r = dlopen_cryptsetup(); -+ if (r < 0) -+ return log_error_errno(r, "libcryptsetup not found, cannot encrypt: %m"); -+ -+ if (asprintf(&dm_name, "luks-repart-%08" PRIx64, random_u64()) < 0) -+ return log_oom(); -+ -+ if (ret_volume) { -+ vol = path_join("/dev/mapper/", dm_name); -+ if (!vol) -+ return log_oom(); -+ } -+ -+ r = derive_uuid(p->new_uuid, "luks-uuid", &uuid); -+ if (r < 0) -+ return r; -+ -+ log_info("Encrypting future partition %" PRIu64 "...", p->partno); -+ -+ volume_key = malloc(volume_key_size); -+ if (!volume_key) -+ return log_oom(); -+ -+ r = genuine_random_bytes(volume_key, volume_key_size, RANDOM_BLOCK); -+ if (r < 0) -+ return log_error_errno(r, "Failed to generate volume key: %m"); -+ -+ r = sym_crypt_init(&cd, node); -+ if (r < 0) -+ return log_error_errno(r, "Failed to allocate libcryptsetup context: %m"); -+ -+ cryptsetup_enable_logging(cd); -+ -+ r = sym_crypt_format(cd, -+ CRYPT_LUKS2, -+ "aes", -+ "xts-plain64", -+ id128_to_uuid_string(uuid, suuid), -+ volume_key, -+ volume_key_size, -+ &(struct crypt_params_luks2) { -+ .label = p->new_label, -+ .sector_size = 512U, -+ }); -+ if (r < 0) -+ return log_error_errno(r, "Failed to LUKS2 format future partition: %m"); -+ -+ r = sym_crypt_keyslot_add_by_volume_key( -+ cd, -+ CRYPT_ANY_SLOT, -+ volume_key, -+ volume_key_size, -+ strempty(arg_key), -+ arg_key_size); -+ if (r < 0) -+ return log_error_errno(r, "Failed to add LUKS2 key: %m"); -+ -+ r = sym_crypt_activate_by_volume_key( -+ cd, -+ dm_name, -+ volume_key, -+ volume_key_size, -+ arg_discard ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0); -+ if (r < 0) -+ return log_error_errno(r, "Failed to activate LUKS superblock: %m"); -+ -+ log_info("Successfully encrypted future partition %" PRIu64 ".", p->partno); -+ -+ if (ret_fd) { -+ _cleanup_close_ int dev_fd = -1; -+ -+ dev_fd = open(vol, O_RDWR|O_CLOEXEC|O_NOCTTY); -+ if (dev_fd < 0) -+ return log_error_errno(errno, "Failed to open LUKS volume '%s': %m", vol); -+ -+ *ret_fd = TAKE_FD(dev_fd); -+ } -+ -+ if (ret_cd) -+ *ret_cd = TAKE_PTR(cd); -+ if (ret_volume) -+ *ret_volume = TAKE_PTR(vol); -+ -+ return 0; -+} -+ -+static int deactivate_luks(struct crypt_device *cd, const char *node) { -+ int r; -+ -+ if (!cd) -+ return 0; -+ -+ assert(node); -+ -+ /* udev or so might access out block device in the background while we are done. Let's hence force -+ * detach the volume. We sync'ed before, hence this should be safe. */ -+ -+ r = sym_crypt_deactivate_by_name(cd, basename(node), CRYPT_DEACTIVATE_FORCE); -+ if (r < 0) -+ return log_error_errno(r, "Failed to deactivate LUKS device: %m"); -+ -+ return 1; -+} -+ - static int context_copy_blocks(Context *context) { - Partition *p; -- int fd = -1, r; -+ int whole_fd = -1, r; - - assert(context); - - /* Copy in file systems on the block level */ - - LIST_FOREACH(partitions, p, context->partitions) { -+ _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; -+ _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; -+ _cleanup_free_ char *encrypted = NULL; -+ _cleanup_close_ int encrypted_dev_fd = -1; - char buf[FORMAT_BYTES_MAX]; -+ int target_fd; - - if (p->copy_blocks_fd < 0) - continue; -@@ -2165,24 +2514,297 @@ static int context_copy_blocks(Context *context) { - assert(p->copy_blocks_size != UINT64_MAX); - assert(p->new_size >= p->copy_blocks_size); - -- if (fd < 0) -- assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0); -+ if (whole_fd < 0) -+ assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0); - -- if (lseek(fd, p->offset, SEEK_SET) == (off_t) -1) -- return log_error_errno(errno, "Failed to seek to partition offset: %m"); -+ if (p->encrypt) { -+ r = loop_device_make(whole_fd, O_RDWR, p->offset, p->new_size, 0, &d); -+ if (r < 0) -+ return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno); - -- log_info("Copying in '%s' (%s) on block level into partition %" PRIu64 ".", p->copy_blocks_path, format_bytes(buf, sizeof(buf), p->copy_blocks_size), p->partno); -+ r = loop_device_flock(d, LOCK_EX); -+ if (r < 0) -+ return log_error_errno(r, "Failed to lock loopback device: %m"); - -- r = copy_bytes_full(p->copy_blocks_fd, fd, p->copy_blocks_size, 0, NULL, NULL, NULL, NULL); -+ r = partition_encrypt(p, d->node, &cd, &encrypted, &encrypted_dev_fd); -+ if (r < 0) -+ return log_error_errno(r, "Failed to encrypt device: %m"); -+ -+ if (flock(encrypted_dev_fd, LOCK_EX) < 0) -+ return log_error_errno(errno, "Failed to lock LUKS device: %m"); -+ -+ target_fd = encrypted_dev_fd; -+ } else { -+ if (lseek(whole_fd, p->offset, SEEK_SET) == (off_t) -1) -+ return log_error_errno(errno, "Failed to seek to partition offset: %m"); -+ -+ target_fd = whole_fd; -+ } -+ -+ log_info("Copying in '%s' (%s) on block level into future partition %" PRIu64 ".", p->copy_blocks_path, format_bytes(buf, sizeof(buf), p->copy_blocks_size), p->partno); -+ -+ r = copy_bytes_full(p->copy_blocks_fd, target_fd, p->copy_blocks_size, 0, NULL, NULL, NULL, NULL); - if (r < 0) - return log_error_errno(r, "Failed to copy in data from '%s': %m", p->copy_blocks_path); - -+ if (fsync(target_fd) < 0) -+ return log_error_errno(r, "Failed to synchronize copied data blocks: %m"); -+ -+ if (p->encrypt) { -+ encrypted_dev_fd = safe_close(encrypted_dev_fd); -+ -+ r = deactivate_luks(cd, encrypted); -+ if (r < 0) -+ return r; -+ -+ sym_crypt_free(cd); -+ cd = NULL; -+ -+ r = loop_device_sync(d); -+ if (r < 0) -+ return log_error_errno(r, "Failed to sync loopback device: %m"); -+ } -+ - log_info("Copying in of '%s' on block level completed.", p->copy_blocks_path); - } - - return 0; - } - -+static int do_copy_files(Partition *p, const char *fs) { -+ char **source, **target; -+ int r; -+ -+ assert(p); -+ assert(fs); -+ -+ STRV_FOREACH_PAIR(source, target, p->copy_files) { -+ _cleanup_close_ int sfd = -1, pfd = -1, tfd = -1; -+ _cleanup_free_ char *dn = NULL; -+ -+ dn = dirname_malloc(*target); -+ if (!dn) -+ return log_oom(); -+ -+ sfd = chase_symlinks_and_open(*source, arg_root, CHASE_PREFIX_ROOT|CHASE_WARN, O_CLOEXEC|O_NOCTTY, NULL); -+ if (sfd < 0) -+ return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_root), *source); -+ -+ r = fd_verify_regular(sfd); -+ if (r < 0) { -+ if (r != -EISDIR) -+ return log_error_errno(r, "Failed to check type of source file '%s': %m", *source); -+ -+ /* We are looking at a directory */ -+ tfd = chase_symlinks_and_open(*target, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL); -+ if (tfd < 0) { -+ if (tfd != -ENOENT) -+ return log_error_errno(tfd, "Failed to open target directory '%s': %m", *target); -+ -+ r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755); -+ if (r < 0) -+ return log_error_errno(r, "Failed to create parent directory '%s': %m", dn); -+ -+ pfd = chase_symlinks_and_open(dn, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL); -+ if (pfd < 0) -+ return log_error_errno(pfd, "Failed to open parent directory of target: %m"); -+ -+ r = copy_tree_at( -+ sfd, ".", -+ pfd, basename(*target), -+ UID_INVALID, GID_INVALID, -+ COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS); -+ } else -+ r = copy_tree_at( -+ sfd, ".", -+ tfd, ".", -+ UID_INVALID, GID_INVALID, -+ COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS); -+ if (r < 0) -+ return log_error_errno(r, "Failed to copy %s%s to %s: %m", strempty(arg_root), *source, *target); -+ } else { -+ /* We are looking at a regular file */ -+ -+ r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755); -+ if (r < 0) -+ return log_error_errno(r, "Failed to create parent directory: %m"); -+ -+ pfd = chase_symlinks_and_open(dn, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL); -+ if (pfd < 0) -+ return log_error_errno(tfd, "Failed to open parent directory of target: %m"); -+ -+ tfd = openat(pfd, basename(*target), O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC, 0700); -+ if (tfd < 0) -+ return log_error_errno(errno, "Failed to create target file '%s': %m", *target); -+ -+ r = copy_bytes(sfd, tfd, UINT64_MAX, COPY_REFLINK|COPY_SIGINT); -+ if (r < 0) -+ return log_error_errno(r, "Failed to copy '%s%s' to '%s': %m", strempty(arg_root), *source, *target); -+ -+ (void) copy_xattr(sfd, tfd); -+ (void) copy_access(sfd, tfd); -+ (void) copy_times(sfd, tfd, 0); -+ } -+ } -+ -+ return 0; -+} -+ -+static int partition_copy_files(Partition *p, const char *node) { -+ int r; -+ -+ assert(p); -+ assert(node); -+ -+ if (strv_isempty(p->copy_files)) -+ return 0; -+ -+ log_info("Populating partition %" PRIu64 " with files.", p->partno); -+ -+ /* We copy in a child process, since we have to mount the fs for that, and we don't want that fs to -+ * appear in the host namespace. Hence we fork a child that has its own file system namespace and -+ * detached mount propagation. */ -+ -+ r = safe_fork("(sd-copy)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL); -+ if (r < 0) -+ return r; -+ if (r == 0) { -+ static const char fs[] = "/run/systemd/mount-root"; -+ /* This is a child process with its own mount namespace and propagation to host turned off */ -+ -+ r = mkdir_p(fs, 0700); -+ if (r < 0) { -+ log_error_errno(r, "Failed to create mount point: %m"); -+ _exit(EXIT_FAILURE); -+ } -+ -+ if (mount_verbose(LOG_ERR, node, fs, p->format, MS_NOATIME|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0) -+ _exit(EXIT_FAILURE); -+ -+ if (do_copy_files(p, fs) < 0) -+ _exit(EXIT_FAILURE); -+ -+ r = syncfs_path(AT_FDCWD, fs); -+ if (r < 0) { -+ log_error_errno(r, "Failed to synchronize written files: %m"); -+ _exit(EXIT_FAILURE); -+ } -+ -+ _exit(EXIT_SUCCESS); -+ } -+ -+ log_info("Successfully populated partition %" PRIu64 " with files.", p->partno); -+ return 0; -+} -+ -+static int context_mkfs(Context *context) { -+ Partition *p; -+ int fd = -1, r; -+ -+ assert(context); -+ -+ /* Make a file system */ -+ -+ LIST_FOREACH(partitions, p, context->partitions) { -+ _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; -+ _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; -+ _cleanup_free_ char *encrypted = NULL; -+ _cleanup_close_ int encrypted_dev_fd = -1; -+ const char *fsdev; -+ sd_id128_t fs_uuid; -+ -+ if (p->dropped) -+ continue; -+ -+ if (PARTITION_EXISTS(p)) /* Never format existing partitions */ -+ continue; -+ -+ if (!p->format) -+ continue; -+ -+ assert(p->offset != UINT64_MAX); -+ assert(p->new_size != UINT64_MAX); -+ -+ if (fd < 0) -+ assert_se((fd = fdisk_get_devfd(context->fdisk_context)) >= 0); -+ -+ /* Loopback block devices are not only useful to turn regular files into block devices, but -+ * also to cut out sections of block devices into new block devices. */ -+ -+ r = loop_device_make(fd, O_RDWR, p->offset, p->new_size, 0, &d); -+ if (r < 0) -+ return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno); -+ -+ r = loop_device_flock(d, LOCK_EX); -+ if (r < 0) -+ return log_error_errno(r, "Failed to lock loopback device: %m"); -+ -+ if (p->encrypt) { -+ r = partition_encrypt(p, d->node, &cd, &encrypted, &encrypted_dev_fd); -+ if (r < 0) -+ return log_error_errno(r, "Failed to encrypt device: %m"); -+ -+ if (flock(encrypted_dev_fd, LOCK_EX) < 0) -+ return log_error_errno(errno, "Failed to lock LUKS device: %m"); -+ -+ fsdev = encrypted; -+ } else -+ fsdev = d->node; -+ -+ log_info("Formatting future partition %" PRIu64 ".", p->partno); -+ -+ /* Calculate the UUID for the file system as HMAC-SHA256 of the string "file-system-uuid", -+ * keyed off the partition UUID. */ -+ r = derive_uuid(p->new_uuid, "file-system-uuid", &fs_uuid); -+ if (r < 0) -+ return r; -+ -+ r = make_filesystem(fsdev, p->format, p->new_label, fs_uuid, arg_discard); -+ if (r < 0) { -+ encrypted_dev_fd = safe_close(encrypted_dev_fd); -+ (void) deactivate_luks(cd, encrypted); -+ return r; -+ } -+ -+ log_info("Successfully formatted future partition %" PRIu64 ".", p->partno); -+ -+ /* The file system is now created, no need to delay udev further */ -+ if (p->encrypt) -+ if (flock(encrypted_dev_fd, LOCK_UN) < 0) -+ return log_error_errno(errno, "Failed to unlock LUKS device: %m"); -+ -+ r = partition_copy_files(p, fsdev); -+ if (r < 0) { -+ encrypted_dev_fd = safe_close(encrypted_dev_fd); -+ (void) deactivate_luks(cd, encrypted); -+ return r; -+ } -+ -+ /* Note that we always sync explicitly here, since mkfs.fat doesn't do that on its own, and -+ * if we don't sync before detaching a block device the in-flight sectors possibly won't hit -+ * the disk. */ -+ -+ if (p->encrypt) { -+ if (fsync(encrypted_dev_fd) < 0) -+ return log_error_errno(r, "Failed to synchronize LUKS volume: %m"); -+ encrypted_dev_fd = safe_close(encrypted_dev_fd); -+ -+ r = deactivate_luks(cd, encrypted); -+ if (r < 0) -+ return r; -+ -+ sym_crypt_free(cd); -+ cd = NULL; -+ } -+ -+ r = loop_device_sync(d); -+ if (r < 0) -+ return log_error_errno(r, "Failed to sync loopback device: %m"); -+ } -+ -+ return 0; -+} -+ - static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *ret) { - struct { - sd_id128_t type_uuid; -@@ -2387,68 +3009,12 @@ static int device_kernel_partitions_supported(int fd) { - return FLAGS_SET(info.lo_flags, LO_FLAGS_PARTSCAN); - } - --static int context_write_partition_table( -- Context *context, -- const char *node, -- bool from_scratch) { -- -- _cleanup_(fdisk_unref_tablep) struct fdisk_table *original_table = NULL; -- int capable, r; -+static int context_mangle_partitions(Context *context) { - Partition *p; -+ int r; - - assert(context); - -- if (arg_pretty > 0 || -- (arg_pretty < 0 && isatty(STDOUT_FILENO) > 0)) { -- -- if (context->n_partitions == 0) -- puts("Empty partition table."); -- else -- (void) context_dump_partitions(context, node); -- -- putc('\n', stdout); -- -- (void) context_dump_partition_bar(context, node); -- putc('\n', stdout); -- fflush(stdout); -- } -- -- if (!from_scratch && !context_changed(context)) { -- log_info("No changes."); -- return 0; -- } -- -- if (arg_dry_run) { -- log_notice("Refusing to repartition, please re-run with --dry-run=no."); -- return 0; -- } -- -- log_info("Applying changes."); -- -- if (from_scratch) { -- r = context_discard_range(context, 0, context->total); -- if (r == -EOPNOTSUPP) -- log_info("Storage does not support discarding, not discarding entire block device data."); -- else if (r < 0) -- return log_error_errno(r, "Failed to discard entire block device: %m"); -- else if (r > 0) -- log_info("Discarded entire block device."); -- } -- -- r = fdisk_get_partitions(context->fdisk_context, &original_table); -- if (r < 0) -- return log_error_errno(r, "Failed to acquire partition table: %m"); -- -- /* Wipe fs signatures and discard sectors where the new partitions are going to be placed and in the -- * gaps between partitions, just to be sure. */ -- r = context_wipe_and_discard(context, from_scratch); -- if (r < 0) -- return r; -- -- r = context_copy_blocks(context); -- if (r < 0) -- return r; -- - LIST_FOREACH(partitions, p, context->partitions) { - if (p->dropped) - continue; -@@ -2560,7 +3126,7 @@ static int context_write_partition_table( - if (r < 0) - return log_error_errno(r, "Failed to set partition label: %m"); - -- log_info("Creating new partition %" PRIu64 ".", p->partno); -+ log_info("Adding new partition %" PRIu64 " to partition table.", p->partno); - - r = fdisk_add_partition(context->fdisk_context, q, NULL); - if (r < 0) -@@ -2571,6 +3137,83 @@ static int context_write_partition_table( - } - } - -+ return 0; -+} -+ -+static int context_write_partition_table( -+ Context *context, -+ const char *node, -+ bool from_scratch) { -+ -+ _cleanup_(fdisk_unref_tablep) struct fdisk_table *original_table = NULL; -+ int capable, r; -+ -+ assert(context); -+ -+ if (arg_pretty > 0 || -+ (arg_pretty < 0 && isatty(STDOUT_FILENO) > 0) || -+ arg_json) { -+ -+ (void) context_dump_partitions(context, node); -+ -+ putc('\n', stdout); -+ -+ if (!arg_json) -+ (void) context_dump_partition_bar(context, node); -+ putc('\n', stdout); -+ fflush(stdout); -+ } -+ -+ if (!from_scratch && !context_changed(context)) { -+ log_info("No changes."); -+ return 0; -+ } -+ -+ if (arg_dry_run) { -+ log_notice("Refusing to repartition, please re-run with --dry-run=no."); -+ return 0; -+ } -+ -+ log_info("Applying changes."); -+ -+ if (from_scratch) { -+ r = context_wipe_range(context, 0, context->total); -+ if (r < 0) -+ return r; -+ -+ log_info("Wiped block device."); -+ -+ r = context_discard_range(context, 0, context->total); -+ if (r == -EOPNOTSUPP) -+ log_info("Storage does not support discard, not discarding entire block device data."); -+ else if (r < 0) -+ return log_error_errno(r, "Failed to discard entire block device: %m"); -+ else if (r > 0) -+ log_info("Discarded entire block device."); -+ } -+ -+ r = fdisk_get_partitions(context->fdisk_context, &original_table); -+ if (r < 0) -+ return log_error_errno(r, "Failed to acquire partition table: %m"); -+ -+ /* Wipe fs signatures and discard sectors where the new partitions are going to be placed and in the -+ * gaps between partitions, just to be sure. */ -+ r = context_wipe_and_discard(context, from_scratch); -+ if (r < 0) -+ return r; -+ -+ r = context_copy_blocks(context); -+ if (r < 0) -+ return r; -+ -+ r = context_mkfs(context); -+ if (r < 0) -+ return r; -+ -+ r = context_mangle_partitions(context); -+ if (r < 0) -+ return r; -+ - log_info("Writing new partition table."); - - r = fdisk_write_disklabel(context->fdisk_context); -@@ -2734,6 +3377,8 @@ static int context_open_copy_block_paths(Context *context) { - /* Special support for btrfs */ - - r = btrfs_get_block_device_fd(source_fd, &devt); -+ if (r == -EUCLEAN) -+ return btrfs_log_dev_root(LOG_ERR, r, p->copy_blocks_path); - if (r < 0) - return log_error_errno(r, "Unable to determine backing block device of '%s': %m", p->copy_blocks_path); - -@@ -2791,14 +3436,17 @@ static int help(void) { - " --empty=MODE One of refuse, allow, require, force, create; controls\n" - " how to handle empty disks lacking partition tables\n" - " --discard=BOOL Whether to discard backing blocks for new partitions\n" -- " --pretty=BOOL Whether to show pretty summary before executing operation\n" -+ " --pretty=BOOL Whether to show pretty summary before doing changes\n" - " --factory-reset=BOOL Whether to remove data partitions before recreating\n" - " them\n" - " --can-factory-reset Test whether factory reset is defined\n" - " --root=PATH Operate relative to root path\n" - " --definitions=DIR Find partitions in specified directory\n" -+ " --key-file=PATH Key to use when encrypting partitions\n" - " --seed=UUID 128bit seed UUID to derive all UUIDs from\n" - " --size=BYTES Grow loopback file to specified size\n" -+ " --json=pretty|short|off\n" -+ " Generate JSON output\n" - "\nSee the %s for details.\n" - , program_invocation_short_name - , ansi_highlight(), ansi_normal() -@@ -2822,6 +3470,8 @@ static int parse_argv(int argc, char *argv[]) { - ARG_PRETTY, - ARG_DEFINITIONS, - ARG_SIZE, -+ ARG_JSON, -+ ARG_KEY_FILE, - }; - - static const struct option options[] = { -@@ -2837,6 +3487,8 @@ static int parse_argv(int argc, char *argv[]) { - { "pretty", required_argument, NULL, ARG_PRETTY }, - { "definitions", required_argument, NULL, ARG_DEFINITIONS }, - { "size", required_argument, NULL, ARG_SIZE }, -+ { "json", required_argument, NULL, ARG_JSON }, -+ { "key-file", required_argument, NULL, ARG_KEY_FILE }, - {} - }; - -@@ -2943,6 +3595,12 @@ static int parse_argv(int argc, char *argv[]) { - case ARG_SIZE: { - uint64_t parsed, rounded; - -+ if (streq(optarg, "auto")) { -+ arg_size = UINT64_MAX; -+ arg_size_auto = true; -+ break; -+ } -+ - r = parse_size(optarg, 1024, &parsed); - if (r < 0) - return log_error_errno(r, "Failed to parse --size= parameter: %s", optarg); -@@ -2958,6 +3616,41 @@ static int parse_argv(int argc, char *argv[]) { - parsed, rounded); - - arg_size = rounded; -+ arg_size_auto = false; -+ break; -+ } -+ -+ case ARG_JSON: -+ if (streq(optarg, "pretty")) { -+ arg_json = true; -+ arg_json_format_flags = JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR_AUTO; -+ } else if (streq(optarg, "short")) { -+ arg_json = true; -+ arg_json_format_flags = JSON_FORMAT_NEWLINE; -+ } else if (streq(optarg, "off")) { -+ arg_json = false; -+ arg_json_format_flags = 0; -+ } else if (streq(optarg, "help")) { -+ puts("pretty\n" -+ "short\n" -+ "off"); -+ return 0; -+ } else -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown argument to --json=: %s", optarg); -+ -+ break; -+ -+ case ARG_KEY_FILE: { -+ _cleanup_(erase_and_freep) char *k = NULL; -+ size_t n = 0; -+ -+ r = read_full_file_full(AT_FDCWD, optarg, READ_FULL_FILE_SECURE|READ_FULL_FILE_CONNECT_SOCKET, &k, &n); -+ if (r < 0) -+ return log_error_errno(r, "Failed to read key file '%s': %m", optarg); -+ -+ erase_and_free(arg_key); -+ arg_key = TAKE_PTR(k); -+ arg_key_size = n; - break; - } - -@@ -2983,7 +3676,7 @@ static int parse_argv(int argc, char *argv[]) { - else if (dry_run >= 0) - arg_dry_run = dry_run; - -- if (arg_empty == EMPTY_CREATE && arg_size == UINT64_MAX) -+ if (arg_empty == EMPTY_CREATE && (arg_size == UINT64_MAX && !arg_size_auto)) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "If --empty=create is specified, --size= must be specified, too."); - -@@ -3140,7 +3833,7 @@ static int find_root(char **ret, int *ret_fd) { - if (!s) - return log_oom(); - -- fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0777); -+ fd = open(arg_node, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOFOLLOW, 0666); - if (fd < 0) - return log_error_errno(errno, "Failed to create '%s': %m", arg_node); - -@@ -3150,8 +3843,10 @@ static int find_root(char **ret, int *ret_fd) { - } - - r = acquire_root_devno(arg_node, O_RDONLY|O_CLOEXEC, ret, ret_fd); -+ if (r == -EUCLEAN) -+ return btrfs_log_dev_root(LOG_ERR, r, arg_node); - if (r < 0) -- return log_error_errno(r, "Failed to determine backing device of %s: %m", arg_node); -+ return log_error_errno(r, "Failed to open file or determine backing device of %s: %m", arg_node); - - return 0; - } -@@ -3177,6 +3872,8 @@ static int find_root(char **ret, int *ret_fd) { - - r = acquire_root_devno(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC, ret, ret_fd); - if (r < 0) { -+ if (r == -EUCLEAN) -+ return btrfs_log_dev_root(LOG_ERR, r, p); - if (r != -ENODEV) - return log_error_errno(r, "Failed to determine backing device of %s: %m", p); - } else -@@ -3259,6 +3956,35 @@ static int resize_backing_fd(const char *node, int *fd) { - return 1; - } - -+static int determine_auto_size(Context *c) { -+ uint64_t sum = round_up_size(GPT_METADATA_SIZE, 4096); -+ char buf[FORMAT_BYTES_MAX]; -+ Partition *p; -+ -+ assert_se(c); -+ assert_se(arg_size == UINT64_MAX); -+ assert_se(arg_size_auto); -+ -+ LIST_FOREACH(partitions, p, c->partitions) { -+ uint64_t m; -+ -+ if (p->dropped) -+ continue; -+ -+ m = partition_min_size_with_padding(p); -+ if (m > UINT64_MAX - sum) -+ return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "Image would grow too large, refusing."); -+ -+ sum += m; -+ } -+ -+ assert_se(format_bytes(buf, sizeof(buf), sum)); -+ log_info("Automatically determined minimal disk image size as %s.", buf); -+ -+ arg_size = sum; -+ return 0; -+} -+ - static int run(int argc, char *argv[]) { - _cleanup_(context_freep) Context* context = NULL; - _cleanup_free_ char *node = NULL; -@@ -3360,6 +4086,24 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return r; - -+ if (arg_size_auto) { -+ r = determine_auto_size(context); -+ if (r < 0) -+ return r; -+ -+ /* Flush out everything again, and let's grow the file first, then start fresh */ -+ context_unload_partition_table(context); -+ -+ assert_se(arg_size != UINT64_MAX); -+ r = resize_backing_fd(node, &backing_fd); -+ if (r < 0) -+ return r; -+ -+ r = context_load_partition_table(context, node, &backing_fd); -+ if (r < 0) -+ return r; -+ } -+ - /* First try to fit new partitions in, dropping by priority until it fits */ - for (;;) { - if (context_allocate_partitions(context)) -diff --git a/src/partition/test-repart.sh b/src/partition/test-repart.sh -index bfb9bcb..5765978 100755 ---- a/src/partition/test-repart.sh -+++ b/src/partition/test-repart.sh -@@ -1,6 +1,8 @@ - #!/usr/bin/env bash - set -ex - -+[[ -f /dev/loop-control ]] || exit 77 -+ - repart=$1 - test -x $repart - -@@ -10,6 +12,8 @@ mkdir -p $D/definitions - - SEED=e2a40bf9-73f1-4278-9160-49c031e7aef8 - -+echo "### Testing systemd-repart --empty=create ###" -+ - $repart $D/zzz --empty=create --size=1G --seed=$SEED - - sfdisk -d $D/zzz | grep -v -e 'sector-size' -e '^$' >$D/empty -@@ -23,6 +27,8 @@ first-lba: 2048 - last-lba: 2097118 - EOF - -+echo "### Testing with root, root2, home, & swap ###" -+ - cat >$D/definitions/root.conf <$D/definitions/swap.conf <$D/populated3 -@@ -115,6 +125,8 @@ EOF - - dd if=/dev/urandom of=$D/block-copy bs=4096 count=10240 - -+echo "### Testing with root, root2, home, swap, another partition, & partition copy ###" -+ - cat >$D/definitions/extra2.conf < /dev/null ; then -+ echo "### Testing Format=/Encrypt=/CopyFiles=" -+ -+ # These tests require privileges unfortunately -+ -+ cat >$D/definitions/extra3.conf <$D/populated5 -+ -+ cmp $D/populated5 - < /dev/null -+ umount $D/mount -+ cryptsetup close $VOLUME -+ losetup -d $LOOP -+else -+ echo "### Skipping Format=/Encrypt=/CopyFiles= test, lacking privileges or missing cryptsetup/diff/losetup" -+fi -+ -+echo "### Testing json output ###" -+$repart $D/zzz --size=3G --dry-run=no --seed=$SEED --definitions=$D/definitions --json=help -+$repart $D/zzz --size=3G --dry-run=no --seed=$SEED --definitions=$D/definitions --json=pretty -+$repart $D/zzz --size=3G --dry-run=no --seed=$SEED --definitions=$D/definitions --json=short -diff --git a/src/portable/portable.c b/src/portable/portable.c -index 3a1367e..e55a811 100644 ---- a/src/portable/portable.c -+++ b/src/portable/portable.c -@@ -103,7 +103,6 @@ static int compare_metadata(PortableMetadata *const *x, PortableMetadata *const - int portable_metadata_hashmap_to_sorted_array(Hashmap *unit_files, PortableMetadata ***ret) { - - _cleanup_free_ PortableMetadata **sorted = NULL; -- Iterator iterator; - PortableMetadata *item; - size_t k = 0; - -@@ -111,7 +110,7 @@ int portable_metadata_hashmap_to_sorted_array(Hashmap *unit_files, PortableMetad - if (!sorted) - return -ENOMEM; - -- HASHMAP_FOREACH(item, unit_files, iterator) -+ HASHMAP_FOREACH(item, unit_files) - sorted[k++] = item; - - assert(k == hashmap_size(unit_files)); -@@ -380,7 +379,7 @@ static int portable_extract_by_path( - if (r < 0) - return log_debug_errno(r, "Failed to create temporary directory: %m"); - -- r = dissect_image(d->fd, NULL, 0, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK, &m); -+ r = dissect_image(d->fd, NULL, 0, NULL, NULL, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK, &m); - if (r == -ENOPKG) - sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't identify a suitable partition table or file system in '%s'.", path); - else if (r == -EADDRNOTAVAIL) -@@ -987,7 +986,6 @@ int portable_attach( - _cleanup_(lookup_paths_free) LookupPaths paths = {}; - _cleanup_(image_unrefp) Image *image = NULL; - PortableMetadata *item; -- Iterator iterator; - int r; - - assert(name_or_path); -@@ -1004,7 +1002,7 @@ int portable_attach( - if (r < 0) - return r; - -- HASHMAP_FOREACH(item, unit_files, iterator) { -+ HASHMAP_FOREACH(item, unit_files) { - r = unit_file_exists(UNIT_FILE_SYSTEM, &paths, item->name); - if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name); -@@ -1018,7 +1016,7 @@ int portable_attach( - return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active already, refusing.", item->name); - } - -- HASHMAP_FOREACH(item, unit_files, iterator) { -+ HASHMAP_FOREACH(item, unit_files) { - r = attach_unit_file(&paths, image->path, image->type, item, profile, flags, changes, n_changes); - if (r < 0) - return r; -@@ -1140,7 +1138,6 @@ int portable_detach( - _cleanup_set_free_ Set *unit_files = NULL, *markers = NULL; - _cleanup_closedir_ DIR *d = NULL; - const char *where, *item; -- Iterator iterator; - struct dirent *de; - int ret = 0; - int r; -@@ -1210,7 +1207,7 @@ int portable_detach( - if (set_isempty(unit_files)) - goto not_found; - -- SET_FOREACH(item, unit_files, iterator) { -+ SET_FOREACH(item, unit_files) { - _cleanup_free_ char *md = NULL; - const char *suffix; - -@@ -1252,7 +1249,7 @@ int portable_detach( - } - - /* Now, also drop any image symlink, for images outside of the sarch path */ -- SET_FOREACH(item, markers, iterator) { -+ SET_FOREACH(item, markers) { - _cleanup_free_ char *sl = NULL; - struct stat st; - -diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c -index aa63698..4369dfd 100644 ---- a/src/portable/portablectl.c -+++ b/src/portable/portablectl.c -@@ -392,6 +392,7 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_strv_free_ char **names = NULL; - UnitFileChange *changes = NULL; -+ const uint64_t flags = UNIT_FILE_PORTABLE | (arg_runtime ? UNIT_FILE_RUNTIME : 0); - size_t n_changes = 0; - int r; - -@@ -408,7 +409,7 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) { - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", -- enable ? "EnableUnitFiles" : "DisableUnitFiles"); -+ enable ? "EnableUnitFilesWithFlags" : "DisableUnitFilesWithFlags"); - if (r < 0) - return bus_log_create_error(r); - -@@ -416,16 +417,10 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) { - if (r < 0) - return bus_log_create_error(r); - -- r = sd_bus_message_append(m, "b", arg_runtime); -+ r = sd_bus_message_append(m, "t", flags); - if (r < 0) - return bus_log_create_error(r); - -- if (enable) { -- r = sd_bus_message_append(m, "b", false); -- if (r < 0) -- return bus_log_create_error(r); -- } -- - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) - return log_error_errno(r, "Failed to %s the portable service %s: %s", -diff --git a/src/portable/portabled-bus.c b/src/portable/portabled-bus.c -index 0fa0543..0169dcb 100644 ---- a/src/portable/portabled-bus.c -+++ b/src/portable/portabled-bus.c -@@ -135,7 +135,6 @@ static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_er - _cleanup_hashmap_free_ Hashmap *images = NULL; - Manager *m = userdata; - Image *image; -- Iterator i; - int r; - - assert(message); -@@ -157,7 +156,7 @@ static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_er - if (r < 0) - return r; - -- HASHMAP_FOREACH(image, images, i) { -+ HASHMAP_FOREACH(image, images) { - _cleanup_(sd_bus_error_free) sd_bus_error error_state = SD_BUS_ERROR_NULL; - PortableState state = _PORTABLE_STATE_INVALID; - _cleanup_free_ char *p = NULL; -diff --git a/src/portable/portabled-image-bus.c b/src/portable/portabled-image-bus.c -index 9646601..b9914f5 100644 ---- a/src/portable/portabled-image-bus.c -+++ b/src/portable/portabled-image-bus.c -@@ -704,7 +704,6 @@ int bus_image_node_enumerator(sd_bus *bus, const char *path, void *userdata, cha - size_t n_allocated = 0, n = 0; - Manager *m = userdata; - Image *image; -- Iterator i; - int r; - - assert(bus); -@@ -719,7 +718,7 @@ int bus_image_node_enumerator(sd_bus *bus, const char *path, void *userdata, cha - if (r < 0) - return r; - -- HASHMAP_FOREACH(image, images, i) { -+ HASHMAP_FOREACH(image, images) { - char *p; - - r = bus_image_path(image, &p); -diff --git a/src/portable/portabled-image.c b/src/portable/portabled-image.c -index d95845b..e498ba3 100644 ---- a/src/portable/portabled-image.c -+++ b/src/portable/portabled-image.c -@@ -85,7 +85,6 @@ int manager_image_cache_add(Manager *m, Image *image) { - - int manager_image_cache_discover(Manager *m, Hashmap *images, sd_bus_error *error) { - Image *image; -- Iterator i; - int r; - - assert(m); -@@ -97,7 +96,7 @@ int manager_image_cache_discover(Manager *m, Hashmap *images, sd_bus_error *erro - if (r < 0) - return r; - -- HASHMAP_FOREACH(image, images, i) -+ HASHMAP_FOREACH(image, images) - (void) manager_image_cache_add(m, image); - - return 0; -diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c -index 908e627..75bb875 100644 ---- a/src/rc-local-generator/rc-local-generator.c -+++ b/src/rc-local-generator/rc-local-generator.c -@@ -59,7 +59,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) - - assert_se(arg_dest = dest); - -- if (check_executable(RC_LOCAL_SCRIPT_PATH_START) >= 0) { -+ if (check_executable(RC_LOCAL_PATH) >= 0) { - log_debug("Automatically adding rc-local.service."); - - r = add_symlink("rc-local.service", "multi-user.target"); -diff --git a/src/resolve/meson.build b/src/resolve/meson.build -index 92b67b6..da2256f 100644 ---- a/src/resolve/meson.build -+++ b/src/resolve/meson.build -@@ -17,53 +17,55 @@ basic_dns_sources = files(''' - dns_type_h = files('dns-type.h')[0] - - systemd_resolved_sources = files(''' -- resolved.c -- resolved-manager.c -- resolved-manager.h -- resolved-dnssd.c -- resolved-dnssd.h -- resolved-dnssd-bus.c -- resolved-dnssd-bus.h -- resolved-conf.c -- resolved-conf.h -- resolved-resolv-conf.c -- resolved-resolv-conf.h - resolved-bus.c - resolved-bus.h -- resolved-link.h -- resolved-link.c -- resolved-link-bus.c -- resolved-link-bus.h -- resolved-llmnr.h -- resolved-llmnr.c -- resolved-mdns.h -- resolved-mdns.c -+ resolved-conf.c -+ resolved-conf.h - resolved-def.h -- resolved-dns-query.h -+ resolved-dns-cache.c -+ resolved-dns-cache.h - resolved-dns-query.c -- resolved-dns-synthesize.h -- resolved-dns-synthesize.c -- resolved-dns-transaction.h -- resolved-dns-transaction.c -- resolved-dns-scope.h -+ resolved-dns-query.h - resolved-dns-scope.c -- resolved-dns-server.h -- resolved-dns-server.c -- resolved-dns-search-domain.h -+ resolved-dns-scope.h - resolved-dns-search-domain.c -- resolved-dns-cache.h -- resolved-dns-cache.c -- resolved-dns-zone.h -- resolved-dns-zone.c -- resolved-dns-stream.h -+ resolved-dns-search-domain.h -+ resolved-dns-server.c -+ resolved-dns-server.h - resolved-dns-stream.c -- resolved-dns-trust-anchor.h -- resolved-dns-trust-anchor.c -- resolved-dns-stub.h -+ resolved-dns-stream.h - resolved-dns-stub.c -- resolved-etc-hosts.h -- resolved-etc-hosts.c -+ resolved-dns-stub.h -+ resolved-dns-synthesize.c -+ resolved-dns-synthesize.h -+ resolved-dns-transaction.c -+ resolved-dns-transaction.h -+ resolved-dns-trust-anchor.c -+ resolved-dns-trust-anchor.h -+ resolved-dns-zone.c -+ resolved-dns-zone.h -+ resolved-dnssd-bus.c -+ resolved-dnssd-bus.h -+ resolved-dnssd.c -+ resolved-dnssd.h - resolved-dnstls.h -+ resolved-etc-hosts.c -+ resolved-etc-hosts.h -+ resolved-link-bus.c -+ resolved-link-bus.h -+ resolved-link.c -+ resolved-link.h -+ resolved-llmnr.c -+ resolved-llmnr.h -+ resolved-manager.c -+ resolved-manager.h -+ resolved-mdns.c -+ resolved-mdns.h -+ resolved-resolv-conf.c -+ resolved-resolv-conf.h -+ resolved-varlink.c -+ resolved-varlink.h -+ resolved.c - '''.split()) - - resolvectl_sources = files(''' -diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c -index 3072b98..8378ff5 100644 ---- a/src/resolve/resolvectl.c -+++ b/src/resolve/resolvectl.c -@@ -2545,6 +2545,7 @@ static int native_help(void) { - " dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode\n" - " nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA\n" - " revert LINK Revert per-interface configuration\n" -+ " log-level [LEVEL] Get/set logging threshold for systemd-resolved\n" - "\nOptions:\n" - " -h --help Show this help\n" - " --version Show package version\n" -diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c -index dba1639..b60a0fd 100644 ---- a/src/resolve/resolved-bus.c -+++ b/src/resolve/resolved-bus.c -@@ -24,45 +24,81 @@ - - BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support, resolve_support, ResolveSupport); - -+static int query_on_bus_track(sd_bus_track *t, void *userdata) { -+ DnsQuery *q = userdata; -+ -+ assert(t); -+ assert(q); -+ -+ if (!DNS_TRANSACTION_IS_LIVE(q->state)) -+ return 0; -+ -+ log_debug("Client of active query vanished, aborting query."); -+ dns_query_complete(q, DNS_TRANSACTION_ABORTED); -+ return 0; -+} -+ -+static int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) { -+ int r; -+ -+ assert(q); -+ assert(m); -+ -+ if (!q->bus_track) { -+ r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, query_on_bus_track, q); -+ if (r < 0) -+ return r; -+ } -+ -+ r = sd_bus_track_add_sender(q->bus_track, m); -+ if (r < 0) -+ return r; -+ -+ return 0; -+} -+ - static int reply_query_state(DnsQuery *q) { - -+ assert(q); -+ assert(q->bus_request); -+ - switch (q->state) { - - case DNS_TRANSACTION_NO_SERVERS: -- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); -+ return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); - - case DNS_TRANSACTION_TIMEOUT: -- return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out"); -+ return sd_bus_reply_method_errorf(q->bus_request, SD_BUS_ERROR_TIMEOUT, "Query timed out"); - - case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED: -- return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed"); -+ return sd_bus_reply_method_errorf(q->bus_request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed"); - - case DNS_TRANSACTION_INVALID_REPLY: -- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply"); -+ return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_INVALID_REPLY, "Received invalid reply"); - - case DNS_TRANSACTION_ERRNO: -- return sd_bus_reply_method_errnof(q->request, q->answer_errno, "Lookup failed due to system error: %m"); -+ return sd_bus_reply_method_errnof(q->bus_request, q->answer_errno, "Lookup failed due to system error: %m"); - - case DNS_TRANSACTION_ABORTED: -- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted"); -+ return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_ABORTED, "Query aborted"); - - case DNS_TRANSACTION_DNSSEC_FAILED: -- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s", -+ return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s", - dnssec_result_to_string(q->answer_dnssec_result)); - - case DNS_TRANSACTION_NO_TRUST_ANCHOR: -- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known"); -+ return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known"); - - case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED: -- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type"); -+ return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type"); - - case DNS_TRANSACTION_NETWORK_DOWN: -- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NETWORK_DOWN, "Network is down"); -+ return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NETWORK_DOWN, "Network is down"); - - case DNS_TRANSACTION_NOT_FOUND: - /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we - * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */ -- return sd_bus_reply_method_errorf(q->request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q)); -+ return sd_bus_reply_method_errorf(q->bus_request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q)); - - case DNS_TRANSACTION_RCODE_FAILURE: { - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -@@ -83,7 +119,7 @@ static int reply_query_state(DnsQuery *q) { - sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", dns_query_string(q), rc); - } - -- return sd_bus_reply_method_error(q->request, &error); -+ return sd_bus_reply_method_error(q->bus_request, &error); - } - - case DNS_TRANSACTION_NULL: -@@ -139,6 +175,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { - _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_free_ char *normalized = NULL; -+ DnsQuestion *question; - DnsResourceRecord *rr; - unsigned added = 0; - int ifindex, r; -@@ -152,7 +189,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { - - r = dns_query_process_cname(q); - if (r == -ELOOP) { -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); - goto finish; - } - if (r < 0) -@@ -160,7 +197,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { - if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ - return; - -- r = sd_bus_message_new_method_return(q->request, &reply); -+ r = sd_bus_message_new_method_return(q->bus_request, &reply); - if (r < 0) - goto finish; - -@@ -168,10 +205,9 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { - if (r < 0) - goto finish; - -- DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { -- DnsQuestion *question; -+ question = dns_query_question_for_protocol(q, q->answer_protocol); - -- question = dns_query_question_for_protocol(q, q->answer_protocol); -+ DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { - - r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); - if (r < 0) -@@ -190,7 +226,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { - } - - if (added <= 0) { -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); - goto finish; - } - -@@ -198,14 +234,14 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { - if (r < 0) - goto finish; - -- /* The key names are not necessarily normalized, make sure that they are when we return them to our bus -- * clients. */ -+ /* The key names are not necessarily normalized, make sure that they are when we return them to our -+ * bus clients. */ -+ assert(canonical); - r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized); - if (r < 0) - goto finish; - - /* Return the precise spelling and uppercasing and CNAME target reported by the server */ -- assert(canonical); - r = sd_bus_message_append( - reply, "st", - normalized, -@@ -218,15 +254,29 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) { - finish: - if (r < 0) { - log_error_errno(r, "Failed to send hostname reply: %m"); -- sd_bus_reply_method_errno(q->request, r, NULL); -+ sd_bus_reply_method_errno(q->bus_request, r, NULL); - } - - dns_query_free(q); - } - --static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) { -+static int validate_and_mangle_ifindex_and_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) { - assert(flags); - -+ /* Checks that the client supplied interface index and flags parameter actually are valid and make -+ * sense in our method call context. Specifically: -+ * -+ * 1. Checks that the interface index is either 0 (meaning *all* interfaces) or positive -+ * -+ * 2. Only the protocols flags and the NO_CNAME flag are set, at most. Plus additional flags specific -+ * to our method, passed in the "ok" parameter. -+ * -+ * 3. If zero protocol flags are specified it is automatically turned into *all* protocols. This way -+ * clients can simply pass 0 as flags and all will work as it should. They can also use this so -+ * that clients don't have to know all the protocols resolved implements, but can just specify 0 -+ * to mean "all supported protocols". -+ */ -+ - if (ifindex < 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index"); - -@@ -324,7 +374,7 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, - if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); - -- r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error); -+ r = validate_and_mangle_ifindex_and_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error); - if (r < 0) - return r; - -@@ -350,10 +400,9 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, - if (r < 0) - return r; - -- q->request = sd_bus_message_ref(message); -+ q->bus_request = sd_bus_message_ref(message); - q->request_family = family; - q->complete = bus_method_resolve_hostname_complete; -- q->suppress_unroutable_family = family == AF_UNSPEC; - - r = dns_query_bus_track(q, message); - if (r < 0) -@@ -386,7 +435,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) { - - r = dns_query_process_cname(q); - if (r == -ELOOP) { -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); - goto finish; - } - if (r < 0) -@@ -394,7 +443,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) { - if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ - return; - -- r = sd_bus_message_new_method_return(q->request, &reply); -+ r = sd_bus_message_new_method_return(q->bus_request, &reply); - if (r < 0) - goto finish; - -@@ -428,7 +477,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) { - _cleanup_free_ char *ip = NULL; - - (void) in_addr_to_string(q->request_family, &q->request_address, &ip); -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SUCH_RR, - "Address '%s' does not have any RR of requested type", strnull(ip)); - goto finish; - } -@@ -446,7 +495,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) { - finish: - if (r < 0) { - log_error_errno(r, "Failed to send address reply: %m"); -- sd_bus_reply_method_errno(q->request, r, NULL); -+ sd_bus_reply_method_errno(q->bus_request, r, NULL); - } - - dns_query_free(q); -@@ -478,7 +527,7 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s - if (r < 0) - return r; - -- r = check_ifindex_flags(ifindex, &flags, 0, error); -+ r = validate_and_mangle_ifindex_and_flags(ifindex, &flags, 0, error); - if (r < 0) - return r; - -@@ -490,7 +539,7 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s - if (r < 0) - return r; - -- q->request = sd_bus_message_ref(message); -+ q->bus_request = sd_bus_message_ref(message); - q->request_family = family; - q->request_address = a; - q->complete = bus_method_resolve_address_complete; -@@ -555,7 +604,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) { - - r = dns_query_process_cname(q); - if (r == -ELOOP) { -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); - goto finish; - } - if (r < 0) -@@ -563,7 +612,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) { - if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ - return; - -- r = sd_bus_message_new_method_return(q->request, &reply); -+ r = sd_bus_message_new_method_return(q->bus_request, &reply); - if (r < 0) - goto finish; - -@@ -588,7 +637,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) { - } - - if (added <= 0) { -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", dns_query_string(q)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", dns_query_string(q)); - goto finish; - } - -@@ -605,7 +654,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) { - finish: - if (r < 0) { - log_error_errno(r, "Failed to send record reply: %m"); -- sd_bus_reply_method_errno(q->request, r, NULL); -+ sd_bus_reply_method_errno(q->bus_request, r, NULL); - } - - dns_query_free(q); -@@ -643,7 +692,7 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd - if (dns_type_is_obsolete(type)) - return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type); - -- r = check_ifindex_flags(ifindex, &flags, 0, error); -+ r = validate_and_mangle_ifindex_and_flags(ifindex, &flags, 0, error); - if (r < 0) - return r; - -@@ -667,7 +716,7 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd - * blob */ - q->clamp_ttl = true; - -- q->request = sd_bus_message_ref(message); -+ q->bus_request = sd_bus_message_ref(message); - q->complete = bus_method_resolve_record_complete; - - r = dns_query_bus_track(q, message); -@@ -891,7 +940,7 @@ static void resolve_service_all_complete(DnsQuery *q) { - assert(bad->auxiliary_result != 0); - - if (bad->auxiliary_result == -ELOOP) { -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad)); - goto finish; - } - -@@ -904,7 +953,7 @@ static void resolve_service_all_complete(DnsQuery *q) { - } - } - -- r = sd_bus_message_new_method_return(q->request, &reply); -+ r = sd_bus_message_new_method_return(q->bus_request, &reply); - if (r < 0) - goto finish; - -@@ -913,6 +962,7 @@ static void resolve_service_all_complete(DnsQuery *q) { - goto finish; - - question = dns_query_question_for_protocol(q, q->answer_protocol); -+ - DNS_ANSWER_FOREACH(rr, q->answer) { - r = dns_question_matches_rr(question, rr, NULL); - if (r < 0) -@@ -933,7 +983,7 @@ static void resolve_service_all_complete(DnsQuery *q) { - } - - if (added <= 0) { -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); - goto finish; - } - -@@ -979,7 +1029,7 @@ static void resolve_service_all_complete(DnsQuery *q) { - finish: - if (r < 0) { - log_error_errno(r, "Failed to send service reply: %m"); -- sd_bus_reply_method_errno(q->request, r, NULL); -+ sd_bus_reply_method_errno(q->bus_request, r, NULL); - } - - dns_query_free(q); -@@ -1071,7 +1121,7 @@ static void bus_method_resolve_service_complete(DnsQuery *q) { - - r = dns_query_process_cname(q); - if (r == -ELOOP) { -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); - goto finish; - } - if (r < 0) -@@ -1115,12 +1165,12 @@ static void bus_method_resolve_service_complete(DnsQuery *q) { - * domain. Report this as a recognizable - * error. See RFC 2782, Section "Usage - * Rules". */ -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_query_string(q)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_query_string(q)); - goto finish; - } - - if (found <= 0) { -- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); -+ r = sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); - goto finish; - } - -@@ -1131,7 +1181,7 @@ static void bus_method_resolve_service_complete(DnsQuery *q) { - finish: - if (r < 0) { - log_error_errno(r, "Failed to send service reply: %m"); -- sd_bus_reply_method_errno(q->request, r, NULL); -+ sd_bus_reply_method_errno(q->bus_request, r, NULL); - } - - dns_query_free(q); -@@ -1177,7 +1227,7 @@ static int bus_method_resolve_service(sd_bus_message *message, void *userdata, s - if (name && !type) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type."); - -- r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error); -+ r = validate_and_mangle_ifindex_and_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error); - if (r < 0) - return r; - -@@ -1193,7 +1243,7 @@ static int bus_method_resolve_service(sd_bus_message *message, void *userdata, s - if (r < 0) - return r; - -- q->request = sd_bus_message_ref(message); -+ q->bus_request = sd_bus_message_ref(message); - q->request_family = family; - q->complete = bus_method_resolve_service_complete; - -@@ -1274,7 +1324,6 @@ static int bus_property_get_dns_servers_internal( - - Manager *m = userdata; - DnsServer *s; -- Iterator i; - Link *l; - int r; - -@@ -1291,7 +1340,7 @@ static int bus_property_get_dns_servers_internal( - return r; - } - -- HASHMAP_FOREACH(l, m->links, i) -+ HASHMAP_FOREACH(l, m->links) - LIST_FOREACH(servers, s, l->dns_servers) { - r = bus_dns_server_append(reply, s, true, extended); - if (r < 0) -@@ -1427,7 +1476,6 @@ static int bus_property_get_domains( - - Manager *m = userdata; - DnsSearchDomain *d; -- Iterator i; - Link *l; - int r; - -@@ -1444,7 +1492,7 @@ static int bus_property_get_domains( - return r; - } - -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - LIST_FOREACH(domains, d, l->search_domains) { - r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only); - if (r < 0) -@@ -1531,7 +1579,6 @@ static int bus_property_get_ntas( - - Manager *m = userdata; - const char *domain; -- Iterator i; - int r; - - assert(reply); -@@ -1541,7 +1588,7 @@ static int bus_property_get_ntas( - if (r < 0) - return r; - -- SET_FOREACH(domain, m->trust_anchor.negative_by_name, i) { -+ SET_FOREACH(domain, m->trust_anchor.negative_by_name) { - r = sd_bus_message_append(reply, "s", domain); - if (r < 0) - return r; -@@ -1690,7 +1737,7 @@ static int bus_method_reset_server_features(sd_bus_message *message, void *userd - return sd_bus_reply_method_return(message, NULL); - } - --static int on_bus_track(sd_bus_track *t, void *userdata) { -+static int dnssd_service_on_bus_track(sd_bus_track *t, void *userdata) { - DnssdService *s = userdata; - - assert(t); -@@ -1707,7 +1754,6 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata, - _cleanup_(dnssd_service_freep) DnssdService *service = NULL; - _cleanup_(sd_bus_track_unrefp) sd_bus_track *bus_track = NULL; - _cleanup_free_ char *path = NULL; -- _cleanup_free_ char *instance_name = NULL; - Manager *m = userdata; - DnssdService *s = NULL; - const char *name; -@@ -1748,6 +1794,10 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata, - if (!dnssd_srv_type_is_valid(type)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service type '%s' is invalid", type); - -+ r = dnssd_render_instance_name(name_template, NULL); -+ if (r < 0) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service name '%s' is invalid", name_template); -+ - service->name = strdup(name); - if (!service->name) - return log_oom(); -@@ -1760,10 +1810,6 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata, - if (!service->type) - return log_oom(); - -- r = dnssd_render_instance_name(service, &instance_name); -- if (r < 0) -- return r; -- - r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "a{say}"); - if (r < 0) - return r; -@@ -1863,7 +1909,7 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata, - if (r < 0) - return r; - -- r = sd_bus_track_new(sd_bus_message_get_bus(message), &bus_track, on_bus_track, service); -+ r = sd_bus_track_new(sd_bus_message_get_bus(message), &bus_track, dnssd_service_on_bus_track, service); - if (r < 0) - return r; - -diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c -index 6b99271..0b7c5c8 100644 ---- a/src/resolve/resolved-conf.c -+++ b/src/resolve/resolved-conf.c -@@ -10,23 +10,17 @@ - #include "resolved-dnssd.h" - #include "resolved-manager.h" - #include "resolved-dns-search-domain.h" -+#include "resolved-dns-stub.h" - #include "dns-domain.h" - #include "socket-netlink.h" - #include "specifier.h" - #include "string-table.h" - #include "string-util.h" -+#include "strv.h" - #include "utf8.h" - - DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode, "Failed to parse DNS stub listener mode setting"); - --static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MAX] = { -- [DNS_STUB_LISTENER_NO] = "no", -- [DNS_STUB_LISTENER_UDP] = "udp", -- [DNS_STUB_LISTENER_TCP] = "tcp", -- [DNS_STUB_LISTENER_YES] = "yes", --}; --DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES); -- - static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { - _cleanup_free_ char *server_name = NULL; - union in_addr_union address; -@@ -41,9 +35,6 @@ static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, cons - if (r < 0) - return r; - -- if (IN_SET(port, 53, 853)) -- port = 0; -- - /* Silently filter out 0.0.0.0 and 127.0.0.53 (our own stub DNS listener) */ - if (!dns_server_address_valid(family, &address)) - return 0; -@@ -56,12 +47,8 @@ static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, cons - /* Filter out duplicates */ - s = dns_server_find(manager_get_first_dns_server(m, type), family, &address, port, ifindex, server_name); - if (s) { -- /* -- * Drop the marker. This is used to find the servers -- * that ceased to exist, see -- * manager_mark_dns_servers() and -- * manager_flush_marked_dns_servers(). -- */ -+ /* Drop the marker. This is used to find the servers that ceased to exist, see -+ * manager_mark_dns_servers() and manager_flush_marked_dns_servers(). */ - dns_server_move_back_and_unmark(s); - return 0; - } -@@ -174,7 +161,8 @@ int config_parse_dns_servers( - /* Otherwise, add to the list */ - r = manager_parse_dns_server_string_and_warn(m, ltype, rvalue); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server string '%s'. Ignoring.", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse DNS server string '%s', ignoring.", rvalue); - return 0; - } - } -@@ -216,7 +204,8 @@ int config_parse_search_domains( - /* Otherwise, add to the list */ - r = manager_parse_search_domains_and_warn(m, rvalue); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse search domains string '%s'. Ignoring.", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse search domains string '%s', ignoring.", rvalue); - return 0; - } - } -@@ -228,21 +217,19 @@ int config_parse_search_domains( - return 0; - } - --int config_parse_dnssd_service_name(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { -- static const Specifier specifier_table[] = { -- { 'm', specifier_machine_id, NULL }, -- { 'b', specifier_boot_id, NULL }, -- { 'H', specifier_host_name, NULL }, -- { 'v', specifier_kernel_release, NULL }, -- { 'a', specifier_architecture, NULL }, -- { 'o', specifier_os_id, NULL }, -- { 'w', specifier_os_version_id, NULL }, -- { 'B', specifier_os_build_id, NULL }, -- { 'W', specifier_os_variant_id, NULL }, -- {} -- }; -+int config_parse_dnssd_service_name( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ - DnssdService *s = userdata; -- _cleanup_free_ char *name = NULL; - int r; - - assert(filename); -@@ -251,27 +238,38 @@ int config_parse_dnssd_service_name(const char *unit, const char *filename, unsi - assert(s); - - if (isempty(rvalue)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Service instance name can't be empty. Ignoring."); -- return -EINVAL; -+ s->name_template = mfree(s->name_template); -+ return 0; - } - -- r = free_and_strdup(&s->name_template, rvalue); -- if (r < 0) -+ r = dnssd_render_instance_name(rvalue, NULL); -+ if (r == -ENOMEM) - return log_oom(); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Invalid service instance name template '%s', ignoring: %m", rvalue); -+ return 0; -+ } - -- r = specifier_printf(s->name_template, specifier_table, NULL, &name); -+ r = free_and_strdup(&s->name_template, rvalue); - if (r < 0) -- return log_debug_errno(r, "Failed to replace specifiers: %m"); -- -- if (!dns_service_name_is_valid(name)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Service instance name template renders to invalid name '%s'. Ignoring.", name); -- return -EINVAL; -- } -+ return log_oom(); - - return 0; - } - --int config_parse_dnssd_service_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { -+int config_parse_dnssd_service_type( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ - DnssdService *s = userdata; - int r; - -@@ -281,13 +279,13 @@ int config_parse_dnssd_service_type(const char *unit, const char *filename, unsi - assert(s); - - if (isempty(rvalue)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Service type can't be empty. Ignoring."); -- return -EINVAL; -+ s->type = mfree(s->type); -+ return 0; - } - - if (!dnssd_srv_type_is_valid(rvalue)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Service type is invalid. Ignoring."); -- return -EINVAL; -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Service type is invalid. Ignoring."); -+ return 0; - } - - r = free_and_strdup(&s->type, rvalue); -@@ -297,7 +295,18 @@ int config_parse_dnssd_service_type(const char *unit, const char *filename, unsi - return 0; - } - --int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { -+int config_parse_dnssd_txt( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ - _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL; - DnssdService *s = userdata; - DnsTxtItem *last = NULL; -@@ -318,9 +327,7 @@ int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line - return log_oom(); - - for (;;) { -- _cleanup_free_ char *word = NULL; -- _cleanup_free_ char *key = NULL; -- _cleanup_free_ char *value = NULL; -+ _cleanup_free_ char *word = NULL, *key = NULL, *value = NULL; - _cleanup_free_ void *decoded = NULL; - size_t length = 0; - DnsTxtItem *i; -@@ -332,8 +339,10 @@ int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line - break; - if (r == -ENOMEM) - return log_oom(); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); -+ return 0; -+ } - - r = split_pair(word, "=", &key, &value); - if (r == -ENOMEM) -@@ -342,8 +351,8 @@ int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line - key = TAKE_PTR(word); - - if (!ascii_is_valid(key)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring: %s", key); -- return -EINVAL; -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid key, ignoring: %s", key); -+ continue; - } - - switch (ltype) { -@@ -353,9 +362,11 @@ int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line - r = unbase64mem(value, strlen(value), &decoded, &length); - if (r == -ENOMEM) - return log_oom(); -- if (r < 0) -- return log_syntax(unit, LOG_ERR, filename, line, r, -- "Invalid base64 encoding, ignoring: %s", value); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Invalid base64 encoding, ignoring: %s", value); -+ continue; -+ } - } - - r = dnssd_txt_item_new_from_data(key, decoded, length, &i); -@@ -379,9 +390,75 @@ int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line - - if (!LIST_IS_EMPTY(txt_data->txt)) { - LIST_PREPEND(items, s->txt_data_items, txt_data); -- txt_data = NULL; -+ TAKE_PTR(txt_data); -+ } -+ -+ return 0; -+} -+ -+int config_parse_dns_stub_listener_extra( -+ const char *unit, -+ const char *filename, -+ unsigned line, -+ const char *section, -+ unsigned section_line, -+ const char *lvalue, -+ int ltype, -+ const char *rvalue, -+ void *data, -+ void *userdata) { -+ -+ _cleanup_free_ DnsStubListenerExtra *stub = NULL; -+ Manager *m = userdata; -+ const char *p; -+ int r; -+ -+ assert(filename); -+ assert(lvalue); -+ assert(rvalue); -+ assert(data); -+ -+ if (isempty(rvalue)) { -+ m->dns_extra_stub_listeners = ordered_set_free(m->dns_extra_stub_listeners); -+ return 0; - } - -+ r = dns_stub_listener_extra_new(m, &stub); -+ if (r < 0) -+ return log_oom(); -+ -+ p = startswith(rvalue, "udp:"); -+ if (p) -+ stub->mode = DNS_STUB_LISTENER_UDP; -+ else { -+ p = startswith(rvalue, "tcp:"); -+ if (p) -+ stub->mode = DNS_STUB_LISTENER_TCP; -+ else { -+ stub->mode = DNS_STUB_LISTENER_YES; -+ p = rvalue; -+ } -+ } -+ -+ r = in_addr_port_ifindex_name_from_string_auto(p, &stub->family, &stub->address, &stub->port, NULL, NULL); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse address in %s=%s, ignoring assignment: %m", -+ lvalue, rvalue); -+ return 0; -+ } -+ -+ r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, stub); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) { -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to store %s=%s, ignoring assignment: %m", lvalue, rvalue); -+ return 0; -+ } -+ -+ TAKE_PTR(stub); -+ - return 0; - } - -diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h -index ac3937c..09ae8d7 100644 ---- a/src/resolve/resolved-conf.h -+++ b/src/resolve/resolved-conf.h -@@ -3,17 +3,6 @@ - - #include "conf-parser.h" - --typedef enum DnsStubListenerMode DnsStubListenerMode; -- --enum DnsStubListenerMode { -- DNS_STUB_LISTENER_NO, -- DNS_STUB_LISTENER_UDP, -- DNS_STUB_LISTENER_TCP, -- DNS_STUB_LISTENER_YES, -- _DNS_STUB_LISTENER_MODE_MAX, -- _DNS_STUB_LISTENER_MODE_INVALID = -1 --}; -- - #include "resolved-dns-server.h" - - int manager_parse_config_file(Manager *m); -@@ -30,6 +19,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_mode); - CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name); - CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type); - CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt); -- --const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_; --DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_; -+CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_extra); -diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c -index 946889a..683f113 100644 ---- a/src/resolve/resolved-dns-cache.c -+++ b/src/resolve/resolved-dns-cache.c -@@ -1015,14 +1015,13 @@ int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_ - - int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) { - unsigned ancount = 0; -- Iterator iterator; - DnsCacheItem *i; - int r; - - assert(cache); - assert(p); - -- HASHMAP_FOREACH(i, cache->by_key, iterator) { -+ HASHMAP_FOREACH(i, cache->by_key) { - DnsCacheItem *j; - - LIST_FOREACH(by_key, j, i) { -@@ -1063,7 +1062,6 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) { - } - - void dns_cache_dump(DnsCache *cache, FILE *f) { -- Iterator iterator; - DnsCacheItem *i; - - if (!cache) -@@ -1072,7 +1070,7 @@ void dns_cache_dump(DnsCache *cache, FILE *f) { - if (!f) - f = stdout; - -- HASHMAP_FOREACH(i, cache->by_key, iterator) { -+ HASHMAP_FOREACH(i, cache->by_key) { - DnsCacheItem *j; - - LIST_FOREACH(by_key, j, i) { -diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c -index 63ede72..75c8bf3 100644 ---- a/src/resolve/resolved-dns-packet.c -+++ b/src/resolve/resolved-dns-packet.c -@@ -354,7 +354,6 @@ static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start - } - - void dns_packet_truncate(DnsPacket *p, size_t sz) { -- Iterator i; - char *s; - void *n; - -@@ -363,7 +362,7 @@ void dns_packet_truncate(DnsPacket *p, size_t sz) { - if (p->size <= sz) - return; - -- HASHMAP_FOREACH_KEY(n, s, p->names, i) { -+ HASHMAP_FOREACH_KEY(n, s, p->names) { - - if (PTR_TO_SIZE(n) < sz) - continue; -@@ -646,7 +645,6 @@ fail: - } - - static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) { -- Iterator i; - uint8_t window = 0; - uint8_t entry = 0; - uint8_t bitmaps[32] = {}; -@@ -658,7 +656,7 @@ static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) { - - saved_size = p->size; - -- BITMAP_FOREACH(n, types, i) { -+ BITMAP_FOREACH(n, types) { - assert(n <= 0xffff); - - if ((n >> 8) != window && bitmaps[entry / 8] != 0) { -diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c -index 906158c..3afe4cf 100644 ---- a/src/resolve/resolved-dns-query.c -+++ b/src/resolve/resolved-dns-query.c -@@ -129,14 +129,13 @@ static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResource - - static int dns_query_candidate_go(DnsQueryCandidate *c) { - DnsTransaction *t; -- Iterator i; - int r; - unsigned n = 0; - - assert(c); - - /* Start the transactions that are not started yet */ -- SET_FOREACH(t, c->transactions, i) { -+ SET_FOREACH(t, c->transactions) { - if (t->state != DNS_TRANSACTION_NULL) - continue; - -@@ -157,14 +156,13 @@ static int dns_query_candidate_go(DnsQueryCandidate *c) { - static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) { - DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS; - DnsTransaction *t; -- Iterator i; - - assert(c); - - if (c->error_code != 0) - return DNS_TRANSACTION_ERRNO; - -- SET_FOREACH(t, c->transactions, i) { -+ SET_FOREACH(t, c->transactions) { - - switch (t->state) { - -@@ -338,9 +336,14 @@ DnsQuery *dns_query_free(DnsQuery *q) { - - dns_query_reset_answer(q); - -- sd_bus_message_unref(q->request); -+ sd_bus_message_unref(q->bus_request); - sd_bus_track_unref(q->bus_track); - -+ if (q->varlink_request) { -+ varlink_set_userdata(q->varlink_request, NULL); -+ varlink_unref(q->varlink_request); -+ } -+ - dns_packet_unref(q->request_dns_packet); - dns_packet_unref(q->reply_dns_packet); - -@@ -473,14 +476,13 @@ int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) { - return 0; - } - --static void dns_query_complete(DnsQuery *q, DnsTransactionState state) { -+void dns_query_complete(DnsQuery *q, DnsTransactionState state) { - assert(q); - assert(!DNS_TRANSACTION_IS_LIVE(state)); - assert(DNS_TRANSACTION_IS_LIVE(q->state)); - -- /* Note that this call might invalidate the query. Callers -- * should hence not attempt to access the query or transaction -- * after calling this function. */ -+ /* Note that this call might invalidate the query. Callers should hence not attempt to access the -+ * query or transaction after calling this function. */ - - q->state = state; - -@@ -687,11 +689,11 @@ int dns_query_go(DnsQuery *q) { - - dns_query_reset_answer(q); - -- r = sd_event_add_time( -+ r = sd_event_add_time_relative( - q->manager->event, - &q->timeout_event_source, - clock_boottime_or_monotonic(), -- now(clock_boottime_or_monotonic()) + SD_RESOLVED_QUERY_TIMEOUT_USEC, -+ SD_RESOLVED_QUERY_TIMEOUT_USEC, - 0, on_query_timeout, q); - if (r < 0) - goto fail; -@@ -725,7 +727,6 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) { - bool has_authenticated = false, has_non_authenticated = false; - DnssecResult dnssec_result_authenticated = _DNSSEC_RESULT_INVALID, dnssec_result_non_authenticated = _DNSSEC_RESULT_INVALID; - DnsTransaction *t; -- Iterator i; - int r; - - assert(q); -@@ -749,7 +750,7 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) { - q->answer_errno = c->error_code; - } - -- SET_FOREACH(t, c->transactions, i) { -+ SET_FOREACH(t, c->transactions) { - - switch (t->state) { - -@@ -987,36 +988,6 @@ int dns_query_process_cname(DnsQuery *q) { - return DNS_QUERY_RESTARTED; /* We restarted the query for a new cname */ - } - --static int on_bus_track(sd_bus_track *t, void *userdata) { -- DnsQuery *q = userdata; -- -- assert(t); -- assert(q); -- -- log_debug("Client of active query vanished, aborting query."); -- dns_query_complete(q, DNS_TRANSACTION_ABORTED); -- return 0; --} -- --int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) { -- int r; -- -- assert(q); -- assert(m); -- -- if (!q->bus_track) { -- r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q); -- if (r < 0) -- return r; -- } -- -- r = sd_bus_track_add_sender(q->bus_track, m); -- if (r < 0) -- return r; -- -- return 0; --} -- - DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol) { - assert(q); - -diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h -index fe8a219..36a9b7b 100644 ---- a/src/resolve/resolved-dns-query.h -+++ b/src/resolve/resolved-dns-query.h -@@ -4,9 +4,11 @@ - #include "sd-bus.h" - - #include "set.h" -+#include "varlink.h" - - typedef struct DnsQueryCandidate DnsQueryCandidate; - typedef struct DnsQuery DnsQuery; -+typedef struct DnsStubListenerExtra DnsStubListenerExtra; - - #include "resolved-dns-answer.h" - #include "resolved-dns-question.h" -@@ -48,10 +50,6 @@ struct DnsQuery { - uint64_t flags; - int ifindex; - -- /* If true, A or AAAA RR lookups will be suppressed on links with no routable address of the matching address -- * family */ -- bool suppress_unroutable_family; -- - /* If true, the RR TTLs of the answer will be clamped by their current left validity in the cache */ - bool clamp_ttl; - -@@ -72,8 +70,9 @@ struct DnsQuery { - int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */ - bool previous_redirect_unauthenticated; - -- /* Bus client information */ -- sd_bus_message *request; -+ /* Bus + Varlink client information */ -+ sd_bus_message *bus_request; -+ Varlink *varlink_request; - int request_family; - bool request_address_valid; - union in_addr_union request_address; -@@ -84,6 +83,7 @@ struct DnsQuery { - DnsPacket *request_dns_packet; - DnsStream *request_dns_stream; - DnsPacket *reply_dns_packet; -+ DnsStubListenerExtra *stub_listener_extra; - - /* Completion callback */ - void (*complete)(DnsQuery* q); -@@ -116,7 +116,7 @@ void dns_query_ready(DnsQuery *q); - - int dns_query_process_cname(DnsQuery *q); - --int dns_query_bus_track(DnsQuery *q, sd_bus_message *m); -+void dns_query_complete(DnsQuery *q, DnsTransactionState state); - - DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol); - -diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c -index fa43dd0..63ed9eb 100644 ---- a/src/resolve/resolved-dns-rr.c -+++ b/src/resolve/resolved-dns-rr.c -@@ -750,11 +750,10 @@ static int format_timestamp_dns(char *buf, size_t l, time_t sec) { - static char *format_types(Bitmap *types) { - _cleanup_strv_free_ char **strv = NULL; - _cleanup_free_ char *str = NULL; -- Iterator i; - unsigned type; - int r; - -- BITMAP_FOREACH(type, types, i) { -+ BITMAP_FOREACH(type, types) { - if (dns_type_to_string(type)) { - r = strv_extend(&strv, dns_type_to_string(type)); - if (r < 0) -diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c -index bd4b59e..2ad4544 100644 ---- a/src/resolve/resolved-dns-scope.c -+++ b/src/resolve/resolved-dns-scope.c -@@ -386,54 +386,27 @@ static int dns_scope_socket( - } - - if (s->link) { -- be32_t ifindex_be = htobe32(ifindex); -- -- if (sa.sa.sa_family == AF_INET) { -- r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)); -- if (r < 0) -- return -errno; -- } else if (sa.sa.sa_family == AF_INET6) { -- r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)); -- if (r < 0) -- return -errno; -- } -+ r = socket_set_unicast_if(fd, sa.sa.sa_family, ifindex); -+ if (r < 0) -+ return r; - } - - if (s->protocol == DNS_PROTOCOL_LLMNR) { - /* RFC 4795, section 2.5 requires the TTL to be set to 1 */ -- -- if (sa.sa.sa_family == AF_INET) { -- r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true); -- if (r < 0) -- return r; -- } else if (sa.sa.sa_family == AF_INET6) { -- r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, true); -- if (r < 0) -- return r; -- } -+ r = socket_set_ttl(fd, sa.sa.sa_family, 1); -+ if (r < 0) -+ return r; - } - - if (type == SOCK_DGRAM) { - /* Set IP_RECVERR or IPV6_RECVERR to get ICMP error feedback. See discussion in #10345. */ -+ r = socket_set_recverr(fd, sa.sa.sa_family, true); -+ if (r < 0) -+ return r; - -- if (sa.sa.sa_family == AF_INET) { -- r = setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, true); -- if (r < 0) -- return r; -- -- r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true); -- if (r < 0) -- return r; -- -- } else if (sa.sa.sa_family == AF_INET6) { -- r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, true); -- if (r < 0) -- return r; -- -- r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); -- if (r < 0) -- return r; -- } -+ r = socket_set_recvpktinfo(fd, sa.sa.sa_family, true); -+ if (r < 0) -+ return r; - } - - if (ret_socket_address) -@@ -1059,12 +1032,13 @@ int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) { - random_bytes(&jitter, sizeof(jitter)); - jitter %= LLMNR_JITTER_INTERVAL_USEC; - -- r = sd_event_add_time(scope->manager->event, -- &scope->conflict_event_source, -- clock_boottime_or_monotonic(), -- now(clock_boottime_or_monotonic()) + jitter, -- LLMNR_JITTER_INTERVAL_USEC, -- on_conflict_dispatch, scope); -+ r = sd_event_add_time_relative( -+ scope->manager->event, -+ &scope->conflict_event_source, -+ clock_boottime_or_monotonic(), -+ jitter, -+ LLMNR_JITTER_INTERVAL_USEC, -+ on_conflict_dispatch, scope); - if (r < 0) - return log_debug_errno(r, "Failed to add conflict dispatch event: %m"); - -@@ -1217,7 +1191,6 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) { - DnsTransaction *t; - DnsZoneItem *z, *i; - unsigned size = 0; -- Iterator iterator; - char *service_type; - int r; - -@@ -1237,7 +1210,7 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) { - return 0; /* we reach this point only if changing hostname didn't help */ - - /* Calculate answer's size. */ -- HASHMAP_FOREACH(z, scope->zone.by_key, iterator) { -+ HASHMAP_FOREACH(z, scope->zone.by_key) { - if (z->state != DNS_ZONE_ITEM_ESTABLISHED) - continue; - -@@ -1269,7 +1242,7 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) { - return log_oom(); - - /* Second iteration, actually add RRs to the answer. */ -- HASHMAP_FOREACH(z, scope->zone.by_key, iterator) -+ HASHMAP_FOREACH(z, scope->zone.by_key) - LIST_FOREACH (by_key, i, z) { - DnsAnswerFlags flags; - -@@ -1287,7 +1260,7 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) { - } - - /* Since all the active services are in the zone make them discoverable now. */ -- SET_FOREACH(service_type, types, iterator) { -+ SET_FOREACH(service_type, types) { - _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr; - - rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, -@@ -1318,18 +1291,13 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) { - /* In section 8.3 of RFC6762: "The Multicast DNS responder MUST send at least two unsolicited - * responses, one second apart." */ - if (!scope->announced) { -- usec_t ts; -- - scope->announced = true; - -- assert_se(sd_event_now(scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); -- ts += MDNS_ANNOUNCE_DELAY; -- -- r = sd_event_add_time( -+ r = sd_event_add_time_relative( - scope->manager->event, - &scope->announce_event_source, - clock_boottime_or_monotonic(), -- ts, -+ MDNS_ANNOUNCE_DELAY, - MDNS_JITTER_RANGE_USEC, - on_announcement_timeout, scope); - if (r < 0) -@@ -1342,7 +1310,6 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) { - } - - int dns_scope_add_dnssd_services(DnsScope *scope) { -- Iterator i; - DnssdService *service; - DnssdTxtData *txt_data; - int r; -@@ -1354,7 +1321,7 @@ int dns_scope_add_dnssd_services(DnsScope *scope) { - - scope->announced = false; - -- HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) { -+ HASHMAP_FOREACH(service, scope->manager->dnssd_services) { - service->withdrawn = false; - - r = dns_zone_put(&scope->zone, scope, service->ptr_rr, false); -@@ -1377,7 +1344,6 @@ int dns_scope_add_dnssd_services(DnsScope *scope) { - - int dns_scope_remove_dnssd_services(DnsScope *scope) { - _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; -- Iterator i; - DnssdService *service; - DnssdTxtData *txt_data; - int r; -@@ -1393,7 +1359,7 @@ int dns_scope_remove_dnssd_services(DnsScope *scope) { - if (r < 0) - return r; - -- HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) { -+ HASHMAP_FOREACH(service, scope->manager->dnssd_services) { - dns_zone_remove_rr(&scope->zone, service->ptr_rr); - dns_zone_remove_rr(&scope->zone, service->srv_rr); - LIST_FOREACH(items, txt_data, service->txt_data_items) -diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c -index 9c221e1..a5b8912 100644 ---- a/src/resolve/resolved-dns-server.c -+++ b/src/resolve/resolved-dns-server.c -@@ -753,13 +753,12 @@ DnsServer *manager_get_dns_server(Manager *m) { - - if (!m->current_dns_server) { - bool found = false; -- Iterator i; - - /* No DNS servers configured, let's see if there are - * any on any links. If not, we use the fallback - * servers */ - -- HASHMAP_FOREACH(l, m->links, i) -+ HASHMAP_FOREACH(l, m->links) - if (l->dns_servers) { - found = true; - break; -diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c -index d4c49e6..e6f72f0 100644 ---- a/src/resolve/resolved-dns-stream.c -+++ b/src/resolve/resolved-dns-stream.c -@@ -190,18 +190,10 @@ static int dns_stream_identify(DnsStream *s) { - s->ifindex = manager_find_ifindex(s->manager, s->local.sa.sa_family, s->local.sa.sa_family == AF_INET ? (union in_addr_union*) &s->local.in.sin_addr : (union in_addr_union*) &s->local.in6.sin6_addr); - - if (s->protocol == DNS_PROTOCOL_LLMNR && s->ifindex > 0) { -- be32_t ifindex = htobe32(s->ifindex); -- - /* Make sure all packets for this connection are sent on the same interface */ -- if (s->local.sa.sa_family == AF_INET) { -- r = setsockopt(s->fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)); -- if (r < 0) -- log_debug_errno(errno, "Failed to invoke IP_UNICAST_IF: %m"); -- } else if (s->local.sa.sa_family == AF_INET6) { -- r = setsockopt(s->fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex)); -- if (r < 0) -- log_debug_errno(errno, "Failed to invoke IPV6_UNICAST_IF: %m"); -- } -+ r = socket_set_unicast_if(s->fd, s->local.sa.sa_family, s->ifindex); -+ if (r < 0) -+ log_debug_errno(errno, "Failed to invoke IP_UNICAST_IF/IPV6_UNICAST_IF: %m"); - } - - s->identified = true; -@@ -445,7 +437,7 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use - - /* If we did something, let's restart the timeout event source */ - if (progressed && s->timeout_event_source) { -- r = sd_event_source_set_time(s->timeout_event_source, now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC); -+ r = sd_event_source_set_time_relative(s->timeout_event_source, DNS_STREAM_TIMEOUT_USEC); - if (r < 0) - log_warning_errno(errno, "Couldn't restart TCP connection timeout, ignoring: %m"); - } -@@ -455,7 +447,6 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use - - static DnsStream *dns_stream_free(DnsStream *s) { - DnsPacket *p; -- Iterator i; - - assert(s); - -@@ -471,7 +462,7 @@ static DnsStream *dns_stream_free(DnsStream *s) { - dnstls_stream_free(s); - #endif - -- ORDERED_SET_FOREACH(p, s->write_queue, i) -+ ORDERED_SET_FOREACH(p, s->write_queue) - dns_packet_unref(ordered_set_remove(s->write_queue, p)); - - dns_packet_unref(s->write_packet); -@@ -528,11 +519,11 @@ int dns_stream_new( - - (void) sd_event_source_set_description(s->io_event_source, "dns-stream-io"); - -- r = sd_event_add_time( -+ r = sd_event_add_time_relative( - m->event, - &s->timeout_event_source, - clock_boottime_or_monotonic(), -- now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC, 0, -+ DNS_STREAM_TIMEOUT_USEC, 0, - on_stream_timeout, s); - if (r < 0) - return r; -diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h -index 9fd8f5a..de19393 100644 ---- a/src/resolve/resolved-dns-stream.h -+++ b/src/resolve/resolved-dns-stream.h -@@ -10,6 +10,7 @@ typedef struct DnsServer DnsServer; - typedef struct DnsStream DnsStream; - typedef struct DnsTransaction DnsTransaction; - typedef struct Manager Manager; -+typedef struct DnsStubListenerExtra DnsStubListenerExtra; - - #include "resolved-dns-packet.h" - #include "resolved-dnstls.h" -@@ -75,6 +76,8 @@ struct DnsStream { - /* used when DNS-over-TLS is enabled */ - bool encrypted:1; - -+ DnsStubListenerExtra *stub_listener_extra; -+ - LIST_FIELDS(DnsStream, streams); - }; - -diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c -index 03edbe2..5c6da94 100644 ---- a/src/resolve/resolved-dns-stub.c -+++ b/src/resolve/resolved-dns-stub.c -@@ -1,17 +1,86 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - -+#include -+ - #include "errno-util.h" - #include "fd-util.h" - #include "missing_network.h" -+#include "missing_socket.h" - #include "resolved-dns-stub.h" -+#include "socket-netlink.h" - #include "socket-util.h" -+#include "string-table.h" - - /* The MTU of the loopback device is 64K on Linux, advertise that as maximum datagram size, but subtract the Ethernet, - * IP and UDP header sizes */ - #define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U) - --static int manager_dns_stub_udp_fd(Manager *m); --static int manager_dns_stub_tcp_fd(Manager *m); -+static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int type); -+ -+static void dns_stub_listener_extra_hash_func(const DnsStubListenerExtra *a, struct siphash *state) { -+ assert(a); -+ -+ siphash24_compress(&a->mode, sizeof(a->mode), state); -+ siphash24_compress(&a->family, sizeof(a->family), state); -+ siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state); -+ siphash24_compress(&a->port, sizeof(a->port), state); -+} -+ -+static int dns_stub_listener_extra_compare_func(const DnsStubListenerExtra *a, const DnsStubListenerExtra *b) { -+ int r; -+ -+ assert(a); -+ assert(b); -+ -+ r = CMP(a->mode, b->mode); -+ if (r != 0) -+ return r; -+ -+ r = CMP(a->family, b->family); -+ if (r != 0) -+ return r; -+ -+ r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family)); -+ if (r != 0) -+ return r; -+ -+ return CMP(a->port, b->port); -+} -+ -+DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( -+ dns_stub_listener_extra_hash_ops, -+ DnsStubListenerExtra, -+ dns_stub_listener_extra_hash_func, -+ dns_stub_listener_extra_compare_func, -+ dns_stub_listener_extra_free); -+ -+int dns_stub_listener_extra_new( -+ Manager *m, -+ DnsStubListenerExtra **ret) { -+ -+ DnsStubListenerExtra *l; -+ -+ l = new(DnsStubListenerExtra, 1); -+ if (!l) -+ return -ENOMEM; -+ -+ *l = (DnsStubListenerExtra) { -+ .manager = m, -+ }; -+ -+ *ret = TAKE_PTR(l); -+ return 0; -+} -+ -+DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p) { -+ if (!p) -+ return NULL; -+ -+ p->udp_event_source = sd_event_source_unref(p->udp_event_source); -+ p->tcp_event_source = sd_event_source_unref(p->tcp_event_source); -+ -+ return mfree(p); -+} - - static int dns_stub_make_reply_packet( - DnsPacket **p, -@@ -128,7 +197,13 @@ static int dns_stub_finish_reply_packet( - return 0; - } - --static int dns_stub_send(Manager *m, DnsStream *s, DnsPacket *p, DnsPacket *reply) { -+static int dns_stub_send( -+ Manager *m, -+ DnsStubListenerExtra *l, -+ DnsStream *s, -+ DnsPacket *p, -+ DnsPacket *reply) { -+ - int r; - - assert(m); -@@ -137,26 +212,29 @@ static int dns_stub_send(Manager *m, DnsStream *s, DnsPacket *p, DnsPacket *repl - - if (s) - r = dns_stream_write_packet(s, reply); -- else { -- int fd; -- -- fd = manager_dns_stub_udp_fd(m); -- if (fd < 0) -- return log_debug_errno(fd, "Failed to get reply socket: %m"); -- -+ else - /* Note that it is essential here that we explicitly choose the source IP address for this packet. This - * is because otherwise the kernel will choose it automatically based on the routing table and will - * thus pick 127.0.0.1 rather than 127.0.0.53. */ -- -- r = manager_send(m, fd, LOOPBACK_IFINDEX, p->family, &p->sender, p->sender_port, &p->destination, reply); -- } -+ r = manager_send(m, -+ manager_dns_stub_fd_extra(m, l, SOCK_DGRAM), -+ l ? p->ifindex : LOOPBACK_IFINDEX, /* force loopback iface if this is the main listener stub */ -+ p->family, &p->sender, p->sender_port, &p->destination, -+ reply); - if (r < 0) - return log_debug_errno(r, "Failed to send reply packet: %m"); - - return 0; - } - --static int dns_stub_send_failure(Manager *m, DnsStream *s, DnsPacket *p, int rcode, bool authenticated) { -+static int dns_stub_send_failure( -+ Manager *m, -+ DnsStubListenerExtra *l, -+ DnsStream *s, -+ DnsPacket *p, -+ int rcode, -+ bool authenticated) { -+ - _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL; - int r; - -@@ -171,7 +249,7 @@ static int dns_stub_send_failure(Manager *m, DnsStream *s, DnsPacket *p, int rco - if (r < 0) - return log_debug_errno(r, "Failed to build failure packet: %m"); - -- return dns_stub_send(m, s, p, reply); -+ return dns_stub_send(m, l, s, p, reply); - } - - static void dns_stub_query_complete(DnsQuery *q) { -@@ -194,7 +272,7 @@ static void dns_stub_query_complete(DnsQuery *q) { - if (!truncated) { - r = dns_query_process_cname(q); - if (r == -ELOOP) { -- (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); -+ (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); - break; - } - if (r < 0) { -@@ -218,16 +296,16 @@ static void dns_stub_query_complete(DnsQuery *q) { - break; - } - -- (void) dns_stub_send(q->manager, q->request_dns_stream, q->request_dns_packet, q->reply_dns_packet); -+ (void) dns_stub_send(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, q->reply_dns_packet); - break; - } - - case DNS_TRANSACTION_RCODE_FAILURE: -- (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, q->answer_rcode, dns_query_fully_authenticated(q)); -+ (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, q->answer_rcode, dns_query_fully_authenticated(q)); - break; - - case DNS_TRANSACTION_NOT_FOUND: -- (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_NXDOMAIN, dns_query_fully_authenticated(q)); -+ (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_NXDOMAIN, dns_query_fully_authenticated(q)); - break; - - case DNS_TRANSACTION_TIMEOUT: -@@ -243,7 +321,7 @@ static void dns_stub_query_complete(DnsQuery *q) { - case DNS_TRANSACTION_NO_TRUST_ANCHOR: - case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED: - case DNS_TRANSACTION_NETWORK_DOWN: -- (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); -+ (void) dns_stub_send_failure(q->manager, q->stub_listener_extra, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); - break; - - case DNS_TRANSACTION_NULL: -@@ -277,7 +355,7 @@ static int dns_stub_stream_complete(DnsStream *s, int error) { - return 0; - } - --static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { -+static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStream *s, DnsPacket *p) { - _cleanup_(dns_query_freep) DnsQuery *q = NULL; - int r; - -@@ -285,55 +363,56 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { - assert(p); - assert(p->protocol == DNS_PROTOCOL_DNS); - -- if (in_addr_is_localhost(p->family, &p->sender) <= 0 || -- in_addr_is_localhost(p->family, &p->destination) <= 0) { -+ if (!l && /* l == NULL if this is the main stub */ -+ (in_addr_is_localhost(p->family, &p->sender) <= 0 || -+ in_addr_is_localhost(p->family, &p->destination) <= 0)) { - log_error("Got packet on unexpected IP range, refusing."); -- dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); -+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_SERVFAIL, false); - return; - } - - r = dns_packet_extract(p); - if (r < 0) { - log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m"); -- dns_stub_send_failure(m, s, p, DNS_RCODE_FORMERR, false); -+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_FORMERR, false); - return; - } - - if (!DNS_PACKET_VERSION_SUPPORTED(p)) { - log_debug("Got EDNS OPT field with unsupported version number."); -- dns_stub_send_failure(m, s, p, DNS_RCODE_BADVERS, false); -+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_BADVERS, false); - return; - } - - if (dns_type_is_obsolete(p->question->keys[0]->type)) { - log_debug("Got message with obsolete key type, refusing."); -- dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false); -+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false); - return; - } - - if (dns_type_is_zone_transer(p->question->keys[0]->type)) { - log_debug("Got request for zone transfer, refusing."); -- dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false); -+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false); - return; - } - - if (!DNS_PACKET_RD(p)) { - /* If the "rd" bit is off (i.e. recursion was not requested), then refuse operation */ - log_debug("Got request with recursion disabled, refusing."); -- dns_stub_send_failure(m, s, p, DNS_RCODE_REFUSED, false); -+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_REFUSED, false); - return; - } - - if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) { - log_debug("Got request with DNSSEC CD bit set, refusing."); -- dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false); -+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_NOTIMP, false); - return; - } - - r = dns_query_new(m, &q, p->question, p->question, 0, SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_SEARCH); - if (r < 0) { - log_error_errno(r, "Failed to generate query object: %m"); -- dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); -+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_SERVFAIL, false); - return; - } - -@@ -342,6 +421,7 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { - - q->request_dns_packet = dns_packet_ref(p); - q->request_dns_stream = dns_stream_ref(s); /* make sure the stream stays around until we can send a reply through it */ -+ q->stub_listener_extra = l; - q->complete = dns_stub_query_complete; - - if (s) { -@@ -359,7 +439,7 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { - r = dns_query_go(q); - if (r < 0) { - log_error_errno(r, "Failed to start query: %m"); -- dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); -+ dns_stub_send_failure(m, l, s, p, DNS_RCODE_SERVFAIL, false); - return; - } - -@@ -367,9 +447,8 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { - TAKE_PTR(q); - } - --static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { -+static int on_dns_stub_packet_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, DnsStubListenerExtra *l) { - _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; -- Manager *m = userdata; - int r; - - r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p); -@@ -379,56 +458,23 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void - if (dns_packet_validate_query(p) > 0) { - log_debug("Got DNS stub UDP query packet for id %u", DNS_PACKET_ID(p)); - -- dns_stub_process_query(m, NULL, p); -+ dns_stub_process_query(m, l, NULL, p); - } else - log_debug("Invalid DNS stub UDP packet, ignoring."); - - return 0; - } - --static int manager_dns_stub_udp_fd(Manager *m) { -- union sockaddr_union sa = { -- .in.sin_family = AF_INET, -- .in.sin_port = htobe16(53), -- .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), -- }; -- _cleanup_close_ int fd = -1; -- int r; -- -- if (m->dns_stub_udp_fd >= 0) -- return m->dns_stub_udp_fd; -- -- fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); -- if (fd < 0) -- return -errno; -- -- r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true); -- if (r < 0) -- return r; -- -- r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true); -- if (r < 0) -- return r; -- -- r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true); -- if (r < 0) -- return r; -- -- /* Make sure no traffic from outside the local host can leak to onto this socket */ -- r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX); -- if (r < 0) -- return r; -- -- if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) -- return -errno; -+static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { -+ return on_dns_stub_packet_internal(s, fd, revents, userdata, NULL); -+} - -- r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, fd, EPOLLIN, on_dns_stub_packet, m); -- if (r < 0) -- return r; -+static int on_dns_stub_packet_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) { -+ DnsStubListenerExtra *l = userdata; - -- (void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp"); -+ assert(l); - -- return m->dns_stub_udp_fd = TAKE_FD(fd); -+ return on_dns_stub_packet_internal(s, fd, revents, l->manager, l); - } - - static int on_dns_stub_stream_packet(DnsStream *s) { -@@ -442,16 +488,15 @@ static int on_dns_stub_stream_packet(DnsStream *s) { - if (dns_packet_validate_query(p) > 0) { - log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p)); - -- dns_stub_process_query(s->manager, s, p); -+ dns_stub_process_query(s->manager, s->stub_listener_extra, s, p); - } else - log_debug("Invalid DNS stub TCP packet, ignoring."); - - return 0; - } - --static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) { -+static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, DnsStubListenerExtra *l) { - DnsStream *stream; -- Manager *m = userdata; - int cfd, r; - - cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); -@@ -468,6 +513,7 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void - return r; - } - -+ stream->stub_listener_extra = l; - stream->on_packet = on_dns_stub_stream_packet; - stream->complete = dns_stub_stream_complete; - -@@ -476,7 +522,39 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void - return 0; - } - --static int manager_dns_stub_tcp_fd(Manager *m) { -+static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) { -+ return on_dns_stub_stream_internal(s, fd, revents, userdata, NULL); -+} -+ -+static int on_dns_stub_stream_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) { -+ DnsStubListenerExtra *l = userdata; -+ -+ assert(l); -+ return on_dns_stub_stream_internal(s, fd, revents, l->manager, l); -+} -+ -+static int set_dns_stub_common_socket_options(int fd, int family) { -+ int r; -+ -+ assert(fd >= 0); -+ assert(IN_SET(family, AF_INET, AF_INET6)); -+ -+ r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true); -+ if (r < 0) -+ return r; -+ -+ r = socket_set_recvpktinfo(fd, family, true); -+ if (r < 0) -+ return r; -+ -+ r = socket_set_recvttl(fd, family, true); -+ if (r < 0) -+ return r; -+ -+ return 0; -+} -+ -+static int manager_dns_stub_fd(Manager *m, int type) { - union sockaddr_union sa = { - .in.sin_family = AF_INET, - .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), -@@ -485,47 +563,139 @@ static int manager_dns_stub_tcp_fd(Manager *m) { - _cleanup_close_ int fd = -1; - int r; - -- if (m->dns_stub_tcp_fd >= 0) -- return m->dns_stub_tcp_fd; -+ assert(IN_SET(type, SOCK_DGRAM, SOCK_STREAM)); -+ -+ sd_event_source **event_source = type == SOCK_DGRAM ? &m->dns_stub_udp_event_source : &m->dns_stub_tcp_event_source; -+ if (*event_source) -+ return sd_event_source_get_io_fd(*event_source); - -- fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); -+ fd = socket(AF_INET, type | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (fd < 0) - return -errno; - -- r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true); -+ r = set_dns_stub_common_socket_options(fd, AF_INET); - if (r < 0) - return r; - -- r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true); -+ /* Make sure no traffic from outside the local host can leak to onto this socket */ -+ r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX); - if (r < 0) - return r; - -- r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true); -+ r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, 1); - if (r < 0) - return r; - -- r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true); -+ if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) -+ return -errno; -+ -+ if (type == SOCK_STREAM && -+ listen(fd, SOMAXCONN) < 0) -+ return -errno; -+ -+ r = sd_event_add_io(m->event, event_source, fd, EPOLLIN, -+ type == SOCK_DGRAM ? on_dns_stub_packet : on_dns_stub_stream, -+ m); - if (r < 0) - return r; - -- /* Make sure no traffic from outside the local host can leak to onto this socket */ -- r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX); -+ r = sd_event_source_set_io_fd_own(*event_source, true); - if (r < 0) - return r; - -- if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) -- return -errno; -+ (void) sd_event_source_set_description(*event_source, -+ type == SOCK_DGRAM ? "dns-stub-udp" : "dns-stub-tcp"); - -- if (listen(fd, SOMAXCONN) < 0) -- return -errno; -+ return TAKE_FD(fd); -+} -+ -+static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int type) { -+ _cleanup_free_ char *pretty = NULL; -+ _cleanup_close_ int fd = -1; -+ union sockaddr_union sa; -+ int r; -+ -+ assert(m); -+ assert(IN_SET(type, SOCK_DGRAM, SOCK_STREAM)); -+ -+ if (!l) -+ return manager_dns_stub_fd(m, type); - -- r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, fd, EPOLLIN, on_dns_stub_stream, m); -+ sd_event_source **event_source = type == SOCK_DGRAM ? &l->udp_event_source : &l->tcp_event_source; -+ if (*event_source) -+ return sd_event_source_get_io_fd(*event_source); -+ -+ if (l->family == AF_INET) -+ sa = (union sockaddr_union) { -+ .in.sin_family = l->family, -+ .in.sin_port = htobe16(l->port != 0 ? l->port : 53U), -+ .in.sin_addr = l->address.in, -+ }; -+ else -+ sa = (union sockaddr_union) { -+ .in6.sin6_family = l->family, -+ .in6.sin6_port = htobe16(l->port != 0 ? l->port : 53U), -+ .in6.sin6_addr = l->address.in6, -+ }; -+ -+ fd = socket(l->family, type | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); -+ if (fd < 0) { -+ r = -errno; -+ goto fail; -+ } -+ -+ r = set_dns_stub_common_socket_options(fd, l->family); - if (r < 0) -- return r; -+ goto fail; - -- (void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp"); -+ /* Do not set IP_TTL for extra DNS stub listeners, as the address may not be local and in that case -+ * people may want ttl > 1. */ -+ -+ r = socket_set_freebind(fd, l->family, true); -+ if (r < 0) -+ goto fail; -+ -+ if (bind(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) { -+ r = -errno; -+ goto fail; -+ } - -- return m->dns_stub_tcp_fd = TAKE_FD(fd); -+ if (type == SOCK_STREAM && -+ listen(fd, SOMAXCONN) < 0) { -+ r = -errno; -+ goto fail; -+ } -+ -+ r = sd_event_add_io(m->event, event_source, fd, EPOLLIN, -+ type == SOCK_DGRAM ? on_dns_stub_packet_extra : on_dns_stub_stream_extra, -+ l); -+ if (r < 0) -+ goto fail; -+ -+ r = sd_event_source_set_io_fd_own(*event_source, true); -+ if (r < 0) -+ goto fail; -+ -+ (void) sd_event_source_set_description(*event_source, -+ type == SOCK_DGRAM ? "dns-stub-udp-extra" : "dns-stub-tcp-extra"); -+ -+ if (DEBUG_LOGGING) { -+ (void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty); -+ log_debug("Listening on %s socket %s.", -+ type == SOCK_DGRAM ? "UDP" : "TCP", -+ strnull(pretty)); -+ } -+ -+ return TAKE_FD(fd); -+ -+fail: -+ assert(r < 0); -+ (void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty); -+ return log_warning_errno(r, -+ r == -EADDRINUSE ? "Another process is already listening on %s socket %s: %m" : -+ "Failed to listen on %s socket %s: %m", -+ type == SOCK_DGRAM ? "UDP" : "TCP", -+ strnull(pretty)); - } - - int manager_dns_stub_start(Manager *m) { -@@ -542,28 +712,39 @@ int manager_dns_stub_start(Manager *m) { - m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" : - "UDP/TCP"); - -- if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP)) -- r = manager_dns_stub_udp_fd(m); -+ if (FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_UDP)) -+ r = manager_dns_stub_fd(m, SOCK_DGRAM); - - if (r >= 0 && -- IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) { -+ FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_TCP)) { - t = "TCP"; -- r = manager_dns_stub_tcp_fd(m); -+ r = manager_dns_stub_fd(m, SOCK_STREAM); - } - - if (IN_SET(r, -EADDRINUSE, -EPERM)) { -- if (r == -EADDRINUSE) -- log_warning_errno(r, -- "Another process is already listening on %s socket 127.0.0.53:53.\n" -- "Turning off local DNS stub support.", t); -- else -- log_warning_errno(r, -- "Failed to listen on %s socket 127.0.0.53:53: %m.\n" -- "Turning off local DNS stub support.", t); -+ log_warning_errno(r, -+ r == -EADDRINUSE ? "Another process is already listening on %s socket 127.0.0.53:53.\n" -+ "Turning off local DNS stub support." : -+ "Failed to listen on %s socket 127.0.0.53:53: %m.\n" -+ "Turning off local DNS stub support.", -+ t); - manager_dns_stub_stop(m); - } else if (r < 0) - return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t); - -+ if (!ordered_set_isempty(m->dns_extra_stub_listeners)) { -+ DnsStubListenerExtra *l; -+ -+ log_debug("Creating extra stub listeners."); -+ -+ ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners) { -+ if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_UDP)) -+ (void) manager_dns_stub_fd_extra(m, l, SOCK_DGRAM); -+ if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_TCP)) -+ (void) manager_dns_stub_fd_extra(m, l, SOCK_STREAM); -+ } -+ } -+ - return 0; - } - -@@ -572,7 +753,12 @@ void manager_dns_stub_stop(Manager *m) { - - m->dns_stub_udp_event_source = sd_event_source_unref(m->dns_stub_udp_event_source); - m->dns_stub_tcp_event_source = sd_event_source_unref(m->dns_stub_tcp_event_source); -- -- m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd); -- m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd); - } -+ -+static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MAX] = { -+ [DNS_STUB_LISTENER_NO] = "no", -+ [DNS_STUB_LISTENER_UDP] = "udp", -+ [DNS_STUB_LISTENER_TCP] = "tcp", -+ [DNS_STUB_LISTENER_YES] = "yes", -+}; -+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES); -diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h -index f34e9db..6686de5 100644 ---- a/src/resolve/resolved-dns-stub.h -+++ b/src/resolve/resolved-dns-stub.h -@@ -1,7 +1,41 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - #pragma once - -+#include "hash-funcs.h" -+ -+typedef struct DnsStubListenerExtra DnsStubListenerExtra; -+ -+typedef enum DnsStubListenerMode { -+ DNS_STUB_LISTENER_NO, -+ DNS_STUB_LISTENER_UDP = 1 << 0, -+ DNS_STUB_LISTENER_TCP = 1 << 1, -+ DNS_STUB_LISTENER_YES = DNS_STUB_LISTENER_UDP | DNS_STUB_LISTENER_TCP, -+ _DNS_STUB_LISTENER_MODE_MAX, -+ _DNS_STUB_LISTENER_MODE_INVALID = -1 -+} DnsStubListenerMode; -+ - #include "resolved-manager.h" - -+struct DnsStubListenerExtra { -+ Manager *manager; -+ -+ DnsStubListenerMode mode; -+ -+ int family; -+ union in_addr_union address; -+ uint16_t port; -+ -+ sd_event_source *udp_event_source; -+ sd_event_source *tcp_event_source; -+}; -+ -+extern const struct hash_ops dns_stub_listener_extra_hash_ops; -+ -+int dns_stub_listener_extra_new(Manager *m, DnsStubListenerExtra **ret); -+DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p); -+ - void manager_dns_stub_stop(Manager *m); - int manager_dns_stub_start(Manager *m); -+ -+const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_; -+DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_; -diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c -index e23ea27..36f57ea 100644 ---- a/src/resolve/resolved-dns-transaction.c -+++ b/src/resolve/resolved-dns-transaction.c -@@ -364,6 +364,14 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) { - dns_transaction_gc(t); - } - -+static void dns_transaction_complete_errno(DnsTransaction *t, int error) { -+ assert(t); -+ assert(error != 0); -+ -+ t->answer_errno = abs(error); -+ dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); -+} -+ - static int dns_transaction_pick_server(DnsTransaction *t) { - DnsServer *server; - -@@ -415,10 +423,8 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) { - dns_scope_next_dns_server(t->scope); - - r = dns_transaction_go(t); -- if (r < 0) { -- t->answer_errno = -r; -- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); -- } -+ if (r < 0) -+ dns_transaction_complete_errno(t, r); - } - - static int dns_transaction_maybe_restart(DnsTransaction *t) { -@@ -466,10 +472,8 @@ static void on_transaction_stream_error(DnsTransaction *t, int error) { - dns_transaction_retry(t, true); - return; - } -- if (error != 0) { -- t->answer_errno = error; -- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); -- } -+ if (error != 0) -+ dns_transaction_complete_errno(t, error); - } - - static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) { -@@ -698,11 +702,10 @@ static void dns_transaction_cache_answer(DnsTransaction *t) { - - static bool dns_transaction_dnssec_is_live(DnsTransaction *t) { - DnsTransaction *dt; -- Iterator i; - - assert(t); - -- SET_FOREACH(dt, t->dnssec_transactions, i) -+ SET_FOREACH(dt, t->dnssec_transactions) - if (DNS_TRANSACTION_IS_LIVE(dt->state)) - return true; - -@@ -711,14 +714,13 @@ static bool dns_transaction_dnssec_is_live(DnsTransaction *t) { - - static int dns_transaction_dnssec_ready(DnsTransaction *t) { - DnsTransaction *dt; -- Iterator i; - - assert(t); - - /* Checks whether the auxiliary DNSSEC transactions of our transaction have completed, or are still - * ongoing. Returns 0, if we aren't ready for the DNSSEC validation, positive if we are. */ - -- SET_FOREACH(dt, t->dnssec_transactions, i) { -+ SET_FOREACH(dt, t->dnssec_transactions) { - - switch (dt->state) { - -@@ -836,8 +838,7 @@ static void dns_transaction_process_dnssec(DnsTransaction *t) { - return; - - fail: -- t->answer_errno = -r; -- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); -+ dns_transaction_complete_errno(t, r); - } - - static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) { -@@ -1169,8 +1170,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { - return; - - fail: -- t->answer_errno = -r; -- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); -+ dns_transaction_complete_errno(t, r); - } - - static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { -@@ -1182,7 +1182,7 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use - assert(t->scope); - - r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p); -- if (ERRNO_IS_DISCONNECT(-r)) { -+ if (ERRNO_IS_DISCONNECT(r)) { - usec_t usec; - - /* UDP connection failures get reported via ICMP and then are possibly delivered to us on the -@@ -1196,8 +1196,7 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use - return 0; - } - if (r < 0) { -- dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); -- t->answer_errno = -r; -+ dns_transaction_complete_errno(t, r); - return 0; - } - if (r == 0) -@@ -1475,7 +1474,6 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) { - _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; - bool add_known_answers = false; - DnsTransaction *other; -- Iterator i; - DnsResourceKey *tkey; - _cleanup_set_free_ Set *keys = NULL; - unsigned qdcount; -@@ -1584,7 +1582,7 @@ static int dns_transaction_make_packet_mdns(DnsTransaction *t) { - return r; - } - -- SET_FOREACH(tkey, keys, i) { -+ SET_FOREACH(tkey, keys) { - _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; - bool tentative; - -@@ -1736,7 +1734,7 @@ int dns_transaction_go(DnsTransaction *t) { - dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED); - return 0; - } -- if (t->scope->protocol == DNS_PROTOCOL_LLMNR && ERRNO_IS_DISCONNECT(-r)) { -+ if (t->scope->protocol == DNS_PROTOCOL_LLMNR && ERRNO_IS_DISCONNECT(r)) { - /* On LLMNR, if we cannot connect to a host via TCP when doing reverse lookups. This means we cannot - * answer this request with this protocol. */ - dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND); -@@ -1773,7 +1771,6 @@ int dns_transaction_go(DnsTransaction *t) { - - static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) { - DnsTransaction *n; -- Iterator i; - int r; - - assert(t); -@@ -1784,7 +1781,7 @@ static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) { - if (t == aux) - return 1; - -- SET_FOREACH(n, aux->dnssec_transactions, i) { -+ SET_FOREACH(n, aux->dnssec_transactions) { - r = dns_transaction_find_cyclic(t, n); - if (r != 0) - return r; -@@ -1833,7 +1830,7 @@ static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResource - - r = set_ensure_put(&t->dnssec_transactions, NULL, aux); - if (r < 0) -- return r;; -+ return r; - - r = set_ensure_put(&aux->notify_transactions, NULL, t); - if (r < 0) { -@@ -1976,7 +1973,6 @@ static bool dns_transaction_dnssec_supported(DnsTransaction *t) { - - static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) { - DnsTransaction *dt; -- Iterator i; - - assert(t); - -@@ -1985,7 +1981,7 @@ static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) { - if (!dns_transaction_dnssec_supported(t)) - return false; - -- SET_FOREACH(dt, t->dnssec_transactions, i) -+ SET_FOREACH(dt, t->dnssec_transactions) - if (!dns_transaction_dnssec_supported(dt)) - return false; - -@@ -2379,11 +2375,10 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord * - case DNS_TYPE_SOA: - case DNS_TYPE_NS: { - DnsTransaction *dt; -- Iterator i; - - /* For SOA or NS RRs we look for a matching DS transaction */ - -- SET_FOREACH(dt, t->dnssec_transactions, i) { -+ SET_FOREACH(dt, t->dnssec_transactions) { - - if (dt->key->class != rr->key->class) - continue; -@@ -2417,7 +2412,6 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord * - case DNS_TYPE_DNAME: { - const char *parent = NULL; - DnsTransaction *dt; -- Iterator i; - - /* - * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA. -@@ -2425,7 +2419,7 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord * - * DS RRs are signed if the parent is signed, hence also look at the parent SOA - */ - -- SET_FOREACH(dt, t->dnssec_transactions, i) { -+ SET_FOREACH(dt, t->dnssec_transactions) { - - if (dt->key->class != rr->key->class) - continue; -@@ -2461,11 +2455,10 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord * - - default: { - DnsTransaction *dt; -- Iterator i; - - /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */ - -- SET_FOREACH(dt, t->dnssec_transactions, i) { -+ SET_FOREACH(dt, t->dnssec_transactions) { - - if (dt->key->class != rr->key->class) - continue; -@@ -2493,7 +2486,6 @@ static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord * - static int dns_transaction_in_private_tld(DnsTransaction *t, const DnsResourceKey *key) { - DnsTransaction *dt; - const char *tld; -- Iterator i; - int r; - - /* If DNSSEC downgrade mode is on, checks whether the -@@ -2529,7 +2521,7 @@ static int dns_transaction_in_private_tld(DnsTransaction *t, const DnsResourceKe - if (!dns_name_is_single_label(tld)) - return false; - -- SET_FOREACH(dt, t->dnssec_transactions, i) { -+ SET_FOREACH(dt, t->dnssec_transactions) { - - if (dt->key->class != key->class) - continue; -@@ -2555,7 +2547,6 @@ static int dns_transaction_requires_nsec(DnsTransaction *t) { - DnsTransaction *dt; - const char *name; - uint16_t type = 0; -- Iterator i; - int r; - - assert(t); -@@ -2613,7 +2604,7 @@ static int dns_transaction_requires_nsec(DnsTransaction *t) { - /* For all other RRs we check the SOA on the same level to see - * if it's signed. */ - -- SET_FOREACH(dt, t->dnssec_transactions, i) { -+ SET_FOREACH(dt, t->dnssec_transactions) { - - if (dt->key->class != t->key->class) - continue; -@@ -2650,7 +2641,6 @@ static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRe - - DNS_ANSWER_FOREACH(rrsig, t->answer) { - DnsTransaction *dt; -- Iterator i; - - r = dnssec_key_match_rrsig(rr->key, rrsig); - if (r < 0) -@@ -2658,7 +2648,7 @@ static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRe - if (r == 0) - continue; - -- SET_FOREACH(dt, t->dnssec_transactions, i) { -+ SET_FOREACH(dt, t->dnssec_transactions) { - - if (dt->key->class != rr->key->class) - continue; -@@ -2770,14 +2760,13 @@ static int dns_transaction_invalidate_revoked_keys(DnsTransaction *t) { - - static int dns_transaction_copy_validated(DnsTransaction *t) { - DnsTransaction *dt; -- Iterator i; - int r; - - assert(t); - - /* Copy all validated RRs from the auxiliary DNSSEC transactions into our set of validated RRs */ - -- SET_FOREACH(dt, t->dnssec_transactions, i) { -+ SET_FOREACH(dt, t->dnssec_transactions) { - - if (DNS_TRANSACTION_IS_LIVE(dt->state)) - continue; -diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c -index d68d0c3..ad5061c 100644 ---- a/src/resolve/resolved-dns-trust-anchor.c -+++ b/src/resolve/resolved-dns-trust-anchor.c -@@ -464,7 +464,6 @@ static int domain_name_cmp(char * const *a, char * const *b) { - - static int dns_trust_anchor_dump(DnsTrustAnchor *d) { - DnsAnswer *a; -- Iterator i; - - assert(d); - -@@ -472,7 +471,7 @@ static int dns_trust_anchor_dump(DnsTrustAnchor *d) { - log_info("No positive trust anchors defined."); - else { - log_info("Positive Trust Anchors:"); -- HASHMAP_FOREACH(a, d->positive_by_key, i) { -+ HASHMAP_FOREACH(a, d->positive_by_key) { - DnsResourceRecord *rr; - - DNS_ANSWER_FOREACH(rr, a) -diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c -index 33879d6..f8e1491 100644 ---- a/src/resolve/resolved-dns-zone.c -+++ b/src/resolve/resolved-dns-zone.c -@@ -630,11 +630,10 @@ int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key) { - - void dns_zone_verify_all(DnsZone *zone) { - DnsZoneItem *i; -- Iterator iterator; - - assert(zone); - -- HASHMAP_FOREACH(i, zone->by_key, iterator) { -+ HASHMAP_FOREACH(i, zone->by_key) { - DnsZoneItem *j; - - LIST_FOREACH(by_key, j, i) -@@ -643,7 +642,6 @@ void dns_zone_verify_all(DnsZone *zone) { - } - - void dns_zone_dump(DnsZone *zone, FILE *f) { -- Iterator iterator; - DnsZoneItem *i; - - if (!zone) -@@ -652,7 +650,7 @@ void dns_zone_dump(DnsZone *zone, FILE *f) { - if (!f) - f = stdout; - -- HASHMAP_FOREACH(i, zone->by_key, iterator) { -+ HASHMAP_FOREACH(i, zone->by_key) { - DnsZoneItem *j; - - LIST_FOREACH(by_key, j, i) { -diff --git a/src/resolve/resolved-dnssd-bus.c b/src/resolve/resolved-dnssd-bus.c -index 33efb8e..7798746 100644 ---- a/src/resolve/resolved-dnssd-bus.c -+++ b/src/resolve/resolved-dnssd-bus.c -@@ -14,7 +14,6 @@ int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_ - DnssdService *s = userdata; - DnssdTxtData *txt_data; - Manager *m; -- Iterator i; - Link *l; - int r; - -@@ -32,7 +31,7 @@ int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_ - if (r == 0) - return 1; /* Polkit will call us back */ - -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - if (l->mdns_ipv4_scope) { - r = dns_scope_announce(l->mdns_ipv4_scope, true); - if (r < 0) -@@ -91,7 +90,6 @@ static int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - DnssdService *service; -- Iterator i; - unsigned c = 0; - int r; - -@@ -104,7 +102,7 @@ static int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, - if (!l) - return -ENOMEM; - -- HASHMAP_FOREACH(service, m->dnssd_services, i) { -+ HASHMAP_FOREACH(service, m->dnssd_services) { - char *p; - - r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", service->name, &p); -diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c -index 4458ad1..8ffe45e 100644 ---- a/src/resolve/resolved-dnssd.c -+++ b/src/resolve/resolved-dnssd.c -@@ -6,6 +6,7 @@ - #include "resolved-dnssd.h" - #include "resolved-dns-rr.h" - #include "resolved-manager.h" -+#include "resolved-conf.h" - #include "specifier.h" - #include "strv.h" - -@@ -154,7 +155,7 @@ static int specifier_dnssd_host_name(char specifier, const void *data, const voi - return 0; - } - --int dnssd_render_instance_name(DnssdService *s, char **ret_name) { -+int dnssd_render_instance_name(const char *name_template, char **ret_name) { - static const Specifier specifier_table[] = { - { 'm', specifier_machine_id, NULL }, - { 'b', specifier_boot_id, NULL }, -@@ -170,19 +171,17 @@ int dnssd_render_instance_name(DnssdService *s, char **ret_name) { - _cleanup_free_ char *name = NULL; - int r; - -- assert(s); -- assert(s->name_template); -+ assert(name_template); - -- r = specifier_printf(s->name_template, specifier_table, s, &name); -+ r = specifier_printf(name_template, specifier_table, NULL, &name); - if (r < 0) -- return log_debug_errno(r, "Failed to replace specifiers: %m"); -+ return r; - - if (!dns_service_name_is_valid(name)) -- return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), -- "Service instance name '%s' is invalid.", -- name); -+ return -EINVAL; - -- *ret_name = TAKE_PTR(name); -+ if (ret_name) -+ *ret_name = TAKE_PTR(name); - - return 0; - } -@@ -226,7 +225,7 @@ int dnssd_update_rrs(DnssdService *s) { - LIST_FOREACH(items, txt_data, s->txt_data_items) - txt_data->rr = dns_resource_record_unref(txt_data->rr); - -- r = dnssd_render_instance_name(s, &n); -+ r = dnssd_render_instance_name(s->name_template, &n); - if (r < 0) - return r; - -@@ -333,11 +332,10 @@ int dnssd_txt_item_new_from_data(const char *key, const void *data, const size_t - } - - void dnssd_signal_conflict(Manager *manager, const char *name) { -- Iterator i; - DnssdService *s; - int r; - -- HASHMAP_FOREACH(s, manager->dnssd_services, i) { -+ HASHMAP_FOREACH(s, manager->dnssd_services) { - if (s->withdrawn) - continue; - -diff --git a/src/resolve/resolved-dnssd.h b/src/resolve/resolved-dnssd.h -index f2e1014..304bd89 100644 ---- a/src/resolve/resolved-dnssd.h -+++ b/src/resolve/resolved-dnssd.h -@@ -51,7 +51,7 @@ DnssdTxtData *dnssd_txtdata_free_all(DnssdTxtData *txt_data); - DEFINE_TRIVIAL_CLEANUP_FUNC(DnssdService*, dnssd_service_free); - DEFINE_TRIVIAL_CLEANUP_FUNC(DnssdTxtData*, dnssd_txtdata_free); - --int dnssd_render_instance_name(DnssdService *s, char **ret_name); -+int dnssd_render_instance_name(const char *name_template, char **ret_name); - int dnssd_load(Manager *manager); - int dnssd_txt_item_new_from_string(const char *key, const char *value, DnsTxtItem **ret_item); - int dnssd_txt_item_new_from_data(const char *key, const void *value, const size_t size, DnsTxtItem **ret_item); -diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf -index 553da8d..b54fa1b 100644 ---- a/src/resolve/resolved-gperf.gperf -+++ b/src/resolve/resolved-gperf.gperf -@@ -18,14 +18,15 @@ struct ConfigPerfItem; - %struct-type - %includes - %% --Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0 --Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0 --Resolve.Domains, config_parse_search_domains, 0, 0 --Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support) --Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support) --Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode) --Resolve.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Manager, dns_over_tls_mode) --Resolve.Cache, config_parse_dns_cache_mode, DNS_CACHE_MODE_YES, offsetof(Manager, enable_cache) --Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode) --Resolve.ReadEtcHosts, config_parse_bool, 0, offsetof(Manager, read_etc_hosts) --Resolve.ResolveUnicastSingleLabel, config_parse_bool, 0, offsetof(Manager, resolve_unicast_single_label) -+Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0 -+Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0 -+Resolve.Domains, config_parse_search_domains, 0, 0 -+Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support) -+Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support) -+Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode) -+Resolve.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Manager, dns_over_tls_mode) -+Resolve.Cache, config_parse_dns_cache_mode, DNS_CACHE_MODE_YES, offsetof(Manager, enable_cache) -+Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode) -+Resolve.ReadEtcHosts, config_parse_bool, 0, offsetof(Manager, read_etc_hosts) -+Resolve.ResolveUnicastSingleLabel, config_parse_bool, 0, offsetof(Manager, resolve_unicast_single_label) -+Resolve.DNSStubListenerExtra, config_parse_dns_stub_listener_extra, 0, offsetof(Manager, dns_extra_stub_listeners) -diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c -index 42d4ae7..3665d69 100644 ---- a/src/resolve/resolved-link-bus.c -+++ b/src/resolve/resolved-link-bus.c -@@ -222,7 +222,6 @@ static int property_get_ntas( - - Link *l = userdata; - const char *name; -- Iterator i; - int r; - - assert(reply); -@@ -232,7 +231,7 @@ static int property_get_ntas( - if (r < 0) - return r; - -- SET_FOREACH(name, l->dnssec_negative_trust_anchors, i) { -+ SET_FOREACH(name, l->dnssec_negative_trust_anchors) { - r = sd_bus_message_append(reply, "s", name); - if (r < 0) - return r; -@@ -746,7 +745,6 @@ static int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, c - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - Link *link; -- Iterator i; - unsigned c = 0; - - assert(bus); -@@ -758,7 +756,7 @@ static int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, c - if (!l) - return -ENOMEM; - -- HASHMAP_FOREACH(link, m->links, i) { -+ HASHMAP_FOREACH(link, m->links) { - char *p; - - p = link_bus_path(link); -diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c -index f52c556..79d84dd 100644 ---- a/src/resolve/resolved-link.c -+++ b/src/resolve/resolved-link.c -@@ -1250,11 +1250,10 @@ int link_save_user(Link *l) { - - if (!set_isempty(l->dnssec_negative_trust_anchors)) { - bool space = false; -- Iterator i; - char *nta; - - fputs("NTAS=", f); -- SET_FOREACH(nta, l->dnssec_negative_trust_anchors, i) { -+ SET_FOREACH(nta, l->dnssec_negative_trust_anchors) { - - if (space) - fputc(' ', f); -diff --git a/src/resolve/resolved-llmnr.c b/src/resolve/resolved-llmnr.c -index 61e5034..03f2764 100644 ---- a/src/resolve/resolved-llmnr.c -+++ b/src/resolve/resolved-llmnr.c -@@ -326,7 +326,7 @@ int manager_llmnr_ipv4_tcp_fd(Manager *m) { - return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to create socket: %m"); - - /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ -- r = setsockopt_int(s, IPPROTO_IP, IP_TTL, true); -+ r = setsockopt_int(s, IPPROTO_IP, IP_TTL, 1); - if (r < 0) - return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_TTL: %m"); - -@@ -397,7 +397,7 @@ int manager_llmnr_ipv6_tcp_fd(Manager *m) { - return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to create socket: %m"); - - /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ -- r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, true); -+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 1); - if (r < 0) - return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_UNICAST_HOPS: %m"); - -diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c -index 1da590b..7523c65 100644 ---- a/src/resolve/resolved-manager.c -+++ b/src/resolve/resolved-manager.c -@@ -36,6 +36,7 @@ - #include "resolved-manager.h" - #include "resolved-mdns.h" - #include "resolved-resolv-conf.h" -+#include "resolved-varlink.h" - #include "socket-util.h" - #include "string-table.h" - #include "string-util.h" -@@ -267,7 +268,6 @@ static int manager_rtnl_listen(Manager *m) { - - static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - Manager *m = userdata; -- Iterator i; - Link *l; - int r; - -@@ -275,7 +275,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void * - - sd_network_monitor_flush(m->network_monitor); - -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - r = link_update(l); - if (r < 0) - log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex); -@@ -349,7 +349,8 @@ static int determine_hostname(char **full_hostname, char **llmnr_hostname, char - #if HAVE_LIBIDN2 - r = idn2_to_unicode_8z8z(label, &utf8, 0); - if (r != IDN2_OK) -- return log_error("Failed to undo IDNA: %s", idn2_strerror(r)); -+ return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), -+ "Failed to undo IDNA: %s", idn2_strerror(r)); - assert(utf8_is_valid(utf8)); - - r = strlen(utf8); -@@ -508,7 +509,6 @@ static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si - DnsServer *server; - size_t size = 0; - DnsScope *scope; -- Iterator i; - Link *l; - - assert(s); -@@ -526,7 +526,7 @@ static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si - dns_server_dump(server, f); - LIST_FOREACH(servers, server, m->fallback_dns_servers) - dns_server_dump(server, f); -- HASHMAP_FOREACH(l, m->links, i) -+ HASHMAP_FOREACH(l, m->links) - LIST_FOREACH(servers, server, l->dns_servers) - dns_server_dump(server, f); - -@@ -577,8 +577,6 @@ int manager_new(Manager **ret) { - .llmnr_ipv6_tcp_fd = -1, - .mdns_ipv4_fd = -1, - .mdns_ipv6_fd = -1, -- .dns_stub_udp_fd = -1, -- .dns_stub_tcp_fd = -1, - .hostname_fd = -1, - - .llmnr_support = DEFAULT_LLMNR_MODE, -@@ -663,6 +661,10 @@ int manager_start(Manager *m) { - if (r < 0) - return r; - -+ r = manager_varlink_init(m); -+ if (r < 0) -+ return r; -+ - return 0; - } - -@@ -706,6 +708,9 @@ Manager *manager_free(Manager *m) { - manager_llmnr_stop(m); - manager_mdns_stop(m); - manager_dns_stub_stop(m); -+ manager_varlink_done(m); -+ -+ ordered_set_free(m->dns_extra_stub_listeners); - - bus_verify_polkit_async_registry_free(m->polkit_registry); - -@@ -1059,13 +1064,12 @@ int manager_send( - uint32_t manager_find_mtu(Manager *m) { - uint32_t mtu = 0; - Link *l; -- Iterator i; - - /* If we don't know on which link a DNS packet would be - * delivered, let's find the largest MTU that works on all - * interfaces we know of */ - -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - if (l->mtu <= 0) - continue; - -@@ -1089,7 +1093,6 @@ int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_a - } - - void manager_refresh_rrs(Manager *m) { -- Iterator i; - Link *l; - DnssdService *s; - -@@ -1101,11 +1104,11 @@ void manager_refresh_rrs(Manager *m) { - m->mdns_host_ipv6_key = dns_resource_key_unref(m->mdns_host_ipv6_key); - - if (m->mdns_support == RESOLVE_SUPPORT_YES) -- HASHMAP_FOREACH(s, m->dnssd_services, i) -+ HASHMAP_FOREACH(s, m->dnssd_services) - if (dnssd_update_rrs(s) < 0) - log_warning("Failed to refresh DNS-SD service '%s'", s->name); - -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - link_add_rrs(l, true); - link_add_rrs(l, false); - } -@@ -1173,12 +1176,11 @@ int manager_next_hostname(Manager *m) { - } - - LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) { -- Iterator i; - Link *l; - - assert(m); - -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - LinkAddress *a; - - a = link_find_address(l, family, in_addr); -@@ -1265,7 +1267,6 @@ int manager_is_own_hostname(Manager *m, const char *name) { - - int manager_compile_dns_servers(Manager *m, OrderedSet **dns) { - DnsServer *s; -- Iterator i; - Link *l; - int r; - -@@ -1286,7 +1287,7 @@ int manager_compile_dns_servers(Manager *m, OrderedSet **dns) { - } - - /* Then, add the per-link servers */ -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - LIST_FOREACH(servers, s, l->dns_servers) { - r = ordered_set_put(*dns, s); - if (r == -EEXIST) -@@ -1317,7 +1318,6 @@ int manager_compile_dns_servers(Manager *m, OrderedSet **dns) { - */ - int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_route) { - DnsSearchDomain *d; -- Iterator i; - Link *l; - int r; - -@@ -1341,7 +1341,7 @@ int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_ - return r; - } - -- HASHMAP_FOREACH(l, m->links, i) { -+ HASHMAP_FOREACH(l, m->links) { - - LIST_FOREACH(domains, d, l->search_domains) { - -@@ -1371,7 +1371,6 @@ DnssecMode manager_get_dnssec_mode(Manager *m) { - - bool manager_dnssec_supported(Manager *m) { - DnsServer *server; -- Iterator i; - Link *l; - - assert(m); -@@ -1383,7 +1382,7 @@ bool manager_dnssec_supported(Manager *m) { - if (server && !dns_server_dnssec_supported(server)) - return false; - -- HASHMAP_FOREACH(l, m->links, i) -+ HASHMAP_FOREACH(l, m->links) - if (!link_dnssec_supported(l)) - return false; - -@@ -1416,14 +1415,13 @@ void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResource - } - - bool manager_routable(Manager *m, int family) { -- Iterator i; - Link *l; - - assert(m); - - /* Returns true if the host has at least one interface with a routable address of the specified type */ - -- HASHMAP_FOREACH(l, m->links, i) -+ HASHMAP_FOREACH(l, m->links) - if (link_relevant(l, family, false)) - return true; - -@@ -1442,13 +1440,12 @@ void manager_flush_caches(Manager *m) { - } - - void manager_reset_server_features(Manager *m) { -- Iterator i; - Link *l; - - dns_server_reset_features_all(m->dns_servers); - dns_server_reset_features_all(m->fallback_dns_servers); - -- HASHMAP_FOREACH(l, m->links, i) -+ HASHMAP_FOREACH(l, m->links) - dns_server_reset_features_all(l->dns_servers); - - log_info("Resetting learnt feature levels on all servers."); -@@ -1509,14 +1506,13 @@ void manager_cleanup_saved_user(Manager *m) { - } - - bool manager_next_dnssd_names(Manager *m) { -- Iterator i; - DnssdService *s; - bool tried = false; - int r; - - assert(m); - -- HASHMAP_FOREACH(s, m->dnssd_services, i) { -+ HASHMAP_FOREACH(s, m->dnssd_services) { - _cleanup_free_ char * new_name = NULL; - - if (!s->withdrawn) -diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h -index 59944df..c300521 100644 ---- a/src/resolve/resolved-manager.h -+++ b/src/resolve/resolved-manager.h -@@ -11,13 +11,14 @@ - #include "list.h" - #include "ordered-set.h" - #include "resolve-util.h" -+#include "varlink.h" - - typedef struct Manager Manager; - --#include "resolved-conf.h" - #include "resolved-dns-query.h" - #include "resolved-dns-search-domain.h" - #include "resolved-dns-stream.h" -+#include "resolved-dns-stub.h" - #include "resolved-dns-trust-anchor.h" - #include "resolved-link.h" - -@@ -132,14 +133,15 @@ struct Manager { - dev_t etc_hosts_dev; - bool read_etc_hosts; - -- /* Local DNS stub on 127.0.0.53:53 */ -- int dns_stub_udp_fd; -- int dns_stub_tcp_fd; -+ OrderedSet *dns_extra_stub_listeners; - -+ /* Local DNS stub on 127.0.0.53:53 */ - sd_event_source *dns_stub_udp_event_source; - sd_event_source *dns_stub_tcp_event_source; - - Hashmap *polkit_registry; -+ -+ VarlinkServer *varlink_server; - }; - - /* Manager */ -diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c -index c6f48d6..0de5046 100644 ---- a/src/resolve/resolved-resolv-conf.c -+++ b/src/resolve/resolved-resolv-conf.c -@@ -231,8 +231,6 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { - static void write_resolv_conf_search( - OrderedSet *domains, - FILE *f) { -- unsigned length = 0, count = 0; -- Iterator i; - char *domain; - - assert(domains); -@@ -240,16 +238,7 @@ static void write_resolv_conf_search( - - fputs("search", f); - -- ORDERED_SET_FOREACH(domain, domains, i) { -- if (++count > MAXDNSRCH) { -- fputs("\n# Too many search domains configured, remaining ones ignored.", f); -- break; -- } -- length += strlen(domain) + 1; -- if (length > 256) { -- fputs("\n# Total length of all search domains is too long, remaining ones ignored.", f); -- break; -- } -+ ORDERED_SET_FOREACH(domain, domains) { - fputc(' ', f); - fputs(domain, f); - } -@@ -258,7 +247,6 @@ static void write_resolv_conf_search( - } - - static int write_uplink_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) { -- Iterator i; - - fputs("# This file is managed by man:systemd-resolved(8). Do not edit.\n" - "#\n" -@@ -279,7 +267,7 @@ static int write_uplink_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSe - unsigned count = 0; - DnsServer *s; - -- ORDERED_SET_FOREACH(s, dns, i) -+ ORDERED_SET_FOREACH(s, dns) - write_resolv_conf_server(s, f, &count); - } - -diff --git a/src/resolve/resolved-varlink.c b/src/resolve/resolved-varlink.c -new file mode 100644 -index 0000000..2a65293 ---- /dev/null -+++ b/src/resolve/resolved-varlink.c -@@ -0,0 +1,534 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include "in-addr-util.h" -+#include "resolved-dns-synthesize.h" -+#include "resolved-varlink.h" -+#include "socket-netlink.h" -+ -+typedef struct LookupParameters { -+ int ifindex; -+ uint64_t flags; -+ int family; -+ union in_addr_union address; -+ size_t address_size; -+ char *name; -+} LookupParameters; -+ -+static void lookup_parameters_destroy(LookupParameters *p) { -+ assert(p); -+ free(p->name); -+} -+ -+static int reply_query_state(DnsQuery *q) { -+ -+ assert(q); -+ assert(q->varlink_request); -+ -+ switch (q->state) { -+ -+ case DNS_TRANSACTION_NO_SERVERS: -+ return varlink_error(q->varlink_request, "io.systemd.Resolve.NoNameServers", NULL); -+ -+ case DNS_TRANSACTION_TIMEOUT: -+ return varlink_error(q->varlink_request, "io.systemd.Resolve.QueryTimedOut", NULL); -+ -+ case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED: -+ return varlink_error(q->varlink_request, "io.systemd.Resolve.MaxAttemptsReached", NULL); -+ -+ case DNS_TRANSACTION_INVALID_REPLY: -+ return varlink_error(q->varlink_request, "io.systemd.Resolve.InvalidReply", NULL); -+ -+ case DNS_TRANSACTION_ERRNO: -+ return varlink_error_errno(q->varlink_request, q->answer_errno); -+ -+ case DNS_TRANSACTION_ABORTED: -+ return varlink_error(q->varlink_request, "io.systemd.Resolve.QueryAborted", NULL); -+ -+ case DNS_TRANSACTION_DNSSEC_FAILED: -+ return varlink_errorb(q->varlink_request, "io.systemd.Resolve.DNSSECValidationFailed", -+ JSON_BUILD_OBJECT(JSON_BUILD_PAIR("result", JSON_BUILD_STRING(dnssec_result_to_string(q->answer_dnssec_result))))); -+ -+ case DNS_TRANSACTION_NO_TRUST_ANCHOR: -+ return varlink_error(q->varlink_request, "io.systemd.Resolve.NoTrustAnchor", NULL); -+ -+ case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED: -+ return varlink_error(q->varlink_request, "io.systemd.Resolve.ResourceRecordTypeUnsupported", NULL); -+ -+ case DNS_TRANSACTION_NETWORK_DOWN: -+ return varlink_error(q->varlink_request, "io.systemd.Resolve.NetworkDown", NULL); -+ -+ case DNS_TRANSACTION_NOT_FOUND: -+ /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we -+ * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */ -+ return varlink_errorb(q->varlink_request, "io.systemd.Resolve.DNSError", -+ JSON_BUILD_OBJECT(JSON_BUILD_PAIR("rcode", JSON_BUILD_INTEGER(DNS_RCODE_NXDOMAIN)))); -+ -+ case DNS_TRANSACTION_RCODE_FAILURE: -+ return varlink_errorb(q->varlink_request, "io.systemd.Resolve.DNSError", -+ JSON_BUILD_OBJECT(JSON_BUILD_PAIR("rcode", JSON_BUILD_INTEGER(q->answer_rcode)))); -+ -+ case DNS_TRANSACTION_NULL: -+ case DNS_TRANSACTION_PENDING: -+ case DNS_TRANSACTION_VALIDATING: -+ case DNS_TRANSACTION_SUCCESS: -+ default: -+ assert_not_reached("Impossible state"); -+ } -+} -+ -+static void vl_on_disconnect(VarlinkServer *s, Varlink *link, void *userdata) { -+ DnsQuery *q; -+ -+ assert(s); -+ assert(link); -+ -+ q = varlink_get_userdata(link); -+ if (!q) -+ return; -+ -+ if (!DNS_TRANSACTION_IS_LIVE(q->state)) -+ return; -+ -+ log_debug("Client of active query vanished, aborting query."); -+ dns_query_complete(q, DNS_TRANSACTION_ABORTED); -+} -+ -+static bool validate_and_mangle_flags(uint64_t *flags, uint64_t ok) { -+ assert(flags); -+ -+ /* This checks that the specified client-provided flags parameter actually makes sense, and mangles -+ * it slightly. Specifically: -+ * -+ * 1. We check that only the protocol flags and the NO_CNAME flag are on at most, plus the -+ * method-specific flags specified in 'ok'. -+ * -+ * 2. If no protocols are enabled we automatically convert that to "all protocols are enabled". -+ * -+ * The second rule means that clients can just pass 0 as flags for the common case, and all supported -+ * protocols are enabled. Moreover it's useful so that client's do not have to be aware of all -+ * protocols implemented in resolved, but can use 0 as protocols flags set as indicator for -+ * "everything". -+ */ -+ -+ if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok)) -+ return false; -+ -+ if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */ -+ *flags |= SD_RESOLVED_PROTOCOLS_ALL; -+ -+ return true; -+} -+ -+static void vl_method_resolve_hostname_complete(DnsQuery *q) { -+ _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL; -+ _cleanup_(json_variant_unrefp) JsonVariant *array = NULL; -+ _cleanup_free_ char *normalized = NULL; -+ DnsResourceRecord *rr; -+ DnsQuestion *question; -+ int ifindex, r; -+ -+ assert(q); -+ -+ if (q->state != DNS_TRANSACTION_SUCCESS) { -+ r = reply_query_state(q); -+ goto finish; -+ } -+ -+ r = dns_query_process_cname(q); -+ if (r == -ELOOP) { -+ r = varlink_error(q->varlink_request, "io.systemd.Resolve.CNAMELoop", NULL); -+ goto finish; -+ } -+ if (r < 0) -+ goto finish; -+ if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ -+ return; -+ -+ question = dns_query_question_for_protocol(q, q->answer_protocol); -+ -+ DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { -+ _cleanup_(json_variant_unrefp) JsonVariant *entry = NULL; -+ int family; -+ const void *p; -+ -+ r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); -+ if (r < 0) -+ goto finish; -+ if (r == 0) -+ continue; -+ -+ if (rr->key->type == DNS_TYPE_A) { -+ family = AF_INET; -+ p = &rr->a.in_addr; -+ } else if (rr->key->type == DNS_TYPE_AAAA) { -+ family = AF_INET6; -+ p = &rr->aaaa.in6_addr; -+ } else { -+ r = -EAFNOSUPPORT; -+ goto finish; -+ } -+ -+ r = json_build(&entry, -+ JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR("ifindex", JSON_BUILD_INTEGER(ifindex)), -+ JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(family)), -+ JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(p, FAMILY_ADDRESS_SIZE(family))))); -+ if (r < 0) -+ goto finish; -+ -+ if (!canonical) -+ canonical = dns_resource_record_ref(rr); -+ -+ r = json_variant_append_array(&array, entry); -+ if (r < 0) -+ goto finish; -+ } -+ -+ if (json_variant_is_blank_object(array)) { -+ r = varlink_error(q->varlink_request, "io.systemd.Resolve.NoSuchResourceRecord", NULL); -+ goto finish; -+ } -+ -+ assert(canonical); -+ r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized); -+ if (r < 0) -+ goto finish; -+ -+ r = varlink_replyb(q->varlink_request, -+ JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR("addresses", JSON_BUILD_VARIANT(array)), -+ JSON_BUILD_PAIR("name", JSON_BUILD_STRING(normalized)), -+ JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)))))); -+finish: -+ if (r < 0) { -+ log_error_errno(r, "Failed to send hostname reply: %m"); -+ r = varlink_error_errno(q->varlink_request, r); -+ } -+ -+ dns_query_free(q); -+} -+ -+static int parse_as_address(Varlink *link, LookupParameters *p) { -+ _cleanup_free_ char *canonical = NULL; -+ int r, ff, parsed_ifindex, ifindex; -+ union in_addr_union parsed; -+ -+ assert(link); -+ assert(p); -+ -+ /* Check if this parses as literal address. If so, just parse it and return that, do not involve networking */ -+ r = in_addr_ifindex_from_string_auto(p->name, &ff, &parsed, &parsed_ifindex); -+ if (r < 0) -+ return 0; /* not a literal address */ -+ -+ /* Make sure the data we parsed matches what is requested */ -+ if ((p->family != AF_UNSPEC && ff != p->family) || -+ (p->ifindex > 0 && parsed_ifindex > 0 && parsed_ifindex != p->ifindex)) -+ return varlink_error(link, "io.systemd.Resolve.NoSuchResourceRecord", NULL); -+ -+ ifindex = parsed_ifindex > 0 ? parsed_ifindex : p->ifindex; -+ -+ /* Reformat the address as string, to return as canonicalized name */ -+ r = in_addr_ifindex_to_string(ff, &parsed, ifindex, &canonical); -+ if (r < 0) -+ return r; -+ -+ return varlink_replyb( -+ link, -+ JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR("addresses", -+ JSON_BUILD_ARRAY( -+ JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", JSON_BUILD_INTEGER(ifindex)), -+ JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(ff)), -+ JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(&parsed, FAMILY_ADDRESS_SIZE(ff)))))), -+ JSON_BUILD_PAIR("name", JSON_BUILD_STRING(canonical)), -+ JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(p->flags), ff, true))))); -+} -+ -+static int vl_method_resolve_hostname(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { -+ static const JsonDispatch dispatch_table[] = { -+ { "ifindex", JSON_VARIANT_UNSIGNED, json_dispatch_int, offsetof(LookupParameters, ifindex), 0 }, -+ { "name", JSON_VARIANT_STRING, json_dispatch_string, offsetof(LookupParameters, name), JSON_MANDATORY }, -+ { "family", JSON_VARIANT_UNSIGNED, json_dispatch_int, offsetof(LookupParameters, family), 0 }, -+ { "flags", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(LookupParameters, flags), 0 }, -+ {} -+ }; -+ -+ _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL; -+ _cleanup_(lookup_parameters_destroy) LookupParameters p = { -+ .family = AF_UNSPEC, -+ }; -+ Manager *m = userdata; -+ DnsQuery *q; -+ int r; -+ -+ assert(link); -+ assert(m); -+ -+ if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) -+ return -EINVAL; -+ -+ r = json_dispatch(parameters, dispatch_table, NULL, 0, &p); -+ if (r < 0) -+ return r; -+ -+ if (p.ifindex < 0) -+ return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("ifindex")); -+ -+ r = dns_name_is_valid(p.name); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("name")); -+ -+ if (!IN_SET(p.family, AF_UNSPEC, AF_INET, AF_INET6)) -+ return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("family")); -+ -+ if (!validate_and_mangle_flags(&p.flags, SD_RESOLVED_NO_SEARCH)) -+ return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags")); -+ -+ r = parse_as_address(link, &p); -+ if (r != 0) -+ return r; -+ -+ r = dns_question_new_address(&question_utf8, p.family, p.name, false); -+ if (r < 0) -+ return r; -+ -+ r = dns_question_new_address(&question_idna, p.family, p.name, true); -+ if (r < 0 && r != -EALREADY) -+ return r; -+ -+ r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, p.ifindex, p.flags); -+ if (r < 0) -+ return r; -+ -+ q->varlink_request = varlink_ref(link); -+ varlink_set_userdata(link, q); -+ q->request_family = p.family; -+ q->complete = vl_method_resolve_hostname_complete; -+ -+ r = dns_query_go(q); -+ if (r < 0) -+ goto fail; -+ -+ return 1; -+ -+fail: -+ dns_query_free(q); -+ return r; -+} -+ -+static int json_dispatch_address(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { -+ LookupParameters *p = userdata; -+ union in_addr_union buf = {}; -+ JsonVariant *i; -+ size_t n, k = 0; -+ -+ assert(variant); -+ assert(p); -+ -+ if (!json_variant_is_array(variant)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array.", strna(name)); -+ -+ n = json_variant_elements(variant); -+ if (!IN_SET(n, 4, 16)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is array of unexpected size.", strna(name)); -+ -+ JSON_VARIANT_ARRAY_FOREACH(i, variant) { -+ intmax_t b; -+ -+ if (!json_variant_is_integer(i)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is not an integer.", k, strna(name)); -+ -+ b = json_variant_integer(i); -+ if (b < 0 || b > 0xff) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Element %zu of JSON field '%s' is out of range 0…255.", k, strna(name)); -+ -+ buf.bytes[k++] = (uint8_t) b; -+ } -+ -+ p->address = buf; -+ p->address_size = k; -+ -+ return 0; -+} -+ -+static void vl_method_resolve_address_complete(DnsQuery *q) { -+ _cleanup_(json_variant_unrefp) JsonVariant *array = NULL; -+ DnsQuestion *question; -+ DnsResourceRecord *rr; -+ int ifindex, r; -+ -+ assert(q); -+ -+ if (q->state != DNS_TRANSACTION_SUCCESS) { -+ r = reply_query_state(q); -+ goto finish; -+ } -+ -+ r = dns_query_process_cname(q); -+ if (r == -ELOOP) { -+ r = varlink_error(q->varlink_request, "io.systemd.Resolve.CNAMELoop", NULL); -+ goto finish; -+ } -+ if (r < 0) -+ goto finish; -+ if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ -+ return; -+ -+ question = dns_query_question_for_protocol(q, q->answer_protocol); -+ -+ DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { -+ _cleanup_(json_variant_unrefp) JsonVariant *entry = NULL; -+ _cleanup_free_ char *normalized = NULL; -+ -+ r = dns_question_matches_rr(question, rr, NULL); -+ if (r < 0) -+ goto finish; -+ if (r == 0) -+ continue; -+ -+ r = dns_name_normalize(rr->ptr.name, 0, &normalized); -+ if (r < 0) -+ goto finish; -+ -+ r = json_build(&entry, -+ JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR("ifindex", JSON_BUILD_INTEGER(ifindex)), -+ JSON_BUILD_PAIR("name", JSON_BUILD_STRING(normalized)))); -+ if (r < 0) -+ goto finish; -+ -+ r = json_variant_append_array(&array, entry); -+ if (r < 0) -+ goto finish; -+ } -+ -+ if (json_variant_is_blank_object(array)) { -+ r = varlink_error(q->varlink_request, "io.systemd.Resolve.NoSuchResourceRecord", NULL); -+ goto finish; -+ } -+ -+ r = varlink_replyb(q->varlink_request, -+ JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR("names", JSON_BUILD_VARIANT(array)), -+ JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)))))); -+finish: -+ if (r < 0) { -+ log_error_errno(r, "Failed to send address reply: %m"); -+ r = varlink_error_errno(q->varlink_request, r); -+ } -+ -+ dns_query_free(q); -+} -+ -+static int vl_method_resolve_address(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { -+ static const JsonDispatch dispatch_table[] = { -+ { "ifindex", JSON_VARIANT_UNSIGNED, json_dispatch_int, offsetof(LookupParameters, ifindex), 0 }, -+ { "family", JSON_VARIANT_UNSIGNED, json_dispatch_int, offsetof(LookupParameters, family), JSON_MANDATORY }, -+ { "address", JSON_VARIANT_ARRAY, json_dispatch_address, 0, JSON_MANDATORY }, -+ { "flags", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(LookupParameters, flags), 0 }, -+ {} -+ }; -+ -+ _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; -+ _cleanup_(lookup_parameters_destroy) LookupParameters p = { -+ .family = AF_UNSPEC, -+ }; -+ Manager *m = userdata; -+ DnsQuery *q; -+ int r; -+ -+ assert(link); -+ assert(m); -+ -+ if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) -+ return -EINVAL; -+ -+ r = json_dispatch(parameters, dispatch_table, NULL, 0, &p); -+ if (r < 0) -+ return r; -+ -+ if (p.ifindex < 0) -+ return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("ifindex")); -+ -+ if (!IN_SET(p.family, AF_UNSPEC, AF_INET, AF_INET6)) -+ return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("family")); -+ -+ if (FAMILY_ADDRESS_SIZE(p.family) != p.address_size) -+ return varlink_error(link, "io.systemd.UserDatabase.BadAddressSize", NULL); -+ -+ if (!validate_and_mangle_flags(&p.flags, 0)) -+ return varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags")); -+ -+ r = dns_question_new_reverse(&question, p.family, &p.address); -+ if (r < 0) -+ return r; -+ -+ r = dns_query_new(m, &q, question, question, p.ifindex, p.flags|SD_RESOLVED_NO_SEARCH); -+ if (r < 0) -+ return r; -+ -+ q->varlink_request = varlink_ref(link); -+ varlink_set_userdata(link, q); -+ -+ q->request_family = p.family; -+ q->request_address = p.address; -+ q->complete = vl_method_resolve_address_complete; -+ -+ r = dns_query_go(q); -+ if (r < 0) -+ goto fail; -+ -+ return 1; -+ -+fail: -+ dns_query_free(q); -+ return r; -+} -+ -+int manager_varlink_init(Manager *m) { -+ _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL; -+ int r; -+ -+ assert(m); -+ -+ if (m->varlink_server) -+ return 0; -+ -+ r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID); -+ if (r < 0) -+ return log_error_errno(r, "Failed to allocate varlink server object: %m"); -+ -+ varlink_server_set_userdata(s, m); -+ -+ r = varlink_server_bind_method_many( -+ s, -+ "io.systemd.Resolve.ResolveHostname", vl_method_resolve_hostname, -+ "io.systemd.Resolve.ResolveAddress", vl_method_resolve_address); -+ if (r < 0) -+ return log_error_errno(r, "Failed to register varlink methods: %m"); -+ -+ r = varlink_server_bind_disconnect(s, vl_on_disconnect); -+ if (r < 0) -+ return log_error_errno(r, "Failed to register varlink disconnect handler: %m"); -+ -+ r = varlink_server_listen_address(s, "/run/systemd/resolve/io.systemd.Resolve", 0666); -+ if (r < 0) -+ return log_error_errno(r, "Failed to bind to varlink socket: %m"); -+ -+ r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL); -+ if (r < 0) -+ return log_error_errno(r, "Failed to attach varlink connection to event loop: %m"); -+ -+ m->varlink_server = TAKE_PTR(s); -+ return 0; -+} -+ -+void manager_varlink_done(Manager *m) { -+ assert(m); -+ -+ m->varlink_server = varlink_server_unref(m->varlink_server); -+} -diff --git a/src/resolve/resolved-varlink.h b/src/resolve/resolved-varlink.h -new file mode 100644 -index 0000000..cfb90e5 ---- /dev/null -+++ b/src/resolve/resolved-varlink.h -@@ -0,0 +1,7 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#include "resolved-manager.h" -+ -+int manager_varlink_init(Manager *m); -+void manager_varlink_done(Manager *m); -diff --git a/src/run/run.c b/src/run/run.c -index d4ce396..38446d8 100644 ---- a/src/run/run.c -+++ b/src/run/run.c -@@ -1146,7 +1146,7 @@ static int start_transient_service( - &pty_reply, - "s", arg_host); - if (r < 0) -- return log_error_errno(r, "Failed to get machine PTY: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to get machine PTY: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(pty_reply, "hs", &master, &s); - if (r < 0) -@@ -1468,7 +1468,7 @@ static int start_transient_scope(sd_bus *bus) { - - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) -- return log_error_errno(r, "Failed to start transient scope unit: %s", bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to start transient scope unit: %s", bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "o", &object); - if (r < 0) -@@ -1688,7 +1688,7 @@ static int start_transient_trigger( - - r = sd_bus_call(bus, m, 0, &error, &reply); - if (r < 0) -- return log_error_errno(r, "Failed to start transient %s unit: %s", suffix + 1, bus_error_message(&error, -r)); -+ return log_error_errno(r, "Failed to start transient %s unit: %s", suffix + 1, bus_error_message(&error, r)); - - r = sd_bus_message_read(reply, "o", &object); - if (r < 0) -diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c -index dd2b1ef..7a2767c 100644 ---- a/src/shared/acl-util.c -+++ b/src/shared/acl-util.c -@@ -12,12 +12,13 @@ - #include "user-util.h" - #include "util.h" - --int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) { -+int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *ret_entry) { - acl_entry_t i; - int r; - - assert(acl); -- assert(entry); -+ assert(uid_is_valid(uid)); -+ assert(ret_entry); - - for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); - r > 0; -@@ -41,13 +42,14 @@ int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) { - acl_free(u); - - if (b) { -- *entry = i; -+ *ret_entry = i; - return 1; - } - } - if (r < 0) - return -errno; - -+ *ret_entry = NULL; - return 0; - } - -@@ -376,12 +378,29 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) { - return 0; - } - --int add_acls_for_user(int fd, uid_t uid) { -+/* POSIX says that ACL_{READ,WRITE,EXECUTE} don't have to be bitmasks. But that is a natural thing to do and -+ * all extant implementations do it. Let's make sure that we fail verbosely in the (imho unlikely) scenario -+ * that we get a new implementation that does not satisfy this. */ -+assert_cc(!(ACL_READ & ACL_WRITE)); -+assert_cc(!(ACL_WRITE & ACL_EXECUTE)); -+assert_cc(!(ACL_EXECUTE & ACL_READ)); -+assert_cc((unsigned) ACL_READ == ACL_READ); -+assert_cc((unsigned) ACL_WRITE == ACL_WRITE); -+assert_cc((unsigned) ACL_EXECUTE == ACL_EXECUTE); -+ -+int fd_add_uid_acl_permission( -+ int fd, -+ uid_t uid, -+ unsigned mask) { -+ - _cleanup_(acl_freep) acl_t acl = NULL; - acl_permset_t permset; - acl_entry_t entry; - int r; - -+ /* Adds an ACL entry for the specified file to allow the indicated access to the specified -+ * user. Operates purely incrementally. */ -+ - assert(fd >= 0); - assert(uid_is_valid(uid)); - -@@ -397,10 +416,14 @@ int add_acls_for_user(int fd, uid_t uid) { - return -errno; - } - -- /* We do not recalculate the mask unconditionally here, so that the fchmod() mask above stays -- * intact. */ -- if (acl_get_permset(entry, &permset) < 0 || -- acl_add_perm(permset, ACL_READ) < 0) -+ if (acl_get_permset(entry, &permset) < 0) -+ return -errno; -+ -+ if ((mask & ACL_READ) && acl_add_perm(permset, ACL_READ) < 0) -+ return -errno; -+ if ((mask & ACL_WRITE) && acl_add_perm(permset, ACL_WRITE) < 0) -+ return -errno; -+ if ((mask & ACL_EXECUTE) && acl_add_perm(permset, ACL_EXECUTE) < 0) - return -errno; - - r = calc_acl_mask_if_needed(&acl); -diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h -index 10b2a3d..b6a6f48 100644 ---- a/src/shared/acl-util.h -+++ b/src/shared/acl-util.h -@@ -1,8 +1,10 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - #pragma once - --#if HAVE_ACL -+#include -+#include - -+#if HAVE_ACL - #include - #include - #include -@@ -15,7 +17,7 @@ int add_base_acls_if_needed(acl_t *acl_p, const char *path); - int acl_search_groups(const char* path, char ***ret_groups); - int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask); - int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl); --int add_acls_for_user(int fd, uid_t uid); -+int fd_add_uid_acl_permission(int fd, uid_t uid, unsigned mask); - - /* acl_free takes multiple argument types. - * Multiple cleanup functions are necessary. */ -@@ -27,4 +29,12 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(uid_t*, acl_free_uid_tp); - #define acl_free_gid_tp acl_free - DEFINE_TRIVIAL_CLEANUP_FUNC(gid_t*, acl_free_gid_tp); - -+#else -+#define ACL_READ 0x04 -+#define ACL_WRITE 0x02 -+#define ACL_EXECUTE 0x01 -+ -+static inline int fd_add_uid_acl_permission(int fd, uid_t uid, unsigned mask) { -+ return -EOPNOTSUPP; -+} - #endif -diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c -index 3d0b939..a727b98 100644 ---- a/src/shared/ask-password-api.c -+++ b/src/shared/ask-password-api.c -@@ -237,6 +237,9 @@ int ask_password_plymouth( - - assert(ret); - -+ if (!message) -+ message = "Password:"; -+ - if (flag_file) { - notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); - if (notify < 0) -diff --git a/src/shared/bitmap.h b/src/shared/bitmap.h -index f65a050..312cee9 100644 ---- a/src/shared/bitmap.h -+++ b/src/shared/bitmap.h -@@ -27,8 +27,10 @@ bool bitmap_iterate(const Bitmap *b, Iterator *i, unsigned *n); - - bool bitmap_equal(const Bitmap *a, const Bitmap *b); - --#define BITMAP_FOREACH(n, b, i) \ -- for ((i).idx = 0; bitmap_iterate((b), &(i), (unsigned*)&(n)); ) -+#define _BITMAP_FOREACH(n, b, i) \ -+ for (Iterator i = {}; bitmap_iterate((b), &i, (unsigned*)&(n)); ) -+#define BITMAP_FOREACH(n, b) \ -+ _BITMAP_FOREACH(n, b, UNIQ_T(i, UNIQ)) - - DEFINE_TRIVIAL_CLEANUP_FUNC(Bitmap*, bitmap_free); - -diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c -index 9b0a455..0722b1a 100644 ---- a/src/shared/bus-polkit.c -+++ b/src/shared/bus-polkit.c -@@ -3,6 +3,7 @@ - #include "bus-internal.h" - #include "bus-message.h" - #include "bus-polkit.h" -+#include "bus-util.h" - #include "strv.h" - #include "user-util.h" - -@@ -123,7 +124,7 @@ int bus_test_polkit( - r = sd_bus_call(call->bus, request, 0, ret_error, &reply); - if (r < 0) { - /* Treat no PK available as access denied */ -- if (sd_bus_error_has_name(ret_error, SD_BUS_ERROR_SERVICE_UNKNOWN)) { -+ if (bus_error_is_unknown_service(ret_error)) { - sd_bus_error_free(ret_error); - return -EACCES; - } -@@ -296,8 +297,7 @@ int bus_verify_polkit_async( - e = sd_bus_message_get_error(q->reply); - - /* Treat no PK available as access denied */ -- if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) || -- sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER)) -+ if (bus_error_is_unknown_service(e)) - return -EACCES; - - /* Copy error from polkit reply */ -diff --git a/src/shared/bus-unit-procs.c b/src/shared/bus-unit-procs.c -index b21fe39..5ae54ef 100644 ---- a/src/shared/bus-unit-procs.c -+++ b/src/shared/bus-unit-procs.c -@@ -158,13 +158,12 @@ static int dump_processes( - size_t n = 0, i; - pid_t *pids; - void *pidp; -- Iterator j; - int width; - - /* Order processes by their PID */ - pids = newa(pid_t, hashmap_size(cg->pids)); - -- HASHMAP_FOREACH_KEY(name, pidp, cg->pids, j) -+ HASHMAP_FOREACH_KEY(name, pidp, cg->pids) - pids[n++] = PTR_TO_PID(pidp); - - assert(n == hashmap_size(cg->pids)); -@@ -261,16 +260,14 @@ static int dump_extra_processes( - _cleanup_hashmap_free_ Hashmap *names = NULL; - struct CGroupInfo *cg; - size_t n_allocated = 0, n = 0, k; -- Iterator i; - int width, r; - - /* Prints the extra processes, i.e. those that are in cgroups we haven't displayed yet. We show them as - * combined, sorted, linear list. */ - -- HASHMAP_FOREACH(cg, cgroups, i) { -+ HASHMAP_FOREACH(cg, cgroups) { - const char *name; - void *pidp; -- Iterator j; - - if (cg->done) - continue; -@@ -285,7 +282,7 @@ static int dump_extra_processes( - if (!GREEDY_REALLOC(pids, n_allocated, n + hashmap_size(cg->pids))) - return -ENOMEM; - -- HASHMAP_FOREACH_KEY(name, pidp, cg->pids, j) { -+ HASHMAP_FOREACH_KEY(name, pidp, cg->pids) { - pids[n++] = PTR_TO_PID(pidp); - - r = hashmap_put(names, pidp, (void*) name); -diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c -index f2652ed..3ae3c12 100644 ---- a/src/shared/bus-unit-util.c -+++ b/src/shared/bus-unit-util.c -@@ -10,6 +10,7 @@ - #include "condition.h" - #include "coredump-util.h" - #include "cpu-set-util.h" -+#include "dissect-image.h" - #include "escape.h" - #include "exec-util.h" - #include "exit-status.h" -@@ -18,6 +19,7 @@ - #include "hostname-util.h" - #include "in-addr-util.h" - #include "ip-protocol-list.h" -+#include "libmount-util.h" - #include "locale-util.h" - #include "log.h" - #include "missing_fs.h" -@@ -28,6 +30,9 @@ - #include "path-util.h" - #include "process-util.h" - #include "rlimit-util.h" -+#if HAVE_SECCOMP -+#include "seccomp-util.h" -+#endif - #include "securebits-util.h" - #include "signal-util.h" - #include "socket-util.h" -@@ -105,7 +110,10 @@ DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string); - DEFINE_BUS_APPEND_PARSE("i", ip_tos_from_string); - DEFINE_BUS_APPEND_PARSE("i", log_facility_unshifted_from_string); - DEFINE_BUS_APPEND_PARSE("i", log_level_from_string); --DEFINE_BUS_APPEND_PARSE("i", parse_errno); -+#if !HAVE_SECCOMP -+static inline int seccomp_parse_errno_or_action(const char *eq) { return -EINVAL; } -+#endif -+DEFINE_BUS_APPEND_PARSE("i", seccomp_parse_errno_or_action); - DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string); - DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string); - DEFINE_BUS_APPEND_PARSE("i", signal_from_string); -@@ -338,7 +346,7 @@ static int bus_append_exec_command(sd_bus_message *m, const char *field, const c - return log_error_errno(r, "Failed to parse path: %m"); - } - -- r = strv_split_extract(&l, eq, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE); -+ r = strv_split_full(&l, eq, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE); - if (r < 0) - return log_error_errno(r, "Failed to parse command line: %m"); - -@@ -853,6 +861,8 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con - "RuntimeDirectoryPreserve", - "Personality", - "KeyringMode", -+ "ProtectProc", -+ "ProcSubset", - "NetworkNamespacePath", - "LogNamespace")) - return bus_append_string(m, field, eq); -@@ -923,7 +933,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con - return bus_append_parse_nice(m, field, eq); - - if (streq(field, "SystemCallErrorNumber")) -- return bus_append_parse_errno(m, field, eq); -+ return bus_append_seccomp_parse_errno_or_action(m, field, eq); - - if (streq(field, "IOSchedulingClass")) - return bus_append_ioprio_class_from_string(m, field, eq); -@@ -969,6 +979,117 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con - return 1; - } - -+ if (streq(field, "SetCredential")) { -+ r = sd_bus_message_open_container(m, 'r', "sv"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append_basic(m, 's', "SetCredential"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_open_container(m, 'v', "a(say)"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ if (isempty(eq)) -+ r = sd_bus_message_append(m, "a(say)", 0); -+ else { -+ _cleanup_free_ char *word = NULL, *unescaped = NULL; -+ const char *p = eq; -+ int l; -+ -+ r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse SetCredential= parameter: %s", eq); -+ if (r == 0 || !p) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing argument to SetCredential=."); -+ -+ l = cunescape(p, UNESCAPE_ACCEPT_NUL, &unescaped); -+ if (l < 0) -+ return log_error_errno(l, "Failed to unescape SetCredential= value: %s", p); -+ -+ r = sd_bus_message_open_container(m, 'a', "(say)"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_open_container(m, 'r', "say"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append(m, "s", word); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append_array(m, 'y', unescaped, l); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ } -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ return 1; -+ } -+ -+ if (streq(field, "LoadCredential")) { -+ r = sd_bus_message_open_container(m, 'r', "sv"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append_basic(m, 's', "LoadCredential"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_open_container(m, 'v', "a(ss)"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ if (isempty(eq)) -+ r = sd_bus_message_append(m, "a(ss)", 0); -+ else { -+ _cleanup_free_ char *word = NULL; -+ const char *p = eq; -+ -+ r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ if (r == -ENOMEM) -+ return log_oom(); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse LoadCredential= parameter: %s", eq); -+ if (r == 0 || !p) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Missing argument to LoadCredential=."); -+ -+ r = sd_bus_message_append(m, "a(ss)", 1, word, p); -+ } -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ return 1; -+ } -+ - if (streq(field, "LogExtraFields")) { - r = sd_bus_message_open_container(m, 'r', "sv"); - if (r < 0) -@@ -1160,9 +1281,15 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con - _cleanup_free_ uint8_t *array = NULL; - size_t allocated; - -- r = parse_cpu_set(eq, &nodes); -- if (r < 0) -- return log_error_errno(r, "Failed to parse %s value: %s", field, eq); -+ if (eq && streq(eq, "all")) { -+ r = numa_mask_add_all(&nodes); -+ if (r < 0) -+ return log_error_errno(r, "Failed to create NUMA mask representing \"all\" NUMA nodes: %m"); -+ } else { -+ r = parse_cpu_set(eq, &nodes); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse %s value: %s", field, eq); -+ } - - r = cpu_set_to_dbus(&nodes, &array, &allocated); - if (r < 0) -@@ -1172,7 +1299,8 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con - } - - if (STR_IN_SET(field, "RestrictAddressFamilies", -- "SystemCallFilter")) { -+ "SystemCallFilter", -+ "SystemCallLog")) { - int allow_list = 1; - const char *p = eq; - -@@ -1454,6 +1582,167 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con - return bus_append_byte_array(m, field, roothash_sig_decoded, roothash_sig_decoded_size); - } - -+ if (streq(field, "RootImageOptions")) { -+ _cleanup_strv_free_ char **l = NULL; -+ char **first = NULL, **second = NULL; -+ const char *p = eq; -+ -+ r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_open_container(m, 'v', "a(ss)"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_open_container(m, 'a', "(ss)"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = strv_split_colon_pairs(&l, p); -+ if (r < 0) -+ return log_error_errno(r, "Failed to parse argument: %m"); -+ -+ STRV_FOREACH_PAIR(first, second, l) { -+ /* Format is either 'root:foo' or 'foo' (root is implied) */ -+ if (!isempty(*second) && partition_designator_from_string(*first) < 0) -+ return bus_log_create_error(-EINVAL); -+ -+ r = sd_bus_message_append(m, "(ss)", -+ !isempty(*second) ? *first : "root", -+ !isempty(*second) ? *second : *first); -+ if (r < 0) -+ return bus_log_create_error(r); -+ } -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ return 1; -+ } -+ -+ if (streq(field, "MountImages")) { -+ const char *p = eq; -+ -+ r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_open_container(m, 'v', "a(ssba(ss))"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_open_container(m, 'a', "(ssba(ss))"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ for (;;) { -+ _cleanup_free_ char *first = NULL, *second = NULL, *tuple = NULL; -+ const char *q = NULL, *source = NULL; -+ bool permissive = false; -+ -+ r = extract_first_word(&p, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; -+ -+ q = tuple; -+ r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &first, &second, NULL); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ continue; -+ -+ source = first; -+ if (source[0] == '-') { -+ permissive = true; -+ source++; -+ } -+ -+ if (isempty(second)) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "Missing argument after ':': %s", -+ eq); -+ -+ r = sd_bus_message_open_container(m, 'r', "ssba(ss)"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append(m, "ssb", source, second, permissive); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_open_container(m, 'a', "(ss)"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ for (;;) { -+ _cleanup_free_ char *partition = NULL, *mount_options = NULL; -+ -+ r = extract_many_words(&q, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &partition, &mount_options, NULL); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ break; -+ /* Single set of options, applying to the root partition/single filesystem */ -+ if (r == 1) { -+ r = sd_bus_message_append(m, "(ss)", "root", partition); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ break; -+ } -+ -+ if (partition_designator_from_string(partition) < 0) -+ return bus_log_create_error(-EINVAL); -+ -+ r = sd_bus_message_append(m, "(ss)", partition, mount_options); -+ if (r < 0) -+ return bus_log_create_error(r); -+ } -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ } -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ return 1; -+ } -+ - return 0; - } - -@@ -1680,6 +1969,7 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons - int r; - - if (STR_IN_SET(field, "Accept", -+ "FlushPending", - "Writable", - "KeepAlive", - "NoDelay", -diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c -index 77c1c62..9a306da 100644 ---- a/src/shared/bus-util.c -+++ b/src/shared/bus-util.c -@@ -14,14 +14,13 @@ - #include "sd-event.h" - #include "sd-id128.h" - --/* #include "alloc-util.h" */ -+#include "bus-common-errors.h" - #include "bus-internal.h" - #include "bus-label.h" - #include "bus-util.h" - #include "path-util.h" - #include "socket-util.h" - #include "stdio-util.h" --/* #include "string-util.h" */ - - static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - sd_event *e = userdata; -@@ -153,6 +152,13 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { - return has_owner; - } - -+bool bus_error_is_unknown_service(const sd_bus_error *error) { -+ return sd_bus_error_has_names(error, -+ SD_BUS_ERROR_SERVICE_UNKNOWN, -+ SD_BUS_ERROR_NAME_HAS_NO_OWNER, -+ BUS_ERROR_NO_SUCH_UNIT); -+} -+ - int bus_check_peercred(sd_bus *c) { - struct ucred ucred; - int fd, r; -diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h -index d98e004..9b86f95 100644 ---- a/src/shared/bus-util.h -+++ b/src/shared/bus-util.h -@@ -28,6 +28,7 @@ typedef bool (*check_idle_t)(void *userdata); - int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout, check_idle_t check_idle, void *userdata); - - int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error); -+bool bus_error_is_unknown_service(const sd_bus_error *error); - - int bus_check_peercred(sd_bus *c); - -diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c -index e8398cb..e999564 100644 ---- a/src/shared/cgroup-setup.c -+++ b/src/shared/cgroup-setup.c -@@ -166,7 +166,7 @@ static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct - - int cg_trim(const char *controller, const char *path, bool delete_root) { - _cleanup_free_ char *fs = NULL; -- int r = 0, q; -+ int r, q; - - assert(path); - -@@ -608,8 +608,6 @@ int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path - n = cgroup_controller_to_string(c); - if (FLAGS_SET(mask, bit)) - (void) cg_create(n, path); -- else -- (void) cg_trim(n, path, true); - - done |= CGROUP_MASK_EXTEND_JOINED(bit); - } -@@ -618,8 +616,6 @@ int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path - } - - int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) { -- CGroupController c; -- CGroupMask done; - int r; - - r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid); -@@ -633,9 +629,9 @@ int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_m - return 0; - - supported &= CGROUP_MASK_V1; -- done = 0; -+ CGroupMask done = 0; - -- for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { -+ for (CGroupController c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { - CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); - const char *p = NULL; - -@@ -657,46 +653,20 @@ int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_m - return 0; - } - --int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, cg_migrate_callback_t path_callback, void *userdata) { -- Iterator i; -- void *pidp; -- int r = 0; -- -- SET_FOREACH(pidp, pids, i) { -- pid_t pid = PTR_TO_PID(pidp); -- int q; -- -- q = cg_attach_everywhere(supported, path, pid, path_callback, userdata); -- if (q < 0 && r >= 0) -- r = q; -- } -- -- return r; --} -- --int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) { -+int cg_migrate_v1_controllers(CGroupMask supported, CGroupMask mask, const char *from, cg_migrate_callback_t to_callback, void *userdata) { - CGroupController c; - CGroupMask done; - int r = 0, q; - -- if (!path_equal(from, to)) { -- r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, CGROUP_REMOVE); -- if (r < 0) -- return r; -- } -- -- q = cg_all_unified(); -- if (q < 0) -- return q; -- if (q > 0) -- return r; -+ assert(to_callback); - - supported &= CGROUP_MASK_V1; -+ mask = CGROUP_MASK_EXTEND_JOINED(mask); - done = 0; - - for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { - CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); -- const char *p = NULL; -+ const char *to = NULL; - - if (!FLAGS_SET(supported, bit)) - continue; -@@ -704,21 +674,20 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to - if (FLAGS_SET(done, bit)) - continue; - -- if (to_callback) -- p = to_callback(bit, userdata); -- if (!p) -- p = to; -+ if (!FLAGS_SET(mask, bit)) -+ continue; - -- (void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, 0); -- done |= CGROUP_MASK_EXTEND_JOINED(bit); -+ to = to_callback(bit, userdata); -+ -+ /* Remember first error and try continuing */ -+ q = cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, from, cgroup_controller_to_string(c), to, 0); -+ r = (r < 0) ? r : q; - } - - return r; - } - - int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) { -- CGroupController c; -- CGroupMask done; - int r, q; - - r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root); -@@ -731,7 +700,16 @@ int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) - if (q > 0) - return r; - -+ return cg_trim_v1_controllers(supported, _CGROUP_MASK_ALL, path, delete_root); -+} -+ -+int cg_trim_v1_controllers(CGroupMask supported, CGroupMask mask, const char *path, bool delete_root) { -+ CGroupController c; -+ CGroupMask done; -+ int r = 0, q; -+ - supported &= CGROUP_MASK_V1; -+ mask = CGROUP_MASK_EXTEND_JOINED(mask); - done = 0; - - for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { -@@ -743,7 +721,11 @@ int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) - if (FLAGS_SET(done, bit)) - continue; - -- (void) cg_trim(cgroup_controller_to_string(c), path, delete_root); -+ if (FLAGS_SET(mask, bit)) { -+ /* Remember first error and try continuing */ -+ q = cg_trim(cgroup_controller_to_string(c), path, delete_root); -+ r = (r < 0) ? r : q; -+ } - done |= CGROUP_MASK_EXTEND_JOINED(bit); - } - -diff --git a/src/shared/cgroup-setup.h b/src/shared/cgroup-setup.h -index 6e9b685..43ce32e 100644 ---- a/src/shared/cgroup-setup.h -+++ b/src/shared/cgroup-setup.h -@@ -28,7 +28,7 @@ int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const ch - - int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path); - int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t callback, void *userdata); --int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, cg_migrate_callback_t callback, void *userdata); --int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t callback, void *userdata); -+int cg_migrate_v1_controllers(CGroupMask supported, CGroupMask mask, const char *from, cg_migrate_callback_t to_callback, void *userdata); - int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root); -+int cg_trim_v1_controllers(CGroupMask supported, CGroupMask mask, const char *path, bool delete_root); - int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p, CGroupMask *ret_result_mask); -diff --git a/src/shared/clock-util.c b/src/shared/clock-util.c -index 32cce1e..0f0dd82 100644 ---- a/src/shared/clock-util.c -+++ b/src/shared/clock-util.c -@@ -142,15 +142,25 @@ int clock_reset_timewarp(void) { - return 0; - } - --#define TIME_EPOCH_USEC ((usec_t) TIME_EPOCH * USEC_PER_SEC) -+#define EPOCH_FILE "/usr/lib/clock-epoch" - - int clock_apply_epoch(void) { -+ struct stat st; - struct timespec ts; -+ usec_t epoch_usec; - -- if (now(CLOCK_REALTIME) >= TIME_EPOCH_USEC) -+ if (stat(EPOCH_FILE, &st) < 0) { -+ if (errno != ENOENT) -+ log_warning_errno(errno, "Cannot stat %s: %m\n", EPOCH_FILE); -+ -+ epoch_usec = ((usec_t) TIME_EPOCH * USEC_PER_SEC); -+ } else -+ epoch_usec = timespec_load(&st.st_mtim); -+ -+ if (now(CLOCK_REALTIME) >= epoch_usec) - return 0; - -- if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, TIME_EPOCH_USEC)) < 0) -+ if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, epoch_usec)) < 0) - return -errno; - - return 1; -diff --git a/src/shared/condition.c b/src/shared/condition.c -index bf3b5fa..1f61056 100644 ---- a/src/shared/condition.c -+++ b/src/shared/condition.c -@@ -52,7 +52,7 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger - - assert(type >= 0); - assert(type < _CONDITION_TYPE_MAX); -- assert((!parameter) == (type == CONDITION_NULL)); -+ assert(parameter); - - c = new(Condition, 1); - if (!c) -@@ -776,15 +776,6 @@ static int condition_test_file_is_executable(Condition *c, char **env) { - (st.st_mode & 0111)); - } - --static int condition_test_null(Condition *c, char **env) { -- assert(c); -- assert(c->type == CONDITION_NULL); -- -- /* Note that during parsing we already evaluate the string and -- * store it in c->negate */ -- return true; --} -- - int condition_test(Condition *c, char **env) { - - static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c, char **env) = { -@@ -811,7 +802,6 @@ int condition_test(Condition *c, char **env) { - [CONDITION_USER] = condition_test_user, - [CONDITION_GROUP] = condition_test_group, - [CONDITION_CONTROL_GROUP_CONTROLLER] = condition_test_control_group_controller, -- [CONDITION_NULL] = condition_test_null, - [CONDITION_CPUS] = condition_test_cpus, - [CONDITION_MEMORY] = condition_test_memory, - [CONDITION_ENVIRONMENT] = condition_test_environment, -@@ -859,23 +849,20 @@ bool condition_test_list( - r = condition_test(c, env); - - if (logger) { -- const char *p = c->type == CONDITION_NULL ? "true" : c->parameter; -- assert(p); -- - if (r < 0) - logger(userdata, LOG_WARNING, r, PROJECT_FILE, __LINE__, __func__, - "Couldn't determine result for %s=%s%s%s, assuming failed: %m", - to_string(c->type), - c->trigger ? "|" : "", - c->negate ? "!" : "", -- p); -+ c->parameter); - else - logger(userdata, LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__, - "%s=%s%s%s %s.", - to_string(c->type), - c->trigger ? "|" : "", - c->negate ? "!" : "", -- p, -+ c->parameter, - condition_result_to_string(c->result)); - } - -@@ -937,7 +924,6 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { - [CONDITION_USER] = "ConditionUser", - [CONDITION_GROUP] = "ConditionGroup", - [CONDITION_CONTROL_GROUP_CONTROLLER] = "ConditionControlGroupController", -- [CONDITION_NULL] = "ConditionNull", - [CONDITION_CPUS] = "ConditionCPUs", - [CONDITION_MEMORY] = "ConditionMemory", - [CONDITION_ENVIRONMENT] = "ConditionEnvironment", -@@ -969,7 +955,6 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = { - [CONDITION_USER] = "AssertUser", - [CONDITION_GROUP] = "AssertGroup", - [CONDITION_CONTROL_GROUP_CONTROLLER] = "AssertControlGroupController", -- [CONDITION_NULL] = "AssertNull", - [CONDITION_CPUS] = "AssertCPUs", - [CONDITION_MEMORY] = "AssertMemory", - [CONDITION_ENVIRONMENT] = "AssertEnvironment", -diff --git a/src/shared/condition.h b/src/shared/condition.h -index fea74d2..e5ad43f 100644 ---- a/src/shared/condition.h -+++ b/src/shared/condition.h -@@ -34,8 +34,6 @@ typedef enum ConditionType { - CONDITION_FILE_NOT_EMPTY, - CONDITION_FILE_IS_EXECUTABLE, - -- CONDITION_NULL, -- - CONDITION_USER, - CONDITION_GROUP, - -diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c -index 0fec79f..90f0825 100644 ---- a/src/shared/conf-parser.c -+++ b/src/shared/conf-parser.c -@@ -183,14 +183,12 @@ static int parse_line( - k = strlen(l); - assert(k > 0); - -- if (l[k-1] != ']') { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid section header '%s'", l); -- return -EBADMSG; -- } -+ if (l[k-1] != ']') -+ return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EBADMSG), "Invalid section header '%s'", l); - - n = strndup(l+1, k-2); - if (!n) -- return -ENOMEM; -+ return log_oom(); - - if (sections && !nulstr_contains(sections, n)) { - bool ignore = flags & CONFIG_PARSE_RELAXED; -diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h -index 7c9f553..57787ea 100644 ---- a/src/shared/conf-parser.h -+++ b/src/shared/conf-parser.h -@@ -239,10 +239,10 @@ typedef enum Disabled { - - #define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid, msg) \ - CONFIG_PARSER_PROTOTYPE(function) { \ -- type **enums = data, x, *ys; \ -+ type **enums = data; \ - _cleanup_free_ type *xs = NULL; \ -- const char *word, *state; \ -- size_t l, i = 0; \ -+ size_t i = 0; \ -+ int r; \ - \ - assert(filename); \ - assert(lvalue); \ -@@ -255,29 +255,32 @@ typedef enum Disabled { - \ - *xs = invalid; \ - \ -- FOREACH_WORD(word, l, rvalue, state) { \ -+ for (const char *p = rvalue;;) { \ - _cleanup_free_ char *en = NULL; \ -- type *new_xs; \ -+ type x, *new_xs; \ - \ -- en = strndup(word, l); \ -- if (!en) \ -+ r = extract_first_word(&p, &en, NULL, 0); \ -+ if (r == -ENOMEM) \ - return log_oom(); \ -+ if (r < 0) \ -+ return log_syntax(unit, LOG_ERR, filename, line, 0, \ -+ msg ": %s", en); \ -+ if (r == 0) \ -+ break; \ - \ - if ((x = name##_from_string(en)) < 0) { \ -- log_syntax(unit, LOG_WARNING, filename, line, 0, \ -+ log_syntax(unit, LOG_WARNING, filename, line, 0, \ - msg ", ignoring: %s", en); \ - continue; \ - } \ - \ -- for (ys = xs; x != invalid && *ys != invalid; ys++) { \ -- if (*ys == x) { \ -- log_syntax(unit, LOG_NOTICE, filename, \ -- line, 0, \ -- "Duplicate entry, ignoring: %s", \ -+ for (type *ys = xs; x != invalid && *ys != invalid; ys++) \ -+ if (*ys == x) { \ -+ log_syntax(unit, LOG_NOTICE, filename, line, 0, \ -+ "Duplicate entry, ignoring: %s", \ - en); \ - x = invalid; \ - } \ -- } \ - \ - if (x == invalid) \ - continue; \ -@@ -292,6 +295,5 @@ typedef enum Disabled { - *(xs + i) = invalid; \ - } \ - \ -- free_and_replace(*enums, xs); \ -- return 0; \ -+ return free_and_replace(*enums, xs); \ - } -diff --git a/src/shared/cpu-set-util.c b/src/shared/cpu-set-util.c -index 9b92383..8779d1d 100644 ---- a/src/shared/cpu-set-util.c -+++ b/src/shared/cpu-set-util.c -@@ -105,7 +105,7 @@ int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) { - return 0; - } - --static int cpu_set_add(CPUSet *cpu_set, unsigned cpu) { -+int cpu_set_add(CPUSet *cpu_set, unsigned cpu) { - int r; - - if (cpu >= 8192) -diff --git a/src/shared/cpu-set-util.h b/src/shared/cpu-set-util.h -index a60d4ec..9ec83f6 100644 ---- a/src/shared/cpu-set-util.h -+++ b/src/shared/cpu-set-util.h -@@ -20,6 +20,7 @@ static inline void cpu_set_reset(CPUSet *a) { - } - - int cpu_set_add_all(CPUSet *a, const CPUSet *b); -+int cpu_set_add(CPUSet *a, unsigned cpu); - - char* cpu_set_to_string(const CPUSet *a); - char *cpu_set_to_range_string(const CPUSet *a); -diff --git a/src/shared/crypt-util.c b/src/shared/crypt-util.c -deleted file mode 100644 -index 20bdc54..0000000 ---- a/src/shared/crypt-util.c -+++ /dev/null -@@ -1,28 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ -- --#if HAVE_LIBCRYPTSETUP --#include "crypt-util.h" --#include "log.h" -- --void cryptsetup_log_glue(int level, const char *msg, void *usrptr) { -- switch (level) { -- case CRYPT_LOG_NORMAL: -- level = LOG_NOTICE; -- break; -- case CRYPT_LOG_ERROR: -- level = LOG_ERR; -- break; -- case CRYPT_LOG_VERBOSE: -- level = LOG_INFO; -- break; -- case CRYPT_LOG_DEBUG: -- level = LOG_DEBUG; -- break; -- default: -- log_error("Unknown libcryptsetup log level: %d", level); -- level = LOG_ERR; -- } -- -- log_full(level, "%s", msg); --} --#endif -diff --git a/src/shared/crypt-util.h b/src/shared/crypt-util.h -deleted file mode 100644 -index c25b115..0000000 ---- a/src/shared/crypt-util.h -+++ /dev/null -@@ -1,12 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ --#pragma once -- --#if HAVE_LIBCRYPTSETUP --#include -- --#include "macro.h" -- --DEFINE_TRIVIAL_CLEANUP_FUNC(struct crypt_device *, crypt_free); -- --void cryptsetup_log_glue(int level, const char *msg, void *usrptr); --#endif -diff --git a/src/shared/cryptsetup-util.c b/src/shared/cryptsetup-util.c -new file mode 100644 -index 0000000..9d86478 ---- /dev/null -+++ b/src/shared/cryptsetup-util.c -@@ -0,0 +1,111 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#if HAVE_LIBCRYPTSETUP -+#include "alloc-util.h" -+#include "cryptsetup-util.h" -+#include "dlfcn-util.h" -+#include "log.h" -+ -+static void *cryptsetup_dl = NULL; -+ -+int (*sym_crypt_activate_by_passphrase)(struct crypt_device *cd, const char *name, int keyslot, const char *passphrase, size_t passphrase_size, uint32_t flags); -+#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY -+int (*sym_crypt_activate_by_signed_key)(struct crypt_device *cd, const char *name, const char *volume_key, size_t volume_key_size, const char *signature, size_t signature_size, uint32_t flags); -+#endif -+int (*sym_crypt_activate_by_volume_key)(struct crypt_device *cd, const char *name, const char *volume_key, size_t volume_key_size, uint32_t flags); -+int (*sym_crypt_deactivate_by_name)(struct crypt_device *cd, const char *name, uint32_t flags); -+int (*sym_crypt_format)(struct crypt_device *cd, const char *type, const char *cipher, const char *cipher_mode, const char *uuid, const char *volume_key, size_t volume_key_size, void *params); -+void (*sym_crypt_free)(struct crypt_device *cd); -+const char *(*sym_crypt_get_dir)(void); -+int (*sym_crypt_get_verity_info)(struct crypt_device *cd, struct crypt_params_verity *vp); -+int (*sym_crypt_init)(struct crypt_device **cd, const char *device); -+int (*sym_crypt_init_by_name)(struct crypt_device **cd, const char *name); -+int (*sym_crypt_keyslot_add_by_volume_key)(struct crypt_device *cd, int keyslot, const char *volume_key, size_t volume_key_size, const char *passphrase, size_t passphrase_size); -+int (*sym_crypt_load)(struct crypt_device *cd, const char *requested_type, void *params); -+int (*sym_crypt_resize)(struct crypt_device *cd, const char *name, uint64_t new_size); -+int (*sym_crypt_set_data_device)(struct crypt_device *cd, const char *device); -+void (*sym_crypt_set_debug_level)(int level); -+void (*sym_crypt_set_log_callback)(struct crypt_device *cd, void (*log)(int level, const char *msg, void *usrptr), void *usrptr); -+int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size); -+ -+int dlopen_cryptsetup(void) { -+ _cleanup_(dlclosep) void *dl = NULL; -+ int r; -+ -+ if (cryptsetup_dl) -+ return 0; /* Already loaded */ -+ -+ dl = dlopen("libcryptsetup.so.12", RTLD_LAZY); -+ if (!dl) -+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), -+ "libcryptsetup support is not installed: %s", dlerror()); -+ -+ r = dlsym_many_and_warn( -+ dl, -+ LOG_DEBUG, -+ &sym_crypt_activate_by_passphrase, "crypt_activate_by_passphrase", -+#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY -+ &sym_crypt_activate_by_signed_key, "crypt_activate_by_signed_key", -+#endif -+ &sym_crypt_activate_by_volume_key, "crypt_activate_by_volume_key", -+ &sym_crypt_deactivate_by_name, "crypt_deactivate_by_name", -+ &sym_crypt_format, "crypt_format", -+ &sym_crypt_free, "crypt_free", -+ &sym_crypt_get_dir, "crypt_get_dir", -+ &sym_crypt_get_verity_info, "crypt_get_verity_info", -+ &sym_crypt_init, "crypt_init", -+ &sym_crypt_init_by_name, "crypt_init_by_name", -+ &sym_crypt_keyslot_add_by_volume_key, "crypt_keyslot_add_by_volume_key", -+ &sym_crypt_load, "crypt_load", -+ &sym_crypt_resize, "crypt_resize", -+ &sym_crypt_set_data_device, "crypt_set_data_device", -+ &sym_crypt_set_debug_level, "crypt_set_debug_level", -+ &sym_crypt_set_log_callback, "crypt_set_log_callback", -+ &sym_crypt_volume_key_get, "crypt_volume_key_get", -+ NULL); -+ if (r < 0) -+ return r; -+ -+ /* Note that we never release the reference here, because there's no real reason to, after all this -+ * was traditionally a regular shared library dependency which lives forever too. */ -+ cryptsetup_dl = TAKE_PTR(dl); -+ return 1; -+} -+ -+static void cryptsetup_log_glue(int level, const char *msg, void *usrptr) { -+ -+ switch (level) { -+ case CRYPT_LOG_NORMAL: -+ level = LOG_NOTICE; -+ break; -+ case CRYPT_LOG_ERROR: -+ level = LOG_ERR; -+ break; -+ case CRYPT_LOG_VERBOSE: -+ level = LOG_INFO; -+ break; -+ case CRYPT_LOG_DEBUG: -+ level = LOG_DEBUG; -+ break; -+ default: -+ log_error("Unknown libcryptsetup log level: %d", level); -+ level = LOG_ERR; -+ } -+ -+ log_full(level, "%s", msg); -+} -+ -+void cryptsetup_enable_logging(struct crypt_device *cd) { -+ if (!cd) -+ return; -+ -+ if (dlopen_cryptsetup() < 0) /* If this fails, let's gracefully ignore the issue, this is just debug -+ * logging after all, and if this failed we already generated a debug -+ * log message that should help to track things down. */ -+ return; -+ -+ sym_crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ sym_crypt_set_debug_level(DEBUG_LOGGING ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE); -+} -+ -+#endif -diff --git a/src/shared/cryptsetup-util.h b/src/shared/cryptsetup-util.h -new file mode 100644 -index 0000000..046953b ---- /dev/null -+++ b/src/shared/cryptsetup-util.h -@@ -0,0 +1,36 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#include "macro.h" -+ -+#if HAVE_LIBCRYPTSETUP -+#include -+ -+extern int (*sym_crypt_activate_by_passphrase)(struct crypt_device *cd, const char *name, int keyslot, const char *passphrase, size_t passphrase_size, uint32_t flags); -+#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY -+extern int (*sym_crypt_activate_by_signed_key)(struct crypt_device *cd, const char *name, const char *volume_key, size_t volume_key_size, const char *signature, size_t signature_size, uint32_t flags); -+#endif -+extern int (*sym_crypt_activate_by_volume_key)(struct crypt_device *cd, const char *name, const char *volume_key, size_t volume_key_size, uint32_t flags); -+extern int (*sym_crypt_deactivate_by_name)(struct crypt_device *cd, const char *name, uint32_t flags); -+extern int (*sym_crypt_format)(struct crypt_device *cd, const char *type, const char *cipher, const char *cipher_mode, const char *uuid, const char *volume_key, size_t volume_key_size, void *params); -+extern void (*sym_crypt_free)(struct crypt_device *cd); -+extern const char *(*sym_crypt_get_dir)(void); -+extern int (*sym_crypt_get_verity_info)(struct crypt_device *cd, struct crypt_params_verity *vp); -+extern int (*sym_crypt_init)(struct crypt_device **cd, const char *device); -+extern int (*sym_crypt_init_by_name)(struct crypt_device **cd, const char *name); -+extern int (*sym_crypt_keyslot_add_by_volume_key)(struct crypt_device *cd, int keyslot, const char *volume_key, size_t volume_key_size, const char *passphrase, size_t passphrase_size); -+extern int (*sym_crypt_load)(struct crypt_device *cd, const char *requested_type, void *params); -+extern int (*sym_crypt_resize)(struct crypt_device *cd, const char *name, uint64_t new_size); -+extern int (*sym_crypt_set_data_device)(struct crypt_device *cd, const char *device); -+extern void (*sym_crypt_set_debug_level)(int level); -+extern void (*sym_crypt_set_log_callback)(struct crypt_device *cd, void (*log)(int level, const char *msg, void *usrptr), void *usrptr); -+extern int (*sym_crypt_volume_key_get)(struct crypt_device *cd, int keyslot, char *volume_key, size_t *volume_key_size, const char *passphrase, size_t passphrase_size); -+ -+int dlopen_cryptsetup(void); -+ -+DEFINE_TRIVIAL_CLEANUP_FUNC(struct crypt_device *, crypt_free); -+DEFINE_TRIVIAL_CLEANUP_FUNC(struct crypt_device *, sym_crypt_free); -+ -+void cryptsetup_enable_logging(struct crypt_device *cd); -+ -+#endif -diff --git a/src/shared/dev-setup.c b/src/shared/dev-setup.c -index 6e57e2a..d970640 100644 ---- a/src/shared/dev-setup.c -+++ b/src/shared/dev-setup.c -@@ -57,7 +57,7 @@ int dev_setup(const char *prefix, uid_t uid, gid_t gid) { - } - - int make_inaccessible_nodes( -- const char *runtime_dir, -+ const char *parent_dir, - uid_t uid, - gid_t gid) { - -@@ -65,28 +65,27 @@ int make_inaccessible_nodes( - const char *name; - mode_t mode; - } table[] = { -- { "/systemd", S_IFDIR | 0755 }, -- { "/systemd/inaccessible", S_IFDIR | 0000 }, -- { "/systemd/inaccessible/reg", S_IFREG | 0000 }, -- { "/systemd/inaccessible/dir", S_IFDIR | 0000 }, -- { "/systemd/inaccessible/fifo", S_IFIFO | 0000 }, -- { "/systemd/inaccessible/sock", S_IFSOCK | 0000 }, -+ { "inaccessible", S_IFDIR | 0755 }, -+ { "inaccessible/reg", S_IFREG | 0000 }, -+ { "inaccessible/dir", S_IFDIR | 0000 }, -+ { "inaccessible/fifo", S_IFIFO | 0000 }, -+ { "inaccessible/sock", S_IFSOCK | 0000 }, - - /* The following two are likely to fail if we lack the privs for it (for example in an userns -- * environment, if CAP_SYS_MKNOD is missing, or if a device node policy prohibit major/minor of 0 -- * device nodes to be created). But that's entirely fine. Consumers of these files should carry -- * fallback to use a different node then, for example /inaccessible/sock, which is close -- * enough in behaviour and semantics for most uses. */ -- { "/systemd/inaccessible/chr", S_IFCHR | 0000 }, -- { "/systemd/inaccessible/blk", S_IFBLK | 0000 }, -+ * environment, if CAP_SYS_MKNOD is missing, or if a device node policy prohibits creation of -+ * device nodes with a major/minor of 0). But that's entirely fine. Consumers of these files -+ * should implement falling back to use a different node then, for example -+ * /inaccessible/sock, which is close enough in behaviour and semantics for most uses. -+ */ -+ { "inaccessible/chr", S_IFCHR | 0000 }, -+ { "inaccessible/blk", S_IFBLK | 0000 }, - }; - - _cleanup_umask_ mode_t u; -- size_t i; - int r; - -- if (!runtime_dir) -- runtime_dir = "/run"; -+ if (!parent_dir) -+ parent_dir = "/run/systemd"; - - u = umask(0000); - -@@ -95,10 +94,10 @@ int make_inaccessible_nodes( - * to lock down these nodes as much as we can, but otherwise try to match them as closely as possible with the - * underlying file, i.e. in the best case we offer the same node type as the underlying node. */ - -- for (i = 0; i < ELEMENTSOF(table); i++) { -+ for (size_t i = 0; i < ELEMENTSOF(table); i++) { - _cleanup_free_ char *path = NULL; - -- path = path_join(runtime_dir, table[i].name); -+ path = path_join(parent_dir, table[i].name); - if (!path) - return log_oom(); - -@@ -107,8 +106,7 @@ int make_inaccessible_nodes( - else - r = mknod_label(path, table[i].mode, makedev(0, 0)); - if (r < 0) { -- if (r != -EEXIST) -- log_debug_errno(r, "Failed to create '%s', ignoring: %m", path); -+ log_debug_errno(r, "Failed to create '%s', ignoring: %m", path); - continue; - } - -diff --git a/src/shared/dev-setup.h b/src/shared/dev-setup.h -index 72b90ec..437c0e9 100644 ---- a/src/shared/dev-setup.h -+++ b/src/shared/dev-setup.h -@@ -5,4 +5,4 @@ - - int dev_setup(const char *prefix, uid_t uid, gid_t gid); - --int make_inaccessible_nodes(const char *root, uid_t uid, gid_t gid); -+int make_inaccessible_nodes(const char *parent_dir, uid_t uid, gid_t gid); -diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c -index 24be6de..2805313 100644 ---- a/src/shared/dissect-image.c -+++ b/src/shared/dissect-image.c -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - - #include "sd-device.h" - #include "sd-id128.h" -@@ -18,7 +19,7 @@ - #include "blkid-util.h" - #include "blockdev-util.h" - #include "copy.h" --#include "crypt-util.h" -+#include "cryptsetup-util.h" - #include "def.h" - #include "device-nodes.h" - #include "device-util.h" -@@ -33,8 +34,10 @@ - #include "hexdecoct.h" - #include "hostname-util.h" - #include "id128-util.h" -+#include "mkdir.h" - #include "mount-util.h" - #include "mountpoint-util.h" -+#include "namespace-util.h" - #include "nulstr-util.h" - #include "os-util.h" - #include "path-util.h" -@@ -51,6 +54,9 @@ - #include "user-util.h" - #include "xattr-util.h" - -+/* how many times to wait for the device nodes to appear */ -+#define N_DEVICE_NODE_LIST_ATTEMPTS 10 -+ - int probe_filesystem(const char *node, char **ret_fstype) { - /* Try to find device content type and return it in *ret_fstype. If nothing is found, - * 0/NULL will be returned. -EUCLEAN will be returned for ambiguous results, and an -@@ -151,9 +157,6 @@ static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) { - return 0; - } - --/* how many times to wait for the device nodes to appear */ --#define N_DEVICE_NODE_LIST_ATTEMPTS 10 -- - static int wait_for_partitions_to_appear( - int fd, - sd_device *d, -@@ -213,22 +216,18 @@ static int wait_for_partitions_to_appear( - break; - r = -errno; - if (r == -EINVAL) { -- struct loop_info64 info; -- -- /* If we are running on a loop device that has partition scanning off, return -- * an explicit recognizable error about this, so that callers can generate a -- * proper message explaining the situation. */ -+ /* If we are running on a block device that has partition scanning off, return an -+ * explicit recognizable error about this, so that callers can generate a proper -+ * message explaining the situation. */ - -- if (ioctl(fd, LOOP_GET_STATUS64, &info) >= 0) { --#if HAVE_VALGRIND_MEMCHECK_H -- /* Valgrind currently doesn't know LOOP_GET_STATUS64. Remove this once it does */ -- VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info)); --#endif -+ r = blockdev_partscan_enabled(fd); -+ if (r < 0) -+ return r; -+ if (r == 0) -+ return log_debug_errno(EPROTONOSUPPORT, -+ "Device is a loop device and partition scanning is off!"); - -- if ((info.lo_flags & LO_FLAGS_PARTSCAN) == 0) -- return log_debug_errno(EPROTONOSUPPORT, -- "Device is a loop device and partition scanning is off!"); -- } -+ return -EINVAL; /* original error */ - } - if (r != -EBUSY) - return r; -@@ -308,6 +307,7 @@ int dissect_image( - const void *root_hash, - size_t root_hash_size, - const char *verity_data, -+ const MountOptions *mount_options, - DissectImageFlags flags, - DissectedImage **ret) { - -@@ -325,7 +325,6 @@ int dissect_image( - int r, generic_nr; - struct stat st; - sd_device *q; -- unsigned i; - - assert(fd >= 0); - assert(ret); -@@ -400,8 +399,8 @@ int dissect_image( - - (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL); - if (STRPTR_IN_SET(usage, "filesystem", "crypto")) { -- _cleanup_free_ char *t = NULL, *n = NULL; -- const char *fstype = NULL; -+ _cleanup_free_ char *t = NULL, *n = NULL, *o = NULL; -+ const char *fstype = NULL, *options = NULL; - - /* OK, we have found a file system, that's our root partition then. */ - (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); -@@ -420,6 +419,13 @@ int dissect_image( - m->verity = root_hash && verity_data; - m->can_verity = !!verity_data; - -+ options = mount_options_from_designator(mount_options, PARTITION_ROOT); -+ if (options) { -+ o = strdup(options); -+ if (!o) -+ return -ENOMEM; -+ } -+ - m->partitions[PARTITION_ROOT] = (DissectedPartition) { - .found = true, - .rw = !m->verity, -@@ -427,6 +433,7 @@ int dissect_image( - .architecture = _ARCHITECTURE_INVALID, - .fstype = TAKE_PTR(t), - .node = TAKE_PTR(n), -+ .mount_options = TAKE_PTR(o), - }; - - m->encrypted = streq_ptr(fstype, "crypto_LUKS"); -@@ -496,7 +503,8 @@ int dissect_image( - continue; - - if (is_gpt) { -- int designator = _PARTITION_DESIGNATOR_INVALID, architecture = _ARCHITECTURE_INVALID; -+ PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID; -+ int architecture = _ARCHITECTURE_INVALID; - const char *stype, *sid, *fstype = NULL; - sd_id128_t type_id, id; - bool rw = true; -@@ -691,7 +699,8 @@ int dissect_image( - } - - if (designator != _PARTITION_DESIGNATOR_INVALID) { -- _cleanup_free_ char *t = NULL, *n = NULL; -+ _cleanup_free_ char *t = NULL, *n = NULL, *o = NULL; -+ const char *options = NULL; - - /* First one wins */ - if (m->partitions[designator].found) -@@ -707,6 +716,13 @@ int dissect_image( - if (!n) - return -ENOMEM; - -+ options = mount_options_from_designator(mount_options, designator); -+ if (options) { -+ o = strdup(options); -+ if (!o) -+ return -ENOMEM; -+ } -+ - m->partitions[designator] = (DissectedPartition) { - .found = true, - .partno = nr, -@@ -715,6 +731,7 @@ int dissect_image( - .node = TAKE_PTR(n), - .fstype = TAKE_PTR(t), - .uuid = id, -+ .mount_options = TAKE_PTR(o), - }; - } - -@@ -740,9 +757,9 @@ int dissect_image( - break; - - case 0xEA: { /* Boot Loader Spec extended $BOOT partition */ -- _cleanup_free_ char *n = NULL; -+ _cleanup_free_ char *n = NULL, *o = NULL; - sd_id128_t id = SD_ID128_NULL; -- const char *sid; -+ const char *sid, *options = NULL; - - /* First one wins */ - if (m->partitions[PARTITION_XBOOTLDR].found) -@@ -756,6 +773,13 @@ int dissect_image( - if (!n) - return -ENOMEM; - -+ options = mount_options_from_designator(mount_options, PARTITION_XBOOTLDR); -+ if (options) { -+ o = strdup(options); -+ if (!o) -+ return -ENOMEM; -+ } -+ - m->partitions[PARTITION_XBOOTLDR] = (DissectedPartition) { - .found = true, - .partno = nr, -@@ -763,6 +787,7 @@ int dissect_image( - .architecture = _ARCHITECTURE_INVALID, - .node = TAKE_PTR(n), - .uuid = id, -+ .mount_options = TAKE_PTR(o), - }; - - break; -@@ -785,9 +810,11 @@ int dissect_image( - zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]); - - } else if (flags & DISSECT_IMAGE_REQUIRE_ROOT) { -+ _cleanup_free_ char *o = NULL; -+ const char *options = NULL; - -- /* If the root has was set, then we won't fallback to a generic node, because the root hash -- * decides */ -+ /* If the root hash was set, then we won't fall back to a generic node, because the -+ * root hash decides. */ - if (root_hash) - return -EADDRNOTAVAIL; - -@@ -800,6 +827,13 @@ int dissect_image( - if (multiple_generic) - return -ENOTUNIQ; - -+ options = mount_options_from_designator(mount_options, PARTITION_ROOT); -+ if (options) { -+ o = strdup(options); -+ if (!o) -+ return -ENOMEM; -+ } -+ - m->partitions[PARTITION_ROOT] = (DissectedPartition) { - .found = true, - .rw = generic_rw, -@@ -807,6 +841,7 @@ int dissect_image( - .architecture = _ARCHITECTURE_INVALID, - .node = TAKE_PTR(generic_node), - .uuid = generic_uuid, -+ .mount_options = TAKE_PTR(o), - }; - } - } -@@ -831,7 +866,7 @@ int dissect_image( - b = NULL; - - /* Fill in file system types if we don't know them yet. */ -- for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { -+ for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { - DissectedPartition *p = m->partitions + i; - - if (!p->found) -@@ -859,16 +894,15 @@ int dissect_image( - } - - DissectedImage* dissected_image_unref(DissectedImage *m) { -- unsigned i; -- - if (!m) - return NULL; - -- for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { -+ for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { - free(m->partitions[i].fstype); - free(m->partitions[i].node); - free(m->partitions[i].decrypted_fstype); - free(m->partitions[i].decrypted_node); -+ free(m->partitions[i].mount_options); - } - - free(m->hostname); -@@ -962,15 +996,18 @@ static int mount_partition( - assert(m); - assert(where); - -+ /* Use decrypted node and matching fstype if available, otherwise use the original device */ - node = m->decrypted_node ?: m->node; -- fstype = m->decrypted_fstype ?: m->fstype; -+ fstype = m->decrypted_node ? m->decrypted_fstype: m->fstype; - -- if (!m->found || !node || !fstype) -+ if (!m->found || !node) - return 0; -+ if (!fstype) -+ return -EAFNOSUPPORT; - -- /* Stacked encryption? Yuck */ -- if (streq_ptr(fstype, "crypto_LUKS")) -- return -ELOOP; -+ /* We are looking at an encrypted partition? This either means stacked encryption, or the caller didn't call dissected_image_decrypt() beforehand. Let's return a recognizable error for this case. */ -+ if (streq(fstype, "crypto_LUKS")) -+ return -EUNATCH; - - rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY); - -@@ -981,6 +1018,13 @@ static int mount_partition( - } - - if (directory) { -+ if (!FLAGS_SET(flags, DISSECT_IMAGE_READ_ONLY)) { -+ /* Automatically create missing mount points, if necessary. */ -+ r = mkdir_p_root(where, directory, uid_shift, (gid_t) uid_shift, 0755); -+ if (r < 0) -+ return r; -+ } -+ - r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased, NULL); - if (r < 0) - return r; -@@ -1008,6 +1052,16 @@ static int mount_partition( - return -ENOMEM; - } - -+ if (!isempty(m->mount_options)) -+ if (!strextend_with_separator(&options, ",", m->mount_options, NULL)) -+ return -ENOMEM; -+ -+ if (FLAGS_SET(flags, DISSECT_IMAGE_MKDIR)) { -+ r = mkdir_p(p, 0755); -+ if (r < 0) -+ return r; -+ } -+ - r = mount_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options); - if (r < 0) - return r; -@@ -1016,11 +1070,21 @@ static int mount_partition( - } - - int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags) { -- int r, boot_mounted; -+ int r, xbootldr_mounted; - - assert(m); - assert(where); - -+ /* Returns: -+ * -+ * -ENXIO → No root partition found -+ * -EMEDIUMTYPE → DISSECT_IMAGE_VALIDATE_OS set but no os-release file found -+ * -EUNATCH → Encrypted partition found for which no dm-crypt was set up yet -+ * -EUCLEAN → fsck for file system failed -+ * -EBUSY → File system already mounted/used elsewhere (kernel) -+ * -EAFNOSUPPORT → File system type not supported or not known -+ */ -+ - if (!m->partitions[PARTITION_ROOT].found) - return -ENXIO; - -@@ -1041,6 +1105,10 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, - if (flags & DISSECT_IMAGE_MOUNT_ROOT_ONLY) - return 0; - -+ /* Mask DISSECT_IMAGE_MKDIR for all subdirs: the idea is that only the top-level mount point is -+ * created if needed, but the image itself not modified. */ -+ flags &= ~DISSECT_IMAGE_MKDIR; -+ - r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", uid_shift, flags); - if (r < 0) - return r; -@@ -1057,35 +1125,78 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, - if (r < 0) - return r; - -- boot_mounted = mount_partition(m->partitions + PARTITION_XBOOTLDR, where, "/boot", uid_shift, flags); -- if (boot_mounted < 0) -- return boot_mounted; -+ xbootldr_mounted = mount_partition(m->partitions + PARTITION_XBOOTLDR, where, "/boot", uid_shift, flags); -+ if (xbootldr_mounted < 0) -+ return xbootldr_mounted; - - if (m->partitions[PARTITION_ESP].found) { -+ int esp_done = false; -+ - /* Mount the ESP to /efi if it exists. If it doesn't exist, use /boot instead, but only if it - * exists and is empty, and we didn't already mount the XBOOTLDR partition into it. */ - - r = chase_symlinks("/efi", where, CHASE_PREFIX_ROOT, NULL, NULL); -- if (r >= 0) { -- r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, flags); -- if (r < 0) -+ if (r < 0) { -+ if (r != -ENOENT) - return r; - -- } else if (boot_mounted <= 0) { -- _cleanup_free_ char *p = NULL; -+ /* /efi doesn't exist. Let's see if /boot is suitable then */ - -- r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p, NULL); -- if (r >= 0 && dir_is_empty(p) > 0) { -- r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, flags); -- if (r < 0) -- return r; -+ if (!xbootldr_mounted) { -+ _cleanup_free_ char *p = NULL; -+ -+ r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p, NULL); -+ if (r < 0) { -+ if (r != -ENOENT) -+ return r; -+ } else if (dir_is_empty(p) > 0) { -+ /* It exists and is an empty directory. Let's mount the ESP there. */ -+ r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, flags); -+ if (r < 0) -+ return r; -+ -+ esp_done = true; -+ } - } - } -+ -+ if (!esp_done) { -+ /* OK, let's mount the ESP now to /efi (possibly creating the dir if missing) */ -+ -+ r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, flags); -+ if (r < 0) -+ return r; -+ } - } - - return 0; - } - -+int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags) { -+ int r; -+ -+ assert(m); -+ assert(where); -+ -+ r = dissected_image_mount(m, where, uid_shift, flags); -+ if (r == -ENXIO) -+ return log_error_errno(r, "Not root file system found in image."); -+ if (r == -EMEDIUMTYPE) -+ return log_error_errno(r, "No suitable os-release file in image found."); -+ if (r == -EUNATCH) -+ return log_error_errno(r, "Encrypted file system discovered, but decryption not requested."); -+ if (r == -EUCLEAN) -+ return log_error_errno(r, "File system check on image failed."); -+ if (r == -EBUSY) -+ return log_error_errno(r, "File system already mounted elsewhere."); -+ if (r == -EAFNOSUPPORT) -+ return log_error_errno(r, "File system type not supported or not known."); -+ if (r < 0) -+ return log_error_errno(r, "Failed to mount image: %m"); -+ -+ return r; -+} -+ - #if HAVE_LIBCRYPTSETUP - typedef struct DecryptedPartition { - struct crypt_device *device; -@@ -1112,13 +1223,13 @@ DecryptedImage* decrypted_image_unref(DecryptedImage* d) { - DecryptedPartition *p = d->decrypted + i; - - if (p->device && p->name && !p->relinquished) { -- r = crypt_deactivate(p->device, p->name); -+ r = sym_crypt_deactivate_by_name(p->device, p->name, 0); - if (r < 0) - log_debug_errno(r, "Failed to deactivate encrypted partition %s", p->name); - } - - if (p->device) -- crypt_free(p->device); -+ sym_crypt_free(p->device); - free(p->name); - } - -@@ -1152,7 +1263,7 @@ static int make_dm_name_and_node(const void *original_node, const char *suffix, - if (!filename_is_valid(name)) - return -EINVAL; - -- node = path_join(crypt_get_dir(), name); -+ node = path_join(sym_crypt_get_dir(), name); - if (!node) - return -ENOMEM; - -@@ -1169,7 +1280,7 @@ static int decrypt_partition( - DecryptedImage *d) { - - _cleanup_free_ char *node = NULL, *name = NULL; -- _cleanup_(crypt_freep) struct crypt_device *cd = NULL; -+ _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; - int r; - - assert(m); -@@ -1184,6 +1295,10 @@ static int decrypt_partition( - if (!passphrase) - return -ENOKEY; - -+ r = dlopen_cryptsetup(); -+ if (r < 0) -+ return r; -+ - r = make_dm_name_and_node(m->node, "-decrypted", &name, &node); - if (r < 0) - return r; -@@ -1191,19 +1306,19 @@ static int decrypt_partition( - if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1)) - return -ENOMEM; - -- r = crypt_init(&cd, m->node); -+ r = sym_crypt_init(&cd, m->node); - if (r < 0) - return log_debug_errno(r, "Failed to initialize dm-crypt: %m"); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - -- r = crypt_load(cd, CRYPT_LUKS, NULL); -+ r = sym_crypt_load(cd, CRYPT_LUKS, NULL); - if (r < 0) - return log_debug_errno(r, "Failed to load LUKS metadata: %m"); - -- r = crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), -- ((flags & DISSECT_IMAGE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) | -- ((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0)); -+ r = sym_crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), -+ ((flags & DISSECT_IMAGE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) | -+ ((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0)); - if (r < 0) { - log_debug_errno(r, "Failed to activate LUKS device: %m"); - return r == -EPERM ? -EKEYREJECTED : r; -@@ -1221,23 +1336,26 @@ static int decrypt_partition( - static int verity_can_reuse(const void *root_hash, size_t root_hash_size, bool has_sig, const char *name, struct crypt_device **ret_cd) { - /* If the same volume was already open, check that the root hashes match, and reuse it if they do */ - _cleanup_free_ char *root_hash_existing = NULL; -- _cleanup_(crypt_freep) struct crypt_device *cd = NULL; -+ _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; - struct crypt_params_verity crypt_params = {}; - size_t root_hash_existing_size = root_hash_size; - int r; - - assert(ret_cd); - -- r = crypt_init_by_name(&cd, name); -+ r = sym_crypt_init_by_name(&cd, name); - if (r < 0) - return log_debug_errno(r, "Error opening verity device, crypt_init_by_name failed: %m"); -- r = crypt_get_verity_info(cd, &crypt_params); -+ -+ r = sym_crypt_get_verity_info(cd, &crypt_params); - if (r < 0) - return log_debug_errno(r, "Error opening verity device, crypt_get_verity_info failed: %m"); -+ - root_hash_existing = malloc0(root_hash_size); - if (!root_hash_existing) - return -ENOMEM; -- r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_existing, &root_hash_existing_size, NULL, 0); -+ -+ r = sym_crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_existing, &root_hash_existing_size, NULL, 0); - if (r < 0) - return log_debug_errno(r, "Error opening verity device, crypt_volume_key_get failed: %m"); - if (root_hash_size != root_hash_existing_size || memcmp(root_hash_existing, root_hash, root_hash_size) != 0) -@@ -1257,7 +1375,8 @@ static int verity_can_reuse(const void *root_hash, size_t root_hash_size, bool h - static inline void dm_deferred_remove_clean(char *name) { - if (!name) - return; -- (void) crypt_deactivate_by_name(NULL, name, CRYPT_DEACTIVATE_DEFERRED); -+ -+ (void) sym_crypt_deactivate_by_name(NULL, name, CRYPT_DEACTIVATE_DEFERRED); - free(name); - } - DEFINE_TRIVIAL_CLEANUP_FUNC(char *, dm_deferred_remove_clean); -@@ -1275,7 +1394,7 @@ static int verity_partition( - DecryptedImage *d) { - - _cleanup_free_ char *node = NULL, *name = NULL, *hash_sig_from_file = NULL; -- _cleanup_(crypt_freep) struct crypt_device *cd = NULL; -+ _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL; - _cleanup_(dm_deferred_remove_cleanp) char *restore_deferred_remove = NULL; - int r; - -@@ -1295,11 +1414,17 @@ static int verity_partition( - return 0; - } - -+ r = dlopen_cryptsetup(); -+ if (r < 0) -+ return r; -+ - if (FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) { - /* Use the roothash, which is unique per volume, as the device node name, so that it can be reused */ - _cleanup_free_ char *root_hash_encoded = NULL; -+ - root_hash_encoded = hexmem(root_hash, root_hash_size); - if (!root_hash_encoded) -+ - return -ENOMEM; - r = make_dm_name_and_node(root_hash_encoded, "-verity", &name, &node); - } else -@@ -1313,17 +1438,17 @@ static int verity_partition( - return r; - } - -- r = crypt_init(&cd, verity_data ?: v->node); -+ r = sym_crypt_init(&cd, verity_data ?: v->node); - if (r < 0) - return r; - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - -- r = crypt_load(cd, CRYPT_VERITY, NULL); -+ r = sym_crypt_load(cd, CRYPT_VERITY, NULL); - if (r < 0) - return r; - -- r = crypt_set_data_device(cd, m->node); -+ r = sym_crypt_set_data_device(cd, m->node); - if (r < 0) - return r; - -@@ -1336,53 +1461,68 @@ static int verity_partition( - for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) { - if (root_hash_sig || hash_sig_from_file) { - #if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY -- r = crypt_activate_by_signed_key(cd, name, root_hash, root_hash_size, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, CRYPT_ACTIVATE_READONLY); -+ r = sym_crypt_activate_by_signed_key(cd, name, root_hash, root_hash_size, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, CRYPT_ACTIVATE_READONLY); - #else - r = log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "activation of verity device with signature requested, but not supported by cryptsetup due to missing crypt_activate_by_signed_key()"); - #endif - } else -- r = crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY); -+ r = sym_crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY); - /* libdevmapper can return EINVAL when the device is already in the activation stage. - * There's no way to distinguish this situation from a genuine error due to invalid -- * parameters, so immediately fallback to activating the device with a unique name. -+ * parameters, so immediately fall back to activating the device with a unique name. - * Improvements in libcrypsetup can ensure this never happens: https://gitlab.com/cryptsetup/cryptsetup/-/merge_requests/96 */ - if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) - return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d); -- if (!IN_SET(r, 0, -EEXIST, -ENODEV)) -+ if (!IN_SET(r, -+ 0, /* Success */ -+ -EEXIST, /* Volume is already open and ready to be used */ -+ -EBUSY, /* Volume is being opened but not ready, crypt_init_by_name can fetch details */ -+ -ENODEV /* Volume is being opened but not ready, crypt_init_by_name would fail, try to open again */)) - return r; -- if (r == -EEXIST) { -+ if (IN_SET(r, -EEXIST, -EBUSY)) { - struct crypt_device *existing_cd = NULL; - - if (!restore_deferred_remove){ - /* To avoid races, disable automatic removal on umount while setting up the new device. Restore it on failure. */ - r = dm_deferred_remove_cancel(name); -- if (r < 0) -+ /* If activation returns EBUSY there might be no deferred removal to cancel, that's fine */ -+ if (r < 0 && r != -ENXIO) - return log_debug_errno(r, "Disabling automated deferred removal for verity device %s failed: %m", node); -- restore_deferred_remove = strdup(name); -- if (!restore_deferred_remove) -- return -ENOMEM; -+ if (r == 0) { -+ restore_deferred_remove = strdup(name); -+ if (!restore_deferred_remove) -+ return -ENOMEM; -+ } - } - - r = verity_can_reuse(root_hash, root_hash_size, !!root_hash_sig || !!hash_sig_from_file, name, &existing_cd); - /* Same as above, -EINVAL can randomly happen when it actually means -EEXIST */ - if (r == -EINVAL && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) - return verity_partition(m, v, root_hash, root_hash_size, verity_data, NULL, root_hash_sig ?: hash_sig_from_file, root_hash_sig_size, flags & ~DISSECT_IMAGE_VERITY_SHARE, d); -- if (!IN_SET(r, 0, -ENODEV, -ENOENT)) -+ if (!IN_SET(r, 0, -ENODEV, -ENOENT, -EBUSY)) - return log_debug_errno(r, "Checking whether existing verity device %s can be reused failed: %m", node); - if (r == 0) { -+ /* devmapper might say that the device exists, but the devlink might not yet have been -+ * created. Check and wait for the udev event in that case. */ -+ r = device_wait_for_devlink(node, "block", 100 * USEC_PER_MSEC, NULL); -+ /* Fallback to activation with a unique device if it's taking too long */ -+ if (r == -ETIMEDOUT) -+ break; -+ if (r < 0) -+ return r; -+ - if (cd) -- crypt_free(cd); -+ sym_crypt_free(cd); - cd = existing_cd; - } - } - if (r == 0) - break; -+ -+ /* Device is being opened by another process, but it has not finished yet, yield for 2ms */ -+ (void) usleep(2 * USEC_PER_MSEC); - } - -- /* Sanity check: libdevmapper is known to report that the device already exists and is active, -- * but it's actually not there, so the later filesystem probe or mount would fail. */ -- if (r == 0) -- r = access(node, F_OK); - /* An existing verity device was reported by libcryptsetup/libdevmapper, but we can't use it at this time. - * Fall back to activating it with a unique device name. */ - if (r != 0 && FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE)) -@@ -1415,7 +1555,6 @@ int dissected_image_decrypt( - - #if HAVE_LIBCRYPTSETUP - _cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL; -- unsigned i; - int r; - #endif - -@@ -1443,7 +1582,7 @@ int dissected_image_decrypt( - if (!d) - return -ENOMEM; - -- for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { -+ for (PartitionDesignator i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { - DissectedPartition *p = m->partitions + i; - int k; - -@@ -1536,7 +1675,7 @@ int decrypted_image_relinquish(DecryptedImage *d) { - if (p->relinquished) - continue; - -- r = crypt_deactivate_by_name(NULL, p->name, CRYPT_DEACTIVATE_DEFERRED); -+ r = sym_crypt_deactivate_by_name(NULL, p->name, CRYPT_DEACTIVATE_DEFERRED); - if (r < 0) - return log_debug_errno(r, "Failed to mark %s for auto-removal: %m", p->name); - -@@ -1547,7 +1686,14 @@ int decrypted_image_relinquish(DecryptedImage *d) { - return 0; - } - --int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data, char **ret_roothashsig) { -+int verity_metadata_load( -+ const char *image, -+ const char *root_hash_path, -+ void **ret_roothash, -+ size_t *ret_roothash_size, -+ char **ret_verity_data, -+ char **ret_roothashsig) { -+ - _cleanup_free_ char *verity_filename = NULL, *roothashsig_filename = NULL; - _cleanup_free_ void *roothash_decoded = NULL; - size_t roothash_decoded_size = 0; -@@ -1683,12 +1829,14 @@ int dissected_image_acquire_metadata(DissectedImage *m) { - }; - - _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL; -+ _cleanup_close_pair_ int error_pipe[2] = { -1, -1 }; - _cleanup_(rmdir_and_freep) char *t = NULL; - _cleanup_(sigkill_waitp) pid_t child = 0; - sd_id128_t machine_id = SD_ID128_NULL; - _cleanup_free_ char *hostname = NULL; - unsigned n_meta_initialized = 0, k; -- int fds[2 * _META_MAX], r; -+ int fds[2 * _META_MAX], r, v; -+ ssize_t n; - - BLOCK_SIGNALS(SIGCHLD); - -@@ -1704,18 +1852,28 @@ int dissected_image_acquire_metadata(DissectedImage *m) { - if (r < 0) - goto finish; - -+ if (pipe2(error_pipe, O_CLOEXEC) < 0) { -+ r = -errno; -+ goto finish; -+ } -+ - r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child); - if (r < 0) - goto finish; - if (r == 0) { -+ error_pipe[0] = safe_close(error_pipe[0]); -+ - r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_VALIDATE_OS); - if (r < 0) { -+ /* Let parent know the error */ -+ (void) write(error_pipe[1], &r, sizeof(r)); -+ - log_debug_errno(r, "Failed to mount dissected image: %m"); - _exit(EXIT_FAILURE); - } - - for (k = 0; k < _META_MAX; k++) { -- _cleanup_close_ int fd = -1; -+ _cleanup_close_ int fd = -ENOENT; - const char *p; - - fds[2*k] = safe_close(fds[2*k]); -@@ -1727,12 +1885,15 @@ int dissected_image_acquire_metadata(DissectedImage *m) { - } - if (fd < 0) { - log_debug_errno(fd, "Failed to read %s file of image, ignoring: %m", paths[k]); -+ fds[2*k+1] = safe_close(fds[2*k+1]); - continue; - } - - r = copy_bytes(fd, fds[2*k+1], (uint64_t) -1, 0); -- if (r < 0) -+ if (r < 0) { -+ (void) write(error_pipe[1], &r, sizeof(r)); - _exit(EXIT_FAILURE); -+ } - - fds[2*k+1] = safe_close(fds[2*k+1]); - } -@@ -1740,6 +1901,8 @@ int dissected_image_acquire_metadata(DissectedImage *m) { - _exit(EXIT_SUCCESS); - } - -+ error_pipe[1] = safe_close(error_pipe[1]); -+ - for (k = 0; k < _META_MAX; k++) { - _cleanup_fclose_ FILE *f = NULL; - -@@ -1797,7 +1960,16 @@ int dissected_image_acquire_metadata(DissectedImage *m) { - r = wait_for_terminate_and_check("(sd-dissect)", child, 0); - child = 0; - if (r < 0) -- goto finish; -+ return r; -+ -+ n = read(error_pipe[0], &v, sizeof(v)); -+ if (n < 0) -+ return -errno; -+ if (n == sizeof(v)) -+ return v; /* propagate error sent to us from child */ -+ if (n != 0) -+ return -EIO; -+ - if (r != EXIT_SUCCESS) - return -EPROTO; - -@@ -1819,6 +1991,7 @@ int dissect_image_and_warn( - const void *root_hash, - size_t root_hash_size, - const char *verity_data, -+ const MountOptions *mount_options, - DissectImageFlags flags, - DissectedImage **ret) { - -@@ -1833,7 +2006,7 @@ int dissect_image_and_warn( - name = buffer; - } - -- r = dissect_image(fd, root_hash, root_hash_size, verity_data, flags, ret); -+ r = dissect_image(fd, root_hash, root_hash_size, verity_data, mount_options, flags, ret); - - switch (r) { - -@@ -1863,14 +2036,14 @@ int dissect_image_and_warn( - } - } - --bool dissected_image_can_do_verity(const DissectedImage *image, unsigned partition_designator) { -+bool dissected_image_can_do_verity(const DissectedImage *image, PartitionDesignator partition_designator) { - if (image->single_file_system) - return partition_designator == PARTITION_ROOT && image->can_verity; - - return PARTITION_VERITY_OF(partition_designator) >= 0; - } - --bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_designator) { -+bool dissected_image_has_verity(const DissectedImage *image, PartitionDesignator partition_designator) { - int k; - - if (image->single_file_system) -@@ -1880,6 +2053,100 @@ bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_ - return k >= 0 && image->partitions[k].found; - } - -+MountOptions* mount_options_free_all(MountOptions *options) { -+ MountOptions *m; -+ -+ while ((m = options)) { -+ LIST_REMOVE(mount_options, options, m); -+ free(m->options); -+ free(m); -+ } -+ -+ return NULL; -+} -+ -+const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator) { -+ const MountOptions *m; -+ -+ LIST_FOREACH(mount_options, m, options) -+ if (designator == m->partition_designator && !isempty(m->options)) -+ return m->options; -+ -+ return NULL; -+} -+ -+int mount_image_privately_interactively( -+ const char *image, -+ DissectImageFlags flags, -+ char **ret_directory, -+ LoopDevice **ret_loop_device, -+ DecryptedImage **ret_decrypted_image) { -+ -+ _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; -+ _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL; -+ _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL; -+ _cleanup_(rmdir_and_freep) char *created_dir = NULL; -+ _cleanup_free_ char *temp = NULL; -+ int r; -+ -+ /* Mounts an OS image at a temporary place, inside a newly created mount namespace of our own. This -+ * is used by tools such as systemd-tmpfiles or systemd-firstboot to operate on some disk image -+ * easily. */ -+ -+ assert(image); -+ assert(ret_directory); -+ assert(ret_loop_device); -+ assert(ret_decrypted_image); -+ -+ r = tempfn_random_child(NULL, program_invocation_short_name, &temp); -+ if (r < 0) -+ return log_error_errno(r, "Failed to generate temporary mount directory: %m"); -+ -+ r = loop_device_make_by_path( -+ image, -+ FLAGS_SET(flags, DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR, -+ FLAGS_SET(flags, DISSECT_IMAGE_NO_PARTITION_TABLE) ? 0 : LO_FLAGS_PARTSCAN, -+ &d); -+ if (r < 0) -+ return log_error_errno(r, "Failed to set up loopback device: %m"); -+ -+ r = dissect_image_and_warn(d->fd, image, NULL, 0, NULL, NULL, flags, &dissected_image); -+ if (r < 0) -+ return r; -+ -+ r = dissected_image_decrypt_interactively(dissected_image, NULL, NULL, 0, NULL, NULL, NULL, 0, flags, &decrypted_image); -+ if (r < 0) -+ return r; -+ -+ r = detach_mount_namespace(); -+ if (r < 0) -+ return log_error_errno(r, "Failed to detach mount namespace: %m"); -+ -+ r = mkdir_p(temp, 0700); -+ if (r < 0) -+ return log_error_errno(r, "Failed to create mount point: %m"); -+ -+ created_dir = TAKE_PTR(temp); -+ -+ r = dissected_image_mount_and_warn(dissected_image, created_dir, UID_INVALID, flags); -+ if (r < 0) -+ return r; -+ -+ if (decrypted_image) { -+ r = decrypted_image_relinquish(decrypted_image); -+ if (r < 0) -+ return log_error_errno(r, "Failed to relinquish DM devices: %m"); -+ } -+ -+ loop_device_relinquish(d); -+ -+ *ret_directory = TAKE_PTR(created_dir); -+ *ret_loop_device = TAKE_PTR(d); -+ *ret_decrypted_image = TAKE_PTR(decrypted_image); -+ -+ return 0; -+} -+ - static const char *const partition_designator_table[] = { - [PARTITION_ROOT] = "root", - [PARTITION_ROOT_SECONDARY] = "root-secondary", -@@ -1894,4 +2161,4 @@ static const char *const partition_designator_table[] = { - [PARTITION_VAR] = "var", - }; - --DEFINE_STRING_TABLE_LOOKUP(partition_designator, int); -+DEFINE_STRING_TABLE_LOOKUP(partition_designator, PartitionDesignator); -diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h -index 84ec1ce..520d8ab 100644 ---- a/src/shared/dissect-image.h -+++ b/src/shared/dissect-image.h -@@ -5,11 +5,14 @@ - - #include "sd-id128.h" - -+#include "list.h" -+#include "loop-util.h" - #include "macro.h" - - typedef struct DissectedImage DissectedImage; - typedef struct DissectedPartition DissectedPartition; - typedef struct DecryptedImage DecryptedImage; -+typedef struct MountOptions MountOptions; - - struct DissectedPartition { - bool found:1; -@@ -21,9 +24,10 @@ struct DissectedPartition { - char *node; - char *decrypted_node; - char *decrypted_fstype; -+ char *mount_options; - }; - --enum { -+typedef enum PartitionDesignator { - PARTITION_ROOT, - PARTITION_ROOT_SECONDARY, /* Secondary architecture */ - PARTITION_HOME, -@@ -37,9 +41,9 @@ enum { - PARTITION_VAR, - _PARTITION_DESIGNATOR_MAX, - _PARTITION_DESIGNATOR_INVALID = -1 --}; -+} PartitionDesignator; - --static inline int PARTITION_VERITY_OF(int p) { -+static inline PartitionDesignator PARTITION_VERITY_OF(PartitionDesignator p) { - if (p == PARTITION_ROOT) - return PARTITION_ROOT_VERITY; - if (p == PARTITION_ROOT_SECONDARY) -@@ -65,6 +69,7 @@ typedef enum DissectImageFlags { - DISSECT_IMAGE_FSCK = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */ - DISSECT_IMAGE_NO_PARTITION_TABLE = 1 << 12, /* Only recognize single file system images */ - DISSECT_IMAGE_VERITY_SHARE = 1 << 13, /* When activating a verity device, reuse existing one if already open */ -+ DISSECT_IMAGE_MKDIR = 1 << 14, /* Make directory to mount right before mounting, if missing */ - } DissectImageFlags; - - struct DissectedImage { -@@ -81,9 +86,19 @@ struct DissectedImage { - char **os_release; - }; - -+struct MountOptions { -+ PartitionDesignator partition_designator; -+ char *options; -+ LIST_FIELDS(MountOptions, mount_options); -+}; -+ -+MountOptions* mount_options_free_all(MountOptions *options); -+DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all); -+const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator); -+ - int probe_filesystem(const char *node, char **ret_fstype); --int dissect_image(int fd, const void *root_hash, size_t root_hash_size, const char *verity_data, DissectImageFlags flags, DissectedImage **ret); --int dissect_image_and_warn(int fd, const char *name, const void *root_hash, size_t root_hash_size, const char *verity_data, DissectImageFlags flags, DissectedImage **ret); -+int dissect_image(int fd, const void *root_hash, size_t root_hash_size, const char *verity_data, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); -+int dissect_image_and_warn(int fd, const char *name, const void *root_hash, size_t root_hash_size, const char *verity_data, const MountOptions *mount_options, DissectImageFlags flags, DissectedImage **ret); - - DissectedImage* dissected_image_unref(DissectedImage *m); - DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref); -@@ -91,6 +106,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref); - int dissected_image_decrypt(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, const char *verity_data, const char *root_hash_sig_path, const void *root_hash_sig, size_t root_hash_sig_size, DissectImageFlags flags, DecryptedImage **ret); - int dissected_image_decrypt_interactively(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, const char *verity_data, const char *root_hash_sig_path, const void *root_hash_sig, size_t root_hash_sig_size, DissectImageFlags flags, DecryptedImage **ret); - int dissected_image_mount(DissectedImage *m, const char *dest, uid_t uid_shift, DissectImageFlags flags); -+int dissected_image_mount_and_warn(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags); - - int dissected_image_acquire_metadata(DissectedImage *m); - -@@ -98,9 +114,11 @@ DecryptedImage* decrypted_image_unref(DecryptedImage *p); - DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref); - int decrypted_image_relinquish(DecryptedImage *d); - --const char* partition_designator_to_string(int i) _const_; --int partition_designator_from_string(const char *name) _pure_; -+const char* partition_designator_to_string(PartitionDesignator d) _const_; -+PartitionDesignator partition_designator_from_string(const char *name) _pure_; - - int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data, char **ret_roothashsig); --bool dissected_image_can_do_verity(const DissectedImage *image, unsigned partition_designator); --bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_designator); -+bool dissected_image_can_do_verity(const DissectedImage *image, PartitionDesignator d); -+bool dissected_image_has_verity(const DissectedImage *image, PartitionDesignator d); -+ -+int mount_image_privately_interactively(const char *path, DissectImageFlags flags, char **ret_directory, LoopDevice **ret_loop_device, DecryptedImage **ret_decrypted_image); -diff --git a/src/shared/dropin.c b/src/shared/dropin.c -index 932da0c..6c614b5 100644 ---- a/src/shared/dropin.c -+++ b/src/shared/dropin.c -@@ -233,7 +233,6 @@ int unit_file_find_dropin_paths( - _cleanup_strv_free_ char **dirs = NULL; - const char *n; - char **p; -- Iterator i; - int r; - - assert(ret); -@@ -242,7 +241,7 @@ int unit_file_find_dropin_paths( - STRV_FOREACH(p, lookup_path) - (void) unit_file_find_dirs(original_root, unit_path_cache, *p, name, dir_suffix, &dirs); - -- SET_FOREACH(n, aliases, i) -+ SET_FOREACH(n, aliases) - STRV_FOREACH(p, lookup_path) - (void) unit_file_find_dirs(original_root, unit_path_cache, *p, n, dir_suffix, &dirs); - -diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c -index 3bb12f9..9326d28 100644 ---- a/src/shared/ethtool-util.c -+++ b/src/shared/ethtool-util.c -@@ -938,12 +938,13 @@ int config_parse_channel(const char *unit, - - r = safe_atou32(rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse channel value, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse channel value for %s=, ignoring: %s", lvalue, rvalue); - return 0; - } -- - if (k < 1) { -- log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid %s value, ignoring: %s", lvalue, rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Invalid %s= value, ignoring: %s", lvalue, rvalue); - return 0; - } - -@@ -998,24 +999,24 @@ int config_parse_advertise(const char *unit, - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to split advertise modes '%s', ignoring: %m", rvalue); -- break; -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to split advertise modes '%s', ignoring assignment: %m", rvalue); -+ return 0; - } - if (r == 0) -- break; -+ return 0; - - mode = ethtool_link_mode_bit_from_string(w); - /* We reuse the kernel provided enum which does not contain negative value. So, the cast - * below is mandatory. Otherwise, the check below always passes and access an invalid address. */ - if ((int) mode < 0) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse advertise mode, ignoring: %s", w); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Failed to parse advertise mode, ignoring: %s", w); - continue; - } - - advertise[mode / 32] |= 1UL << (mode % 32); - } -- -- return 0; - } - - int config_parse_nic_buffer_size(const char *unit, -@@ -1040,12 +1041,13 @@ int config_parse_nic_buffer_size(const char *unit, - - r = safe_atou32(rvalue, &k); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse interface buffer value, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse interface buffer value, ignoring: %s", rvalue); - return 0; - } -- - if (k < 1) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid %s value, ignoring: %s", lvalue, rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, -+ "Invalid %s= value, ignoring: %s", lvalue, rvalue); - return 0; - } - -diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c -index 82b1422..e2b6c67 100644 ---- a/src/shared/exit-status.c -+++ b/src/shared/exit-status.c -@@ -70,6 +70,8 @@ const ExitStatusMapping exit_status_mappings[256] = { - [EXIT_LOGS_DIRECTORY] = { "LOGS_DIRECTORY", EXIT_STATUS_SYSTEMD }, - [EXIT_CONFIGURATION_DIRECTORY] = { "CONFIGURATION_DIRECTORY", EXIT_STATUS_SYSTEMD }, - [EXIT_NUMA_POLICY] = { "NUMA_POLICY", EXIT_STATUS_SYSTEMD }, -+ [EXIT_CREDENTIALS] = { "CREDENTIALS", EXIT_STATUS_SYSTEMD }, -+ - [EXIT_EXCEPTION] = { "EXCEPTION", EXIT_STATUS_SYSTEMD }, - - [EXIT_INVALIDARGUMENT] = { "INVALIDARGUMENT", EXIT_STATUS_LSB }, -diff --git a/src/shared/exit-status.h b/src/shared/exit-status.h -index 9ea147c..7ac99a4 100644 ---- a/src/shared/exit-status.h -+++ b/src/shared/exit-status.h -@@ -70,6 +70,7 @@ enum { - EXIT_LOGS_DIRECTORY, /* 240 */ - EXIT_CONFIGURATION_DIRECTORY, - EXIT_NUMA_POLICY, -+ EXIT_CREDENTIALS, - - EXIT_EXCEPTION = 255, /* Whenever we want to propagate an abnormal/signal exit, in line with bash */ - }; -diff --git a/src/shared/fdset.c b/src/shared/fdset.c -index 89d118a..dfe8242 100644 ---- a/src/shared/fdset.c -+++ b/src/shared/fdset.c -@@ -161,13 +161,12 @@ finish: - } - - int fdset_cloexec(FDSet *fds, bool b) { -- Iterator i; - void *p; - int r; - - assert(fds); - -- SET_FOREACH(p, MAKE_SET(fds), i) { -+ SET_FOREACH(p, MAKE_SET(fds)) { - r = fd_cloexec(PTR_TO_FD(p), b); - if (r < 0) - return r; -@@ -209,7 +208,6 @@ fail: - - int fdset_close_others(FDSet *fds) { - void *e; -- Iterator i; - int *a = NULL; - size_t j = 0, m; - -@@ -217,7 +215,7 @@ int fdset_close_others(FDSet *fds) { - - if (m > 0) { - a = newa(int, m); -- SET_FOREACH(e, MAKE_SET(fds), i) -+ SET_FOREACH(e, MAKE_SET(fds)) - a[j++] = PTR_TO_FD(e); - } - -diff --git a/src/shared/fdset.h b/src/shared/fdset.h -index bdf1377..ceabb82 100644 ---- a/src/shared/fdset.h -+++ b/src/shared/fdset.h -@@ -35,8 +35,10 @@ int fdset_steal_first(FDSet *fds); - - void fdset_close(FDSet *fds); - --#define FDSET_FOREACH(fd, fds, i) \ -- for ((i) = ITERATOR_FIRST, (fd) = fdset_iterate((fds), &(i)); (fd) >= 0; (fd) = fdset_iterate((fds), &(i))) -+#define _FDSET_FOREACH(fd, fds, i) \ -+ for (Iterator i = ITERATOR_FIRST; ((fd) = fdset_iterate((fds), &i)) >= 0; ) -+#define FDSET_FOREACH(fd, fds) \ -+ _FDSET_FOREACH(fd, fds, UNIQ_T(i, UNIQ)) - - DEFINE_TRIVIAL_CLEANUP_FUNC(FDSet*, fdset_free); - #define _cleanup_fdset_free_ _cleanup_(fdset_freep) -diff --git a/src/shared/format-table.c b/src/shared/format-table.c -index 87ef5c3..7e87629 100644 ---- a/src/shared/format-table.c -+++ b/src/shared/format-table.c -@@ -1335,7 +1335,7 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas - if (d->type == TABLE_TIMESTAMP) - ret = format_timestamp(p, FORMAT_TIMESTAMP_MAX, d->timestamp); - else if (d->type == TABLE_TIMESTAMP_UTC) -- ret = format_timestamp_utc(p, FORMAT_TIMESTAMP_MAX, d->timestamp); -+ ret = format_timestamp_style(p, FORMAT_TIMESTAMP_MAX, d->timestamp, TIMESTAMP_UTC); - else - ret = format_timestamp_relative(p, FORMAT_TIMESTAMP_MAX, d->timestamp); - if (!ret) -diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c -index 806dda8..d883eca 100644 ---- a/src/shared/fstab-util.c -+++ b/src/shared/fstab-util.c -@@ -81,50 +81,53 @@ int fstab_is_mount_point(const char *mount) { - - int fstab_filter_options(const char *opts, const char *names, - const char **ret_namefound, char **ret_value, char **ret_filtered) { -- const char *name, *n = NULL, *x; -+ const char *name, *namefound = NULL, *x; - _cleanup_strv_free_ char **stor = NULL; - _cleanup_free_ char *v = NULL, **strv = NULL; -+ int r; - - assert(names && *names); - - if (!opts) - goto answer; - -- /* If !value and !filtered, this function is not allowed to fail. */ -+ /* If !ret_value and !ret_filtered, this function is not allowed to fail. */ - - if (!ret_filtered) { -- const char *word, *state; -- size_t l; -+ for (const char *word = opts;;) { -+ const char *end = word + strcspn(word, ","); - -- FOREACH_WORD_SEPARATOR(word, l, opts, ",", state) - NULSTR_FOREACH(name, names) { -- if (l < strlen(name)) -+ if (end < word + strlen(name)) - continue; - if (!strneq(word, name, strlen(name))) - continue; - -- /* we know that the string is NUL -- * terminated, so *x is valid */ -+ /* We know that the string is NUL terminated, so *x is valid */ - x = word + strlen(name); - if (IN_SET(*x, '\0', '=', ',')) { -- n = name; -+ namefound = name; - if (ret_value) { -- free(v); -- if (IN_SET(*x, '\0', ',')) -- v = NULL; -- else { -- assert(*x == '='); -- x++; -- v = strndup(x, l - strlen(name) - 1); -- if (!v) -- return -ENOMEM; -- } -+ bool eq = *x == '='; -+ assert(eq || IN_SET(*x, ',', '\0')); -+ -+ r = free_and_strndup(&v, -+ eq ? x + 1 : NULL, -+ eq ? end - x - 1 : 0); -+ if (r < 0) -+ return r; - } -+ -+ break; - } - } -- } else { -- char **t, **s; - -+ if (*end) -+ word = end + 1; -+ else -+ break; -+ } -+ } else { - stor = strv_split(opts, ","); - if (!stor) - return -ENOMEM; -@@ -132,7 +135,8 @@ int fstab_filter_options(const char *opts, const char *names, - if (!strv) - return -ENOMEM; - -- for (s = t = strv; *s; s++) { -+ char **t = strv; -+ for (char **s = strv; *s; s++) { - NULSTR_FOREACH(name, names) { - x = startswith(*s, name); - if (x && IN_SET(*x, '\0', '=')) -@@ -144,18 +148,12 @@ int fstab_filter_options(const char *opts, const char *names, - continue; - found: - /* Keep the last occurrence found */ -- n = name; -+ namefound = name; - if (ret_value) { -- free(v); -- if (*x == '\0') -- v = NULL; -- else { -- assert(*x == '='); -- x++; -- v = strdup(x); -- if (!v) -- return -ENOMEM; -- } -+ assert(IN_SET(*x, '=', '\0')); -+ r = free_and_strdup(&v, *x == '=' ? x + 1 : NULL); -+ if (r < 0) -+ return r; - } - } - *t = NULL; -@@ -163,7 +161,7 @@ int fstab_filter_options(const char *opts, const char *names, - - answer: - if (ret_namefound) -- *ret_namefound = n; -+ *ret_namefound = namefound; - if (ret_filtered) { - char *f; - -@@ -176,7 +174,7 @@ answer: - if (ret_value) - *ret_value = TAKE_PTR(v); - -- return !!n; -+ return !!namefound; - } - - int fstab_extract_values(const char *opts, const char *name, char ***values) { -diff --git a/src/shared/generate-syscall-list.py b/src/shared/generate-syscall-list.py -new file mode 100755 -index 0000000..030c3fe ---- /dev/null -+++ b/src/shared/generate-syscall-list.py -@@ -0,0 +1,14 @@ -+#!/usr/bin/env python3 -+import sys -+import os -+ -+s390 = 's390' in os.uname().machine -+arm = 'arm' in os.uname().machine -+ -+for line in open(sys.argv[1]): -+ if line.startswith('s390_') and not s390: -+ continue -+ if line.startswith('arm_') and not arm: -+ continue -+ -+ print('"{}\\0"'.format(line.strip())) -diff --git a/src/shared/gpt.h b/src/shared/gpt.h -index 26a4e1e..30fcb88 100644 ---- a/src/shared/gpt.h -+++ b/src/shared/gpt.h -@@ -7,26 +7,26 @@ - - #include "id128-util.h" - --/* We only support root disk discovery for x86, x86-64, Itanium and ARM for -- * now, since EFI for anything else doesn't really exist, and we only -- * care for root partitions on the same disk as the EFI ESP. */ -+/* We only support root disk discovery for x86, x86-64, Itanium and ARM for now, since EFI for anything else -+ * doesn't really exist, and we only care for root partitions on the same disk as the EFI ESP. */ - --#define GPT_ROOT_X86 SD_ID128_MAKE(44,47,95,40,f2,97,41,b2,9a,f7,d1,31,d5,f0,45,8a) --#define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09) --#define GPT_ROOT_ARM SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3) --#define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae) --#define GPT_ROOT_IA64 SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97) --#define GPT_ESP SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b) --#define GPT_XBOOTLDR SD_ID128_MAKE(bc,13,c2,ff,59,e6,42,62,a3,52,b2,75,fd,6f,71,72) --#define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f) --#define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15) --#define GPT_SRV SD_ID128_MAKE(3b,8f,84,25,20,e0,4f,3b,90,7f,1a,25,a7,6f,98,e8) --#define GPT_VAR SD_ID128_MAKE(4d,21,b0,16,b5,34,45,c2,a9,fb,5c,16,e0,91,fd,2d) --#define GPT_TMP SD_ID128_MAKE(7e,c6,f5,57,3b,c5,4a,ca,b2,93,16,ef,5d,f6,39,d1) --#define GPT_USER_HOME SD_ID128_MAKE(77,3f,91,ef,66,d4,49,b5,bd,83,d6,83,bf,40,ad,16) -+#define GPT_ROOT_X86 SD_ID128_MAKE(44,47,95,40,f2,97,41,b2,9a,f7,d1,31,d5,f0,45,8a) -+#define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09) -+#define GPT_ROOT_ARM SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3) -+#define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae) -+#define GPT_ROOT_IA64 SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97) -+#define GPT_ESP SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b) -+#define GPT_XBOOTLDR SD_ID128_MAKE(bc,13,c2,ff,59,e6,42,62,a3,52,b2,75,fd,6f,71,72) -+#define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f) -+#define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15) -+#define GPT_SRV SD_ID128_MAKE(3b,8f,84,25,20,e0,4f,3b,90,7f,1a,25,a7,6f,98,e8) -+#define GPT_VAR SD_ID128_MAKE(4d,21,b0,16,b5,34,45,c2,a9,fb,5c,16,e0,91,fd,2d) -+#define GPT_TMP SD_ID128_MAKE(7e,c6,f5,57,3b,c5,4a,ca,b2,93,16,ef,5d,f6,39,d1) -+#define GPT_USER_HOME SD_ID128_MAKE(77,3f,91,ef,66,d4,49,b5,bd,83,d6,83,bf,40,ad,16) -+#define GPT_LINUX_GENERIC SD_ID128_MAKE(0f,c6,3d,af,84,83,47,72,8e,79,3d,69,d8,47,7d,e4) - --/* Verity partitions for the root partitions above (we only define them for the root partitions, because only they are -- * are commonly read-only and hence suitable for verity). */ -+/* Verity partitions for the root partitions above (we only define them for the root partitions, because only -+ * they are are commonly read-only and hence suitable for verity). */ - #define GPT_ROOT_X86_VERITY SD_ID128_MAKE(d1,3c,5d,3b,b5,d1,42,2a,b2,9f,94,54,fd,c8,9d,76) - #define GPT_ROOT_X86_64_VERITY SD_ID128_MAKE(2c,73,57,ed,eb,d2,46,d9,ae,c1,23,d4,37,ec,2b,f5) - #define GPT_ROOT_ARM_VERITY SD_ID128_MAKE(73,86,cd,f2,20,3c,47,a9,a4,98,f2,ec,ce,45,a2,d6) -@@ -62,15 +62,12 @@ - #define GPT_FLAG_NO_BLOCK_IO_PROTOCOL (1ULL << 1) - #define GPT_FLAG_LEGACY_BIOS_BOOTABLE (1ULL << 2) - --/* Flags we recognize on the root, swap, home and srv partitions when -- * doing auto-discovery. These happen to be identical to what -- * Microsoft defines for its own Basic Data Partitions, but that's -- * just because we saw no point in defining any other values here. */ -+/* Flags we recognize on the root, swap, home and srv partitions when doing auto-discovery. These happen to -+ * be identical to what Microsoft defines for its own Basic Data Partitions, but that's just because we saw -+ * no point in defining any other values here. */ - #define GPT_FLAG_READ_ONLY (1ULL << 60) - #define GPT_FLAG_NO_AUTO (1ULL << 63) - --#define GPT_LINUX_GENERIC SD_ID128_MAKE(0f,c6,3d,af,84,83,47,72,8e,79,3d,69,d8,47,7d,e4) -- - const char *gpt_partition_type_uuid_to_string(sd_id128_t id); - const char *gpt_partition_type_uuid_to_string_harder( - sd_id128_t id, -diff --git a/src/shared/group-record-nss.c b/src/shared/group-record-nss.c -deleted file mode 100644 -index 5c4fae8..0000000 ---- a/src/shared/group-record-nss.c -+++ /dev/null -@@ -1,219 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ -- --#include "errno-util.h" --#include "group-record-nss.h" --#include "libcrypt-util.h" --#include "strv.h" -- --int nss_group_to_group_record( -- const struct group *grp, -- const struct sgrp *sgrp, -- GroupRecord **ret) { -- -- _cleanup_(group_record_unrefp) GroupRecord *g = NULL; -- int r; -- -- assert(grp); -- assert(ret); -- -- if (isempty(grp->gr_name)) -- return -EINVAL; -- -- if (sgrp && !streq_ptr(sgrp->sg_namp, grp->gr_name)) -- return -EINVAL; -- -- g = group_record_new(); -- if (!g) -- return -ENOMEM; -- -- g->group_name = strdup(grp->gr_name); -- if (!g->group_name) -- return -ENOMEM; -- -- g->members = strv_copy(grp->gr_mem); -- if (!g->members) -- return -ENOMEM; -- -- g->gid = grp->gr_gid; -- -- if (sgrp) { -- if (hashed_password_valid(sgrp->sg_passwd)) { -- g->hashed_password = strv_new(sgrp->sg_passwd); -- if (!g->hashed_password) -- return -ENOMEM; -- } -- -- r = strv_extend_strv(&g->members, sgrp->sg_mem, 1); -- if (r < 0) -- return r; -- -- g->administrators = strv_copy(sgrp->sg_adm); -- if (!g->administrators) -- return -ENOMEM; -- } -- -- r = json_build(&g->json, JSON_BUILD_OBJECT( -- JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(g->group_name)), -- JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(g->gid)), -- JSON_BUILD_PAIR_CONDITION(!strv_isempty(g->members), "members", JSON_BUILD_STRV(g->members)), -- JSON_BUILD_PAIR_CONDITION(!strv_isempty(g->hashed_password), "privileged", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRV(g->hashed_password)))), -- JSON_BUILD_PAIR_CONDITION(!strv_isempty(g->administrators), "administrators", JSON_BUILD_STRV(g->administrators)))); -- if (r < 0) -- return r; -- -- g->mask = USER_RECORD_REGULAR | -- (!strv_isempty(g->hashed_password) ? USER_RECORD_PRIVILEGED : 0); -- -- *ret = TAKE_PTR(g); -- return 0; --} -- --int nss_sgrp_for_group(const struct group *grp, struct sgrp *ret_sgrp, char **ret_buffer) { -- size_t buflen = 4096; -- int r; -- -- assert(grp); -- assert(ret_sgrp); -- assert(ret_buffer); -- -- for (;;) { -- _cleanup_free_ char *buf = NULL; -- struct sgrp sgrp, *result; -- -- buf = malloc(buflen); -- if (!buf) -- return -ENOMEM; -- -- r = getsgnam_r(grp->gr_name, &sgrp, buf, buflen, &result); -- if (r == 0) { -- if (!result) -- return -ESRCH; -- -- *ret_sgrp = *result; -- *ret_buffer = TAKE_PTR(buf); -- return 0; -- } -- if (r < 0) -- return -EIO; /* Weird, this should not return negative! */ -- if (r != ERANGE) -- return -r; -- -- if (buflen > SIZE_MAX / 2) -- return -ERANGE; -- -- buflen *= 2; -- buf = mfree(buf); -- } --} -- --int nss_group_record_by_name( -- const char *name, -- bool with_shadow, -- GroupRecord **ret) { -- -- _cleanup_free_ char *buf = NULL, *sbuf = NULL; -- struct group grp, *result; -- bool incomplete = false; -- size_t buflen = 4096; -- struct sgrp sgrp, *sresult = NULL; -- int r; -- -- assert(name); -- assert(ret); -- -- for (;;) { -- buf = malloc(buflen); -- if (!buf) -- return -ENOMEM; -- -- r = getgrnam_r(name, &grp, buf, buflen, &result); -- if (r == 0) { -- if (!result) -- return -ESRCH; -- -- break; -- } -- -- if (r < 0) -- return log_debug_errno(SYNTHETIC_ERRNO(EIO), "getgrnam_r() returned a negative value"); -- if (r != ERANGE) -- return -r; -- if (buflen > SIZE_MAX / 2) -- return -ERANGE; -- -- buflen *= 2; -- buf = mfree(buf); -- } -- -- if (with_shadow) { -- r = nss_sgrp_for_group(result, &sgrp, &sbuf); -- if (r < 0) { -- log_debug_errno(r, "Failed to do shadow lookup for group %s, ignoring: %m", result->gr_name); -- incomplete = ERRNO_IS_PRIVILEGE(r); -- } else -- sresult = &sgrp; -- } else -- incomplete = true; -- -- r = nss_group_to_group_record(result, sresult, ret); -- if (r < 0) -- return r; -- -- (*ret)->incomplete = incomplete; -- return 0; --} -- --int nss_group_record_by_gid( -- gid_t gid, -- bool with_shadow, -- GroupRecord **ret) { -- -- _cleanup_free_ char *buf = NULL, *sbuf = NULL; -- struct group grp, *result; -- bool incomplete = false; -- size_t buflen = 4096; -- struct sgrp sgrp, *sresult = NULL; -- int r; -- -- assert(ret); -- -- for (;;) { -- buf = malloc(buflen); -- if (!buf) -- return -ENOMEM; -- -- r = getgrgid_r(gid, &grp, buf, buflen, &result); -- if (r == 0) { -- if (!result) -- return -ESRCH; -- break; -- } -- -- if (r < 0) -- return log_debug_errno(SYNTHETIC_ERRNO(EIO), "getgrgid_r() returned a negative value"); -- if (r != ERANGE) -- return -r; -- if (buflen > SIZE_MAX / 2) -- return -ERANGE; -- -- buflen *= 2; -- buf = mfree(buf); -- } -- -- if (with_shadow) { -- r = nss_sgrp_for_group(result, &sgrp, &sbuf); -- if (r < 0) { -- log_debug_errno(r, "Failed to do shadow lookup for group %s, ignoring: %m", result->gr_name); -- incomplete = ERRNO_IS_PRIVILEGE(r); -- } else -- sresult = &sgrp; -- } else -- incomplete = true; -- -- r = nss_group_to_group_record(result, sresult, ret); -- if (r < 0) -- return r; -- -- (*ret)->incomplete = incomplete; -- return 0; --} -diff --git a/src/shared/group-record-nss.h b/src/shared/group-record-nss.h -deleted file mode 100644 -index 077c22d..0000000 ---- a/src/shared/group-record-nss.h -+++ /dev/null -@@ -1,15 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ --#pragma once -- --#include --#include -- --#include "group-record.h" -- --/* Synthesize GroupRecord objects from NSS data */ -- --int nss_group_to_group_record(const struct group *grp, const struct sgrp *sgrp, GroupRecord **ret); --int nss_sgrp_for_group(const struct group *grp, struct sgrp *ret_sgrp, char **ret_buffer); -- --int nss_group_record_by_name(const char *name, bool with_shadow, GroupRecord **ret); --int nss_group_record_by_gid(gid_t gid, bool with_shadow, GroupRecord **ret); -diff --git a/src/shared/group-record-show.c b/src/shared/group-record-show.c -deleted file mode 100644 -index d0300e4..0000000 ---- a/src/shared/group-record-show.c -+++ /dev/null -@@ -1,76 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ -- --#include "format-util.h" --#include "group-record-show.h" --#include "strv.h" --#include "user-util.h" --#include "userdb.h" -- --void group_record_show(GroupRecord *gr, bool show_full_user_info) { -- int r; -- -- printf(" Group name: %s\n", -- group_record_group_name_and_realm(gr)); -- -- printf(" Disposition: %s\n", user_disposition_to_string(group_record_disposition(gr))); -- -- if (gr->last_change_usec != USEC_INFINITY) { -- char buf[FORMAT_TIMESTAMP_MAX]; -- printf(" Last Change: %s\n", format_timestamp(buf, sizeof(buf), gr->last_change_usec)); -- } -- -- if (gid_is_valid(gr->gid)) -- printf(" GID: " GID_FMT "\n", gr->gid); -- -- if (show_full_user_info) { -- _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL; -- -- r = membershipdb_by_group(gr->group_name, 0, &iterator); -- if (r < 0) { -- errno = -r; -- printf(" Members: (can't acquire: %m)"); -- } else { -- const char *prefix = " Members:"; -- -- for (;;) { -- _cleanup_free_ char *user = NULL; -- -- r = membershipdb_iterator_get(iterator, &user, NULL); -- if (r == -ESRCH) -- break; -- if (r < 0) { -- errno = -r; -- printf("%s (can't iterate: %m\n", prefix); -- break; -- } -- -- printf("%s %s\n", prefix, user); -- prefix = " "; -- } -- } -- } else { -- const char *prefix = " Members:"; -- char **i; -- -- STRV_FOREACH(i, gr->members) { -- printf("%s %s\n", prefix, *i); -- prefix = " "; -- } -- } -- -- if (!strv_isempty(gr->administrators)) { -- const char *prefix = " Admins:"; -- char **i; -- -- STRV_FOREACH(i, gr->administrators) { -- printf("%s %s\n", prefix, *i); -- prefix = " "; -- } -- } -- -- if (!strv_isempty(gr->hashed_password)) -- printf(" Passwords: %zu\n", strv_length(gr->hashed_password)); -- -- if (gr->service) -- printf(" Service: %s\n", gr->service); --} -diff --git a/src/shared/group-record-show.h b/src/shared/group-record-show.h -deleted file mode 100644 -index 12bdbd1..0000000 ---- a/src/shared/group-record-show.h -+++ /dev/null -@@ -1,6 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ --#pragma once -- --#include "group-record.h" -- --void group_record_show(GroupRecord *gr, bool show_full_user_info); -diff --git a/src/shared/group-record.c b/src/shared/group-record.c -index 3c95206..d999ff9 100644 ---- a/src/shared/group-record.c -+++ b/src/shared/group-record.c -@@ -28,6 +28,7 @@ static GroupRecord *group_record_free(GroupRecord *g) { - free(g->group_name); - free(g->realm); - free(g->group_name_and_realm_auto); -+ free(g->description); - - strv_free(g->members); - free(g->service); -@@ -192,6 +193,7 @@ int group_record_load( - static const JsonDispatch group_dispatch_table[] = { - { "groupName", JSON_VARIANT_STRING, json_dispatch_user_group_name, offsetof(GroupRecord, group_name), JSON_RELAX}, - { "realm", JSON_VARIANT_STRING, json_dispatch_realm, offsetof(GroupRecord, realm), 0 }, -+ { "description", JSON_VARIANT_STRING, json_dispatch_gecos, offsetof(GroupRecord, description), 0 }, - { "disposition", JSON_VARIANT_STRING, json_dispatch_user_disposition, offsetof(GroupRecord, disposition), 0 }, - { "service", JSON_VARIANT_STRING, json_dispatch_string, offsetof(GroupRecord, service), JSON_SAFE }, - { "lastChangeUSec", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(GroupRecord, last_change_usec), 0 }, -diff --git a/src/shared/group-record.h b/src/shared/group-record.h -index b72a43e..85c91eb 100644 ---- a/src/shared/group-record.h -+++ b/src/shared/group-record.h -@@ -13,6 +13,8 @@ typedef struct GroupRecord { - char *realm; - char *group_name_and_realm_auto; - -+ char *description; -+ - UserDisposition disposition; - uint64_t last_change_usec; - -diff --git a/src/shared/install.c b/src/shared/install.c -index 3d19387..cd14b2c 100644 ---- a/src/shared/install.c -+++ b/src/shared/install.c -@@ -76,12 +76,10 @@ static bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) { - } - - void unit_file_presets_freep(UnitFilePresets *p) { -- size_t i; -- - if (!p) - return; - -- for (i = 0; i < p->n_rules; i++) { -+ for (size_t i = 0; i < p->n_rules; i++) { - free(p->rules[i].pattern); - strv_free(p->rules[i].instances); - } -@@ -251,6 +249,15 @@ static int path_is_vendor_or_generator(const LookupPaths *p, const char *path) { - return path_equal(rpath, SYSTEM_DATA_UNIT_PATH); - } - -+static const char* config_path_from_flags(const LookupPaths *paths, UnitFileFlags flags) { -+ assert(paths); -+ -+ if (FLAGS_SET(flags, UNIT_FILE_PORTABLE)) -+ return FLAGS_SET(flags, UNIT_FILE_RUNTIME) ? paths->runtime_attached : paths->persistent_attached; -+ else -+ return FLAGS_SET(flags, UNIT_FILE_RUNTIME) ? paths->runtime_config : paths->persistent_config; -+} -+ - int unit_file_changes_add( - UnitFileChange **changes, - size_t *n_changes, -@@ -290,11 +297,9 @@ int unit_file_changes_add( - } - - void unit_file_changes_free(UnitFileChange *changes, size_t n_changes) { -- size_t i; -- - assert(changes || n_changes == 0); - -- for (i = 0; i < n_changes; i++) { -+ for (size_t i = 0; i < n_changes; i++) { - free(changes[i].path); - free(changes[i].source); - } -@@ -303,14 +308,13 @@ void unit_file_changes_free(UnitFileChange *changes, size_t n_changes) { - } - - void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet) { -- size_t i; - bool logged = false; - - assert(changes || n_changes == 0); - /* If verb is not specified, errors are not allowed! */ - assert(verb || r >= 0); - -- for (i = 0; i < n_changes; i++) { -+ for (size_t i = 0; i < n_changes; i++) { - assert(verb || changes[i].type >= 0); - - switch(changes[i].type) { -@@ -2587,7 +2591,7 @@ int unit_file_enable( - if (r < 0) - return r; - -- config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; -+ config_path = config_path_from_flags(&paths, flags); - if (!config_path) - return -ENXIO; - -@@ -2630,7 +2634,7 @@ int unit_file_disable( - if (r < 0) - return r; - -- config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; -+ config_path = config_path_from_flags(&paths, flags); - if (!config_path) - return -ENXIO; - -@@ -3055,20 +3059,17 @@ static int pattern_match_multiple_instances( - - /* Compose a list of specified instances when unit name is a template */ - if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { -- _cleanup_free_ char *prefix = NULL; - _cleanup_strv_free_ char **out_strv = NULL; -- char **iter; -- -- r = unit_name_to_prefix(unit_name, &prefix); -- if (r < 0) -- return r; - -+ char **iter; - STRV_FOREACH(iter, rule.instances) { - _cleanup_free_ char *name = NULL; -- r = unit_name_build(prefix, *iter, ".service", &name); -+ -+ r = unit_name_replace_instance(unit_name, *iter, &name); - if (r < 0) - return r; -- r = strv_extend(&out_strv, name); -+ -+ r = strv_consume(&out_strv, TAKE_PTR(name)); - if (r < 0) - return r; - } -@@ -3091,12 +3092,11 @@ static int pattern_match_multiple_instances( - - static int query_presets(const char *name, const UnitFilePresets *presets, char ***instance_name_list) { - PresetAction action = PRESET_UNKNOWN; -- size_t i; -- char **s; -+ - if (!unit_name_is_valid(name, UNIT_NAME_ANY)) - return -EINVAL; - -- for (i = 0; i < presets->n_rules; i++) -+ for (size_t i = 0; i < presets->n_rules; i++) - if (pattern_match_multiple_instances(presets->rules[i], name, instance_name_list) > 0 || - fnmatch(presets->rules[i].pattern, name, FNM_NOESCAPE) == 0) { - action = presets->rules[i].action; -@@ -3108,10 +3108,11 @@ static int query_presets(const char *name, const UnitFilePresets *presets, char - log_debug("Preset files don't specify rule for %s. Enabling.", name); - return 1; - case PRESET_ENABLE: -- if (instance_name_list && *instance_name_list) -+ if (instance_name_list && *instance_name_list) { -+ char **s; - STRV_FOREACH(s, *instance_name_list) - log_debug("Preset files say enable %s.", *s); -- else -+ } else - log_debug("Preset files say enable %s.", name); - return 1; - case PRESET_DISABLE: -diff --git a/src/shared/install.h b/src/shared/install.h -index 788517d..23ac995 100644 ---- a/src/shared/install.h -+++ b/src/shared/install.h -@@ -35,9 +35,11 @@ enum UnitFileChangeType { - }; - - enum UnitFileFlags { -- UNIT_FILE_RUNTIME = 1 << 0, -- UNIT_FILE_FORCE = 1 << 1, -- UNIT_FILE_DRY_RUN = 1 << 2, -+ UNIT_FILE_RUNTIME = 1 << 0, /* Public API via DBUS, do not change */ -+ UNIT_FILE_FORCE = 1 << 1, /* Public API via DBUS, do not change */ -+ UNIT_FILE_PORTABLE = 1 << 2, /* Public API via DBUS, do not change */ -+ UNIT_FILE_DRY_RUN = 1 << 3, -+ _UNIT_FILE_FLAGS_MASK_PUBLIC = UNIT_FILE_RUNTIME|UNIT_FILE_PORTABLE|UNIT_FILE_FORCE, - }; - - /* type can either one of the UnitFileChangeTypes listed above, or a negative error. -diff --git a/src/shared/journal-util.c b/src/shared/journal-util.c -index cb3762d..4d0edbb 100644 ---- a/src/shared/journal-util.c -+++ b/src/shared/journal-util.c -@@ -85,7 +85,6 @@ int journal_access_blocked(sd_journal *j) { - } - - int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_users) { -- Iterator it; - void *code; - char *path; - int r = 0; -@@ -107,7 +106,7 @@ int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_use - r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions."); - } - -- HASHMAP_FOREACH_KEY(path, code, j->errors, it) { -+ HASHMAP_FOREACH_KEY(path, code, j->errors) { - int err; - - err = abs(PTR_TO_INT(code)); -diff --git a/src/shared/json.c b/src/shared/json.c -index 27a3a51..e938e59 100644 ---- a/src/shared/json.c -+++ b/src/shared/json.c -@@ -405,6 +405,9 @@ int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n) { - return 0; - } - -+ if (!utf8_is_valid_n(s, n)) /* JSON strings must be valid UTF-8 */ -+ return -EUCLEAN; -+ - r = json_variant_new(&v, JSON_VARIANT_STRING, n + 1); - if (r < 0) - return r; -@@ -430,6 +433,12 @@ int json_variant_new_base64(JsonVariant **ret, const void *p, size_t n) { - return json_variant_new_stringn(ret, s, k); - } - -+int json_variant_new_id128(JsonVariant **ret, sd_id128_t id) { -+ char s[SD_ID128_STRING_MAX]; -+ -+ return json_variant_new_string(ret, sd_id128_to_string(id, s)); -+} -+ - static void json_variant_set(JsonVariant *a, JsonVariant *b) { - assert(a); - -@@ -630,8 +639,12 @@ int json_variant_new_array_strv(JsonVariant **ret, char **l) { - return r; - - w->is_reference = true; -- } else -+ } else { -+ if (!utf8_is_valid_n(l[v->n_elements], k)) /* JSON strings must be valid UTF-8 */ -+ return -EUCLEAN; -+ - memcpy(w->string, l[v->n_elements], k+1); -+ } - } - - v->normalized = true; -@@ -1476,6 +1489,58 @@ static int print_source(FILE *f, JsonVariant *v, JsonFormatFlags flags, bool whi - return 0; - } - -+static void json_format_string(FILE *f, const char *q, JsonFormatFlags flags) { -+ assert(q); -+ -+ fputc('"', f); -+ -+ if (flags & JSON_FORMAT_COLOR) -+ fputs(ANSI_GREEN, f); -+ -+ for (; *q; q++) -+ switch (*q) { -+ case '"': -+ fputs("\\\"", f); -+ break; -+ -+ case '\\': -+ fputs("\\\\", f); -+ break; -+ -+ case '\b': -+ fputs("\\b", f); -+ break; -+ -+ case '\f': -+ fputs("\\f", f); -+ break; -+ -+ case '\n': -+ fputs("\\n", f); -+ break; -+ -+ case '\r': -+ fputs("\\r", f); -+ break; -+ -+ case '\t': -+ fputs("\\t", f); -+ break; -+ -+ default: -+ if ((signed char) *q >= 0 && *q < ' ') -+ fprintf(f, "\\u%04x", *q); -+ else -+ fputc(*q, f); -+ break; -+ } -+ -+ if (flags & JSON_FORMAT_COLOR) -+ fputs(ANSI_NORMAL, f); -+ -+ fputc('"', f); -+} -+ - static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const char *prefix) { - int r; - -@@ -1548,61 +1613,9 @@ static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const cha - fputs(ANSI_NORMAL, f); - break; - -- case JSON_VARIANT_STRING: { -- const char *q; -- -- fputc('"', f); -- -- if (flags & JSON_FORMAT_COLOR) -- fputs(ANSI_GREEN, f); -- -- for (q = json_variant_string(v); *q; q++) { -- -- switch (*q) { -- -- case '"': -- fputs("\\\"", f); -- break; -- -- case '\\': -- fputs("\\\\", f); -- break; -- -- case '\b': -- fputs("\\b", f); -- break; -- -- case '\f': -- fputs("\\f", f); -- break; -- -- case '\n': -- fputs("\\n", f); -- break; -- -- case '\r': -- fputs("\\r", f); -- break; -- -- case '\t': -- fputs("\\t", f); -- break; -- -- default: -- if ((signed char) *q >= 0 && *q < ' ') -- fprintf(f, "\\u%04x", *q); -- else -- fputc(*q, f); -- break; -- } -- } -- -- if (flags & JSON_FORMAT_COLOR) -- fputs(ANSI_NORMAL, f); -- -- fputc('"', f); -+ case JSON_VARIANT_STRING: -+ json_format_string(f, json_variant_string(v), flags); - break; -- } - - case JSON_VARIANT_ARRAY: { - size_t i, n; -@@ -1964,6 +1977,17 @@ int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b) { - return json_variant_set_field(v, field, m); - } - -+int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l) { -+ _cleanup_(json_variant_unrefp) JsonVariant *m = NULL; -+ int r; -+ -+ r = json_variant_new_array_strv(&m, l); -+ if (r < 0) -+ return r; -+ -+ return json_variant_set_field(v, field, m); -+} -+ - int json_variant_merge(JsonVariant **v, JsonVariant *m) { - _cleanup_(json_variant_unrefp) JsonVariant *w = NULL; - _cleanup_free_ JsonVariant **array = NULL; -@@ -3579,6 +3603,64 @@ int json_buildv(JsonVariant **ret, va_list ap) { - break; - } - -+ case _JSON_BUILD_ID128: { -+ sd_id128_t id; -+ -+ if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { -+ r = -EINVAL; -+ goto finish; -+ } -+ -+ id = va_arg(ap, sd_id128_t); -+ -+ if (current->n_suppress == 0) { -+ r = json_variant_new_id128(&add, id); -+ if (r < 0) -+ goto finish; -+ } -+ -+ n_subtract = 1; -+ -+ if (current->expect == EXPECT_TOPLEVEL) -+ current->expect = EXPECT_END; -+ else if (current->expect == EXPECT_OBJECT_VALUE) -+ current->expect = EXPECT_OBJECT_KEY; -+ else -+ assert(current->expect == EXPECT_ARRAY_ELEMENT); -+ -+ break; -+ } -+ -+ case _JSON_BUILD_BYTE_ARRAY: { -+ const void *array; -+ size_t n; -+ -+ if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { -+ r = -EINVAL; -+ goto finish; -+ } -+ -+ array = va_arg(ap, const void*); -+ n = va_arg(ap, size_t); -+ -+ if (current->n_suppress == 0) { -+ r = json_variant_new_array_bytes(&add, array, n); -+ if (r < 0) -+ goto finish; -+ } -+ -+ n_subtract = 1; -+ -+ if (current->expect == EXPECT_TOPLEVEL) -+ current->expect = EXPECT_END; -+ else if (current->expect == EXPECT_OBJECT_VALUE) -+ current->expect = EXPECT_OBJECT_KEY; -+ else -+ assert(current->expect == EXPECT_ARRAY_ELEMENT); -+ -+ break; -+ } -+ - case _JSON_BUILD_OBJECT_BEGIN: - - if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { -diff --git a/src/shared/json.h b/src/shared/json.h -index ceb01a2..1d6fec6 100644 ---- a/src/shared/json.h -+++ b/src/shared/json.h -@@ -7,6 +7,8 @@ - #include - #include - -+#include "sd-id128.h" -+ - #include "macro.h" - #include "string-util.h" - #include "log.h" -@@ -65,6 +67,7 @@ int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n); - int json_variant_new_array_strv(JsonVariant **ret, char **l); - int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n); - int json_variant_new_null(JsonVariant **ret); -+int json_variant_new_id128(JsonVariant **ret, sd_id128_t id); - - static inline int json_variant_new_string(JsonVariant **ret, const char *s) { - return json_variant_new_stringn(ret, s, (size_t) -1); -@@ -183,6 +186,7 @@ int json_variant_set_field_string(JsonVariant **v, const char *field, const char - int json_variant_set_field_integer(JsonVariant **v, const char *field, intmax_t value); - int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uintmax_t value); - int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b); -+int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l); - - int json_variant_append_array(JsonVariant **v, JsonVariant *element); - -@@ -223,6 +227,8 @@ enum { - _JSON_BUILD_LITERAL, - _JSON_BUILD_STRV, - _JSON_BUILD_BASE64, -+ _JSON_BUILD_ID128, -+ _JSON_BUILD_BYTE_ARRAY, - _JSON_BUILD_MAX, - }; - -@@ -243,6 +249,8 @@ enum { - #define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, ({ const char *_x = l; _x; }) - #define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, ({ char **_x = l; _x; }) - #define JSON_BUILD_BASE64(p, n) _JSON_BUILD_BASE64, ({ const void *_x = p; _x; }), ({ size_t _y = n; _y; }) -+#define JSON_BUILD_ID128(id) _JSON_BUILD_ID128, ({ sd_id128_t _x = id; _x; }) -+#define JSON_BUILD_BYTE_ARRAY(v, n) _JSON_BUILD_BYTE_ARRAY, ({ const void *_x = v; _x; }), ({ size_t _y = n; _y; }) - - int json_build(JsonVariant **ret, ...); - int json_buildv(JsonVariant **ret, va_list ap); -@@ -296,6 +304,12 @@ assert_cc(sizeof(uintmax_t) == sizeof(uint64_t)); - assert_cc(sizeof(intmax_t) == sizeof(int64_t)); - #define json_dispatch_int64 json_dispatch_integer - -+assert_cc(sizeof(uint32_t) == sizeof(unsigned)); -+#define json_dispatch_uint json_dispatch_uint32 -+ -+assert_cc(sizeof(int32_t) == sizeof(int)); -+#define json_dispatch_int json_dispatch_int32 -+ - static inline int json_dispatch_level(JsonDispatchFlags flags) { - - /* Did the user request no logging? If so, then never log higher than LOG_DEBUG. Also, if this is marked as -diff --git a/src/shared/libcrypt-util.c b/src/shared/libcrypt-util.c -index f41685a..bf66055 100644 ---- a/src/shared/libcrypt-util.c -+++ b/src/shared/libcrypt-util.c -@@ -74,13 +74,18 @@ int make_salt(char **ret) { - #endif - } - --bool hashed_password_valid(const char *s) { -- -- /* Returns true if the specified string is a 'valid' hashed UNIX password, i.e. if starts with '$' or -- * with '!$' (the latter being a valid, yet locked password). */ -- -- if (isempty(s)) -+bool looks_like_hashed_password(const char *s) { -+ /* Returns false if the specified string is certainly not a hashed UNIX password. crypt(5) lists -+ * various hashing methods. We only reject (return false) strings which are documented to have -+ * different meanings. -+ * -+ * In particular, we allow locked passwords, i.e. strings starting with "!", including just "!", -+ * i.e. the locked empty password. See also fc58c0c7bf7e4f525b916e3e5be0de2307fef04e. -+ */ -+ if (!s) - return false; - -- return STARTSWITH_SET(s, "$", "!$"); -+ s += strspn(s, "!"); /* Skip (possibly duplicated) locking prefix */ -+ -+ return !STR_IN_SET(s, "x", "*"); - } -diff --git a/src/shared/libcrypt-util.h b/src/shared/libcrypt-util.h -index 93f0e13..8a860ce 100644 ---- a/src/shared/libcrypt-util.h -+++ b/src/shared/libcrypt-util.h -@@ -19,4 +19,4 @@ - - int make_salt(char **ret); - --bool hashed_password_valid(const char *s); -+bool looks_like_hashed_password(const char *s); -diff --git a/src/shared/log-link.h b/src/shared/log-link.h -index 2d03802..b844f9e 100644 ---- a/src/shared/log-link.h -+++ b/src/shared/log-link.h -@@ -14,24 +14,26 @@ - * See, network/networkd-link.h for example. - */ - --#define log_link_full(link, level, error, ...) \ -+#define log_link_full_errno(link, level, error, ...) \ - ({ \ - const Link *_l = (link); \ - (_l && _l->ifname) ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ - log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ - }) \ - --#define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) --#define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__) --#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__) --#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__) --#define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__) -+#define log_link_full(link, level, ...) (void) log_link_full_errno(link, level, 0, __VA_ARGS__) - --#define log_link_debug_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__) --#define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__) --#define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__) --#define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__) --#define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__) -+#define log_link_debug(link, ...) log_link_full_errno(link, LOG_DEBUG, 0, __VA_ARGS__) -+#define log_link_info(link, ...) log_link_full(link, LOG_INFO, __VA_ARGS__) -+#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, __VA_ARGS__) -+#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, __VA_ARGS__) -+#define log_link_error(link, ...) log_link_full(link, LOG_ERR, __VA_ARGS__) -+ -+#define log_link_debug_errno(link, error, ...) log_link_full_errno(link, LOG_DEBUG, error, __VA_ARGS__) -+#define log_link_info_errno(link, error, ...) log_link_full_errno(link, LOG_INFO, error, __VA_ARGS__) -+#define log_link_notice_errno(link, error, ...) log_link_full_errno(link, LOG_NOTICE, error, __VA_ARGS__) -+#define log_link_warning_errno(link, error, ...) log_link_full_errno(link, LOG_WARNING, error, __VA_ARGS__) -+#define log_link_error_errno(link, error, ...) log_link_full_errno(link, LOG_ERR, error, __VA_ARGS__) - - #define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__ - #define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname -diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c -index 899e894..4f25c64 100644 ---- a/src/shared/logs-show.c -+++ b/src/shared/logs-show.c -@@ -168,8 +168,12 @@ typedef struct ParseFieldVec { - size_t *target_len; - } ParseFieldVec; - --#define PARSE_FIELD_VEC_ENTRY(_field, _target, _target_len) \ -- { .field = _field, .field_len = strlen(_field), .target = _target, .target_len = _target_len } -+#define PARSE_FIELD_VEC_ENTRY(_field, _target, _target_len) { \ -+ .field = _field, \ -+ .field_len = strlen(_field), \ -+ .target = _target, \ -+ .target_len = _target_len \ -+ } - - static int parse_fieldv(const void *data, size_t length, const ParseFieldVec *fields, unsigned n_fields) { - unsigned i; -@@ -364,7 +368,7 @@ static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, Ou - const char *k; - - if (flags & OUTPUT_UTC) -- k = format_timestamp_utc(buf, sizeof(buf), x); -+ k = format_timestamp_style(buf, sizeof(buf), x, TIMESTAMP_UTC); - else - k = format_timestamp(buf, sizeof(buf), x); - if (!k) -@@ -681,8 +685,8 @@ static int output_verbose( - if (r < 0) - return log_error_errno(r, "Failed to get cursor: %m"); - -- timestamp = flags & OUTPUT_UTC ? format_timestamp_us_utc(ts, sizeof ts, realtime) -- : format_timestamp_us(ts, sizeof ts, realtime); -+ timestamp = format_timestamp_style(ts, sizeof ts, realtime, -+ flags & OUTPUT_UTC ? TIMESTAMP_US_UTC : TIMESTAMP_US); - fprintf(f, "%s [%s]\n", - timestamp ?: "(no timestamp)", - cursor); -@@ -996,7 +1000,6 @@ static int output_json( - sd_id128_t boot_id; - Hashmap *h = NULL; - size_t n = 0; -- Iterator i; - int r; - - assert(j); -@@ -1066,7 +1069,7 @@ static int output_json( - goto finish; - } - -- HASHMAP_FOREACH(d, h, i) { -+ HASHMAP_FOREACH(d, h) { - assert(d->n_values > 0); - - array[n++] = json_variant_ref(d->name); -@@ -1122,19 +1125,17 @@ static int output_cat_field( - FILE *f, - sd_journal *j, - OutputFlags flags, -+ int prio, - const char *field, - const size_t highlight[2]) { - -- const char *highlight_on, *highlight_off; -+ const char *color_on = "", *color_off = "", *highlight_on = ""; - const void *data; - size_t l, fl; - int r; - -- if (FLAGS_SET(flags, OUTPUT_COLOR)) { -- highlight_on = ANSI_HIGHLIGHT_RED; -- highlight_off = ANSI_NORMAL; -- } else -- highlight_on = highlight_off = ""; -+ if (FLAGS_SET(flags, OUTPUT_COLOR)) -+ get_log_colors(prio, &color_on, &color_off, &highlight_on); - - r = sd_journal_get_data(j, field, &data, &l); - if (r == -EBADMSG) { -@@ -1153,15 +1154,23 @@ static int output_cat_field( - data = (const uint8_t*) data + fl + 1; - l -= fl + 1; - -- if (highlight && FLAGS_SET(flags, OUTPUT_COLOR)) { -- assert(highlight[0] <= highlight[1]); -- assert(highlight[1] <= l); -- -- fwrite((const char*) data, 1, highlight[0], f); -- fwrite(highlight_on, 1, strlen(highlight_on), f); -- fwrite((const char*) data + highlight[0], 1, highlight[1] - highlight[0], f); -- fwrite(highlight_off, 1, strlen(highlight_off), f); -- fwrite((const char*) data + highlight[1], 1, l - highlight[1], f); -+ if (FLAGS_SET(flags, OUTPUT_COLOR)) { -+ if (highlight) { -+ assert(highlight[0] <= highlight[1]); -+ assert(highlight[1] <= l); -+ -+ fputs(color_on, f); -+ fwrite((const char*) data, 1, highlight[0], f); -+ fputs(highlight_on, f); -+ fwrite((const char*) data + highlight[0], 1, highlight[1] - highlight[0], f); -+ fputs(color_on, f); -+ fwrite((const char*) data + highlight[1], 1, l - highlight[1], f); -+ fputs(color_off, f); -+ } else { -+ fputs(color_on, f); -+ fwrite((const char*) data, 1, l, f); -+ fputs(color_off, f); -+ } - } else - fwrite((const char*) data, 1, l, f); - -@@ -1178,20 +1187,43 @@ static int output_cat( - const Set *output_fields, - const size_t highlight[2]) { - -+ int r, prio = LOG_INFO; - const char *field; -- Iterator iterator; -- int r; - - assert(j); - assert(f); - - (void) sd_journal_set_data_threshold(j, 0); - -+ if (FLAGS_SET(flags, OUTPUT_COLOR)) { -+ const void *data; -+ size_t l; -+ -+ /* Determine priority of this entry, so that we can color it nicely */ -+ -+ r = sd_journal_get_data(j, "PRIORITY", &data, &l); -+ if (r == -EBADMSG) { -+ log_debug_errno(r, "Skipping message we can't read: %m"); -+ return 0; -+ } -+ if (r < 0) { -+ if (r != -ENOENT) -+ return log_error_errno(r, "Failed to get data: %m"); -+ -+ /* An entry without PRIORITY */ -+ } else if (l == 10 && memcmp(data, "PRIORITY=", 9) == 0) { -+ char c = ((char*) data)[9]; -+ -+ if (c >= '0' && c <= '7') -+ prio = c - '0'; -+ } -+ } -+ - if (set_isempty(output_fields)) -- return output_cat_field(f, j, flags, "MESSAGE", highlight); -+ return output_cat_field(f, j, flags, prio, "MESSAGE", highlight); - -- SET_FOREACH(field, output_fields, iterator) { -- r = output_cat_field(f, j, flags, field, streq(field, "MESSAGE") ? highlight : NULL); -+ SET_FOREACH(field, output_fields) { -+ r = output_cat_field(f, j, flags, prio, field, streq(field, "MESSAGE") ? highlight : NULL); - if (r < 0) - return r; - } -diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c -index 4a593b0..fcbd5a5 100644 ---- a/src/shared/loop-util.c -+++ b/src/shared/loop-util.c -@@ -14,20 +14,92 @@ - #include - - #include "alloc-util.h" -+#include "blockdev-util.h" - #include "errno-util.h" - #include "fd-util.h" - #include "fileio.h" - #include "loop-util.h" -+#include "missing_loop.h" - #include "parse-util.h" - #include "stat-util.h" - #include "stdio-util.h" - #include "string-util.h" - - static void cleanup_clear_loop_close(int *fd) { -- if (*fd >= 0) { -- (void) ioctl(*fd, LOOP_CLR_FD); -- (void) safe_close(*fd); -+ if (*fd < 0) -+ return; -+ -+ (void) ioctl(*fd, LOOP_CLR_FD); -+ (void) safe_close(*fd); -+} -+ -+static int loop_configure(int fd, const struct loop_config *c) { -+ int r; -+ -+ assert(fd >= 0); -+ assert(c); -+ -+ if (ioctl(fd, LOOP_CONFIGURE, c) < 0) { -+ /* Do fallback only if LOOP_CONFIGURE is not supported, propagate all other errors. Note that -+ * the kernel is weird: non-existing ioctls currently return EINVAL rather than ENOTTY on -+ * loopback block devices. They should fix that in the kernel, but in the meantime we accept -+ * both here. */ -+ if (!ERRNO_IS_NOT_SUPPORTED(errno) && errno != EINVAL) -+ return -errno; -+ } else { -+ bool good = true; -+ -+ if (c->info.lo_sizelimit != 0) { -+ /* Kernel 5.8 vanilla doesn't properly propagate the size limit into the block -+ * device. If it's used, let's immediately check if it had the desired effect -+ * hence. And if not use classic LOOP_SET_STATUS64. */ -+ uint64_t z; -+ -+ if (ioctl(fd, BLKGETSIZE64, &z) < 0) { -+ r = -errno; -+ goto fail; -+ } -+ -+ if (z != c->info.lo_sizelimit) { -+ log_debug("LOOP_CONFIGURE is broken, doesn't honour .lo_sizelimit. Falling back to LOOP_SET_STATUS64."); -+ good = false; -+ } -+ } -+ -+ if (FLAGS_SET(c->info.lo_flags, LO_FLAGS_PARTSCAN)) { -+ /* Kernel 5.8 vanilla doesn't properly propagate the partition scanning flag into the -+ * block device. Let's hence verify if things work correctly here before -+ * returning. */ -+ -+ r = blockdev_partscan_enabled(fd); -+ if (r < 0) -+ goto fail; -+ if (r == 0) { -+ log_debug("LOOP_CONFIGURE is broken, doesn't honour LO_FLAGS_PARTSCAN. Falling back to LOOP_SET_STATUS64."); -+ good = false; -+ } -+ } -+ -+ if (good) -+ return 0; -+ -+ /* Otherwise, undo the attachment and use the old APIs */ -+ (void) ioctl(fd, LOOP_CLR_FD); -+ } -+ -+ if (ioctl(fd, LOOP_SET_FD, c->fd) < 0) -+ return -errno; -+ -+ if (ioctl(fd, LOOP_SET_STATUS64, &c->info) < 0) { -+ r = -errno; -+ goto fail; - } -+ -+ return 0; -+ -+fail: -+ (void) ioctl(fd, LOOP_CLR_FD); -+ return r; - } - - int loop_device_make( -@@ -39,7 +111,7 @@ int loop_device_make( - LoopDevice **ret) { - - _cleanup_free_ char *loopdev = NULL; -- struct loop_info64 info; -+ struct loop_config config; - LoopDevice *d = NULL; - struct stat st; - int nr = -1, r; -@@ -52,14 +124,14 @@ int loop_device_make( - return -errno; - - if (S_ISBLK(st.st_mode)) { -- if (ioctl(fd, LOOP_GET_STATUS64, &info) >= 0) { -+ if (ioctl(fd, LOOP_GET_STATUS64, &config.info) >= 0) { - /* Oh! This is a loopback device? That's interesting! */ - - #if HAVE_VALGRIND_MEMCHECK_H - /* Valgrind currently doesn't know LOOP_GET_STATUS64. Remove this once it does */ -- VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info)); -+ VALGRIND_MAKE_MEM_DEFINED(&config.info, sizeof(config.info)); - #endif -- nr = info.lo_number; -+ nr = config.info.lo_number; - - if (asprintf(&loopdev, "/dev/loop%i", nr) < 0) - return -ENOMEM; -@@ -100,6 +172,16 @@ int loop_device_make( - if (control < 0) - return -errno; - -+ config = (struct loop_config) { -+ .fd = fd, -+ .info = { -+ /* Use the specified flags, but configure the read-only flag from the open flags, and force autoclear */ -+ .lo_flags = (loop_flags & ~LO_FLAGS_READ_ONLY) | ((loop_flags & O_ACCMODE) == O_RDONLY ? LO_FLAGS_READ_ONLY : 0) | LO_FLAGS_AUTOCLEAR, -+ .lo_offset = offset, -+ .lo_sizelimit = size == UINT64_MAX ? 0 : size, -+ }, -+ }; -+ - /* Loop around LOOP_CTL_GET_FREE, since at the moment we attempt to open the returned device it might - * be gone already, taken by somebody else racing against us. */ - for (unsigned n_attempts = 0;;) { -@@ -119,12 +201,13 @@ int loop_device_make( - if (errno != ENOENT) - return -errno; - } else { -- if (ioctl(loop, LOOP_SET_FD, fd) >= 0) { -+ r = loop_configure(loop, &config); -+ if (r >= 0) { - loop_with_fd = TAKE_FD(loop); - break; - } -- if (errno != EBUSY) -- return -errno; -+ if (r != -EBUSY) -+ return r; - } - - if (++n_attempts >= 64) /* Give up eventually */ -@@ -133,16 +216,6 @@ int loop_device_make( - loopdev = mfree(loopdev); - } - -- info = (struct loop_info64) { -- /* Use the specified flags, but configure the read-only flag from the open flags, and force autoclear */ -- .lo_flags = (loop_flags & ~LO_FLAGS_READ_ONLY) | ((loop_flags & O_ACCMODE) == O_RDONLY ? LO_FLAGS_READ_ONLY : 0) | LO_FLAGS_AUTOCLEAR, -- .lo_offset = offset, -- .lo_sizelimit = size == UINT64_MAX ? 0 : size, -- }; -- -- if (ioctl(loop_with_fd, LOOP_SET_STATUS64, &info) < 0) -- return -errno; -- - d = new(LoopDevice, 1); - if (!d) - return -ENOMEM; -@@ -423,3 +496,18 @@ int loop_device_flock(LoopDevice *d, int operation) { - - return 0; - } -+ -+int loop_device_sync(LoopDevice *d) { -+ assert(d); -+ -+ /* We also do this implicitly in loop_device_unref(). Doing this explicitly here has the benefit that -+ * we can check the return value though. */ -+ -+ if (d->fd < 0) -+ return -EBADF; -+ -+ if (fsync(d->fd) < 0) -+ return -errno; -+ -+ return 0; -+} -diff --git a/src/shared/loop-util.h b/src/shared/loop-util.h -index 73f82a6..16f215b 100644 ---- a/src/shared/loop-util.h -+++ b/src/shared/loop-util.h -@@ -26,3 +26,4 @@ void loop_device_relinquish(LoopDevice *d); - int loop_device_refresh_size(LoopDevice *d, uint64_t offset, uint64_t size); - - int loop_device_flock(LoopDevice *d, int operation); -+int loop_device_sync(LoopDevice *d); -diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c -index 1b7cfb5..c6ff418 100644 ---- a/src/shared/machine-image.c -+++ b/src/shared/machine-image.c -@@ -1171,7 +1171,7 @@ int image_read_metadata(Image *i) { - if (r < 0) - return r; - -- r = dissect_image(d->fd, NULL, 0, NULL, DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_RELAX_VAR_CHECK, &m); -+ r = dissect_image(d->fd, NULL, 0, NULL, NULL, DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_RELAX_VAR_CHECK, &m); - if (r < 0) - return r; - -diff --git a/src/shared/meson.build b/src/shared/meson.build -index 0da733c..723e00e 100644 ---- a/src/shared/meson.build -+++ b/src/shared/meson.build -@@ -73,8 +73,8 @@ shared_sources = files(''' - coredump-util.h - cpu-set-util.c - cpu-set-util.h -- crypt-util.c -- crypt-util.h -+ cryptsetup-util.c -+ cryptsetup-util.h - daemon-util.h - dev-setup.c - dev-setup.h -@@ -113,10 +113,6 @@ shared_sources = files(''' - geneve-util.h - gpt.c - gpt.h -- group-record-nss.c -- group-record-nss.h -- group-record-show.c -- group-record-show.h - group-record.c - group-record.h - id128-print.c -@@ -166,6 +162,8 @@ shared_sources = files(''' - macvlan-util.c - macvlan-util.h - main-func.h -+ mkfs-util.c -+ mkfs-util.h - module-util.h - mount-util.c - mount-util.h -@@ -191,6 +189,8 @@ shared_sources = files(''' - pretty-print.h - ptyfwd.c - ptyfwd.h -+ pwquality-util.c -+ pwquality-util.h - reboot-util.c - reboot-util.h - resize-fs.c -@@ -262,6 +262,16 @@ endif - test_tables_h = files('test-tables.h') - shared_sources += test_tables_h - -+generate_syscall_list = find_program('generate-syscall-list.py') -+fname = 'syscall-list.h' -+syscall_list_h = custom_target( -+ fname, -+ input : 'syscall-names.text', -+ output : fname, -+ command : [generate_syscall_list, -+ '@INPUT@'], -+ capture : true) -+ - if conf.get('HAVE_ACL') == 1 - shared_sources += files('acl-util.c') - endif -@@ -272,6 +282,7 @@ endif - - if conf.get('HAVE_SECCOMP') == 1 - shared_sources += files('seccomp-util.c') -+ shared_sources += syscall_list_h - endif - - if conf.get('HAVE_LIBIPTC') == 1 -@@ -289,6 +300,13 @@ if conf.get('HAVE_PAM') == 1 - '''.split()) - endif - -+if conf.get('HAVE_QRENCODE') == 1 -+ shared_sources += files(''' -+ qrcode-util.c -+ qrcode-util.h -+'''.split()) -+endif -+ - generate_ip_protocol_list = find_program('generate-ip-protocol-list.sh') - ip_protocol_list_txt = custom_target( - 'ip-protocol-list.txt', -@@ -336,7 +354,6 @@ libshared_deps = [threads, - libblkid, - libcap, - libcrypt, -- libcryptsetup, - libgcrypt, - libidn, - libiptc, -@@ -376,3 +393,9 @@ libshared = shared_library( - dependencies : libshared_deps, - install : true, - install_dir : rootlibexecdir) -+ -+############################################################ -+ -+run_target( -+ 'syscall-names-update', -+ command : [syscall_names_update_sh, meson.current_source_dir()]) -diff --git a/src/shared/mkfs-util.c b/src/shared/mkfs-util.c -new file mode 100644 -index 0000000..583ef90 ---- /dev/null -+++ b/src/shared/mkfs-util.c -@@ -0,0 +1,135 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include "id128-util.h" -+#include "mkfs-util.h" -+#include "path-util.h" -+#include "process-util.h" -+#include "stdio-util.h" -+#include "string-util.h" -+ -+int mkfs_exists(const char *fstype) { -+ const char *mkfs; -+ int r; -+ -+ assert(fstype); -+ -+ if (STR_IN_SET(fstype, "auto", "swap")) /* these aren't real file system types, refuse early */ -+ return -EINVAL; -+ -+ mkfs = strjoina("mkfs.", fstype); -+ if (!filename_is_valid(mkfs)) /* refuse file system types with slashes and similar */ -+ return -EINVAL; -+ -+ r = find_binary(mkfs, NULL); -+ if (r == -ENOENT) -+ return false; -+ if (r < 0) -+ return r; -+ -+ return true; -+} -+ -+int make_filesystem( -+ const char *node, -+ const char *fstype, -+ const char *label, -+ sd_id128_t uuid, -+ bool discard) { -+ -+ _cleanup_free_ char *mkfs = NULL; -+ int r; -+ -+ assert(node); -+ assert(fstype); -+ assert(label); -+ -+ if (streq(fstype, "swap")) { -+ r = find_binary("mkswap", &mkfs); -+ if (r == -ENOENT) -+ return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "mkswap binary not available."); -+ if (r < 0) -+ return log_error_errno(r, "Failed to determine whether mkswap binary exists: %m"); -+ } else { -+ r = mkfs_exists(fstype); -+ if (r < 0) -+ return log_error_errno(r, "Failed to determine whether mkfs binary for %s exists: %m", fstype); -+ if (r == 0) -+ return log_error_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT), "mkfs binary for %s is not available.", fstype); -+ -+ mkfs = strjoin("mkfs.", fstype); -+ if (!mkfs) -+ return log_oom(); -+ } -+ -+ r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL); -+ if (r < 0) -+ return r; -+ if (r == 0) { -+ char suuid[ID128_UUID_STRING_MAX]; -+ -+ /* Child */ -+ id128_to_uuid_string(uuid, suuid); -+ -+ if (streq(fstype, "ext4")) -+ (void) execlp(mkfs, mkfs, -+ "-L", label, -+ "-U", suuid, -+ "-I", "256", -+ "-O", "has_journal", -+ "-m", "0", -+ "-E", discard ? "lazy_itable_init=1,discard" : "lazy_itable_init=1,nodiscard", -+ node, NULL); -+ -+ else if (streq(fstype, "btrfs")) { -+ if (discard) -+ (void) execlp(mkfs, mkfs, "-L", label, "-U", suuid, node, NULL); -+ else -+ (void) execlp(mkfs, mkfs, "-L", label, "-U", suuid, "--nodiscard", node, NULL); -+ -+ } else if (streq(fstype, "xfs")) { -+ const char *j; -+ -+ j = strjoina("uuid=", suuid); -+ if (discard) -+ (void) execlp(mkfs, mkfs, "-L", label, "-m", j, "-m", "reflink=1", node, NULL); -+ else -+ (void) execlp(mkfs, mkfs, "-L", label, "-m", j, "-m", "reflink=1", "-K", node, NULL); -+ -+ } else if (streq(fstype, "vfat")) { -+ char mangled_label[8 + 3 + 1], vol_id[8 + 1]; -+ -+ /* Classic FAT only allows 11 character uppercase labels */ -+ strncpy(mangled_label, label, sizeof(mangled_label)-1); -+ mangled_label[sizeof(mangled_label)-1] = 0; -+ ascii_strupper(mangled_label); -+ -+ xsprintf(vol_id, "%08" PRIx32, -+ ((uint32_t) uuid.bytes[0] << 24) | -+ ((uint32_t) uuid.bytes[1] << 16) | -+ ((uint32_t) uuid.bytes[2] << 8) | -+ ((uint32_t) uuid.bytes[3])); /* Take first 32 byte of UUID */ -+ -+ (void) execlp(mkfs, mkfs, -+ "-i", vol_id, -+ "-n", mangled_label, -+ "-F", "32", /* yes, we force FAT32 here */ -+ node, NULL); -+ -+ } else if (streq(fstype, "swap")) { -+ -+ (void) execlp(mkfs, mkfs, -+ "-L", label, -+ "-U", suuid, -+ node, NULL); -+ -+ } else -+ /* Generic fallback for all other file systems */ -+ (void) execlp(mkfs, mkfs, node, NULL); -+ -+ log_error_errno(errno, "Failed to execute %s: %m", mkfs); -+ -+ _exit(EXIT_FAILURE); -+ } -+ -+ return 0; -+} -diff --git a/src/shared/mkfs-util.h b/src/shared/mkfs-util.h -new file mode 100644 -index 0000000..54e9b93 ---- /dev/null -+++ b/src/shared/mkfs-util.h -@@ -0,0 +1,10 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#include -+ -+#include "sd-id128.h" -+ -+int mkfs_exists(const char *fstype); -+ -+int make_filesystem(const char *node, const char *fstype, const char *label, sd_id128_t uuid, bool discard); -diff --git a/src/shared/module-util.c b/src/shared/module-util.c -index 3e64d42..e1d394c 100644 ---- a/src/shared/module-util.c -+++ b/src/shared/module-util.c -@@ -8,7 +8,7 @@ int module_load_and_warn(struct kmod_ctx *ctx, const char *module, bool verbose) - const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST; - struct kmod_list *itr; - _cleanup_(kmod_module_unref_listp) struct kmod_list *modlist = NULL; -- int r = 0; -+ int r; - - /* verbose==true means we should log at non-debug level if we - * fail to find or load the module. */ -diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c -index b3fac13..4d40acf 100644 ---- a/src/shared/mount-util.c -+++ b/src/shared/mount-util.c -@@ -414,7 +414,6 @@ int mode_to_inaccessible_node( - - _cleanup_free_ char *d = NULL; - const char *node = NULL; -- bool fallback = false; - - assert(ret); - -@@ -432,12 +431,10 @@ int mode_to_inaccessible_node( - - case S_IFCHR: - node = "/systemd/inaccessible/chr"; -- fallback = true; - break; - - case S_IFBLK: - node = "/systemd/inaccessible/blk"; -- fallback = true; - break; - - case S_IFIFO: -@@ -455,7 +452,24 @@ int mode_to_inaccessible_node( - if (!d) - return -ENOMEM; - -- if (fallback && access(d, F_OK) < 0) { -+ /* On new kernels unprivileged users are permitted to create 0:0 char device nodes (because they also -+ * act as whiteout inode for overlayfs), but no other char or block device nodes. On old kernels no -+ * device node whatsoever may be created by unprivileged processes. Hence, if the caller asks for the -+ * inaccessible block device node let's see if the block device node actually exists, and if not, -+ * fall back to the character device node. From there fall back to the socket device node. This means -+ * in the best case we'll get the right device node type — but if not we'll hopefully at least get a -+ * device node at all. */ -+ -+ if (S_ISBLK(mode) && -+ access(d, F_OK) < 0 && errno == ENOENT) { -+ free(d); -+ d = path_join(runtime_dir, "/systemd/inaccessible/chr"); -+ if (!d) -+ return -ENOMEM; -+ } -+ -+ if (IN_SET(mode & S_IFMT, S_IFBLK, S_IFCHR) && -+ access(d, F_OK) < 0 && errno == ENOENT) { - free(d); - d = path_join(runtime_dir, "/systemd/inaccessible/sock"); - if (!d) -diff --git a/src/shared/numa-util.c b/src/shared/numa-util.c -index 187992d..3ec8ffc 100644 ---- a/src/shared/numa-util.c -+++ b/src/shared/numa-util.c -@@ -5,6 +5,8 @@ - - #include "alloc-util.h" - #include "cpu-set-util.h" -+#include "dirent-util.h" -+#include "fd-util.h" - #include "fileio.h" - #include "macro.h" - #include "missing_syscall.h" -@@ -124,6 +126,61 @@ int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret) { - return 0; - } - -+static int numa_max_node(void) { -+ _cleanup_closedir_ DIR *d = NULL; -+ struct dirent *de; -+ int r, max_node = 0; -+ -+ d = opendir("/sys/devices/system/node"); -+ if (!d) -+ return -errno; -+ -+ FOREACH_DIRENT(de, d, break) { -+ int node; -+ const char *n; -+ -+ (void) dirent_ensure_type(d, de); -+ -+ if (de->d_type != DT_DIR) -+ continue; -+ -+ n = startswith(de->d_name, "node"); -+ if (!n) -+ continue; -+ -+ r = safe_atoi(n, &node); -+ if (r < 0) -+ continue; -+ -+ if (node > max_node) -+ max_node = node; -+ } -+ -+ return max_node; -+} -+ -+int numa_mask_add_all(CPUSet *mask) { -+ int m; -+ -+ assert(mask); -+ -+ m = numa_max_node(); -+ if (m < 0) { -+ log_debug_errno(m, "Failed to determine maximum NUMA node index, assuming 1023: %m"); -+ m = 1023; /* CONFIG_NODES_SHIFT is set to 10 on x86_64, i.e. 1024 NUMA nodes in total */ -+ } -+ -+ for (int i = 0; i <= m; i++) { -+ int r; -+ -+ r = cpu_set_add(mask, i); -+ if (r < 0) -+ return r; -+ } -+ -+ return 0; -+} -+ - static const char* const mpol_table[] = { - [MPOL_DEFAULT] = "default", - [MPOL_PREFERRED] = "preferred", -diff --git a/src/shared/numa-util.h b/src/shared/numa-util.h -index c991789..2a9ced7 100644 ---- a/src/shared/numa-util.h -+++ b/src/shared/numa-util.h -@@ -29,5 +29,7 @@ static inline void numa_policy_reset(NUMAPolicy *p) { - int apply_numa_policy(const NUMAPolicy *policy); - int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *set); - -+int numa_mask_add_all(CPUSet *mask); -+ - const char* mpol_to_string(int i) _const_; - int mpol_from_string(const char *s) _pure_; -diff --git a/src/shared/offline-passwd.c b/src/shared/offline-passwd.c -index 26a1b9c..2d14a38 100644 ---- a/src/shared/offline-passwd.c -+++ b/src/shared/offline-passwd.c -@@ -36,7 +36,7 @@ static int populate_uid_cache(const char *root, Hashmap **ret) { - if (!cache) - return -ENOMEM; - -- /* The directory list is harcoded here: /etc is the standard, and rpm-ostree uses /usr/lib. This -+ /* The directory list is hardcoded here: /etc is the standard, and rpm-ostree uses /usr/lib. This - * could be made configurable, but I don't see the point right now. */ - - const char *fname; -diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c -index 632964d..4088439 100644 ---- a/src/shared/pkcs11-util.c -+++ b/src/shared/pkcs11-util.c -@@ -212,13 +212,15 @@ int pkcs11_token_login( - "Failed to log into security token '%s': %s", token_label, p11_kit_strerror(rv)); - - log_info("Successfully logged into security token '%s' via protected authentication path.", token_label); -- *ret_used_pin = NULL; -+ if (ret_used_pin) -+ *ret_used_pin = NULL; - return 0; - } - - if (!FLAGS_SET(token_info->flags, CKF_LOGIN_REQUIRED)) { - log_info("No login into security token '%s' required.", token_label); -- *ret_used_pin = NULL; -+ if (ret_used_pin) -+ *ret_used_pin = NULL; - return 0; - } - -diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c -index 69bae68..edba239 100644 ---- a/src/shared/pretty-print.c -+++ b/src/shared/pretty-print.c -@@ -234,6 +234,12 @@ static int guess_type(const char **name, char ***prefixes, bool *is_collection, - if (!n) - return log_oom(); - -+ /* All systemd-style config files should support the /usr-/etc-/run split and -+ * dropins. Let's add a blanket rule that allows us to support them without keeping -+ * an explicit list. */ -+ if (path_startswith(n, "systemd") && endswith(n, ".conf")) -+ usr = true; -+ - delete_trailing_chars(n, "/"); - - if (endswith(n, ".d")) -diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c -index fe17b37..6d67c07 100644 ---- a/src/shared/ptyfwd.c -+++ b/src/shared/ptyfwd.c -@@ -572,9 +572,11 @@ int pty_forward_set_priority(PTYForward *f, int64_t priority) { - int r; - assert(f); - -- r = sd_event_source_set_priority(f->stdin_event_source, priority); -- if (r < 0) -- return r; -+ if (f->stdin_event_source) { -+ r = sd_event_source_set_priority(f->stdin_event_source, priority); -+ if (r < 0) -+ return r; -+ } - - r = sd_event_source_set_priority(f->stdout_event_source, priority); - if (r < 0) -diff --git a/src/shared/pwquality-util.c b/src/shared/pwquality-util.c -new file mode 100644 -index 0000000..6733283 ---- /dev/null -+++ b/src/shared/pwquality-util.c -@@ -0,0 +1,191 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include -+ -+#include "dlfcn-util.h" -+#include "errno-util.h" -+#include "log.h" -+#include "macro.h" -+#include "memory-util.h" -+#include "pwquality-util.h" -+#include "strv.h" -+ -+#if HAVE_PWQUALITY -+ -+static void *pwquality_dl = NULL; -+ -+int (*sym_pwquality_check)(pwquality_settings_t *pwq, const char *password, const char *oldpassword, const char *user, void **auxerror); -+pwquality_settings_t *(*sym_pwquality_default_settings)(void); -+void (*sym_pwquality_free_settings)(pwquality_settings_t *pwq); -+int (*sym_pwquality_generate)(pwquality_settings_t *pwq, int entropy_bits, char **password); -+int (*sym_pwquality_get_str_value)(pwquality_settings_t *pwq, int setting, const char **value); -+int (*sym_pwquality_read_config)(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror); -+int (*sym_pwquality_set_int_value)(pwquality_settings_t *pwq, int setting, int value); -+const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror); -+ -+int dlopen_pwquality(void) { -+ _cleanup_(dlclosep) void *dl = NULL; -+ int r; -+ -+ if (pwquality_dl) -+ return 0; /* Already loaded */ -+ -+ dl = dlopen("libpwquality.so.1", RTLD_LAZY); -+ if (!dl) -+ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), -+ "libpwquality support is not installed: %s", dlerror()); -+ -+ r = dlsym_many_and_warn( -+ dl, -+ LOG_DEBUG, -+ &sym_pwquality_check, "pwquality_check", -+ &sym_pwquality_default_settings, "pwquality_default_settings", -+ &sym_pwquality_free_settings, "pwquality_free_settings", -+ &sym_pwquality_generate, "pwquality_generate", -+ &sym_pwquality_get_str_value, "pwquality_get_str_value", -+ &sym_pwquality_read_config, "pwquality_read_config", -+ &sym_pwquality_set_int_value, "pwquality_set_int_value", -+ &sym_pwquality_strerror, "pwquality_strerror", -+ NULL); -+ if (r < 0) -+ return r; -+ -+ /* Note that we never release the reference here, because there's no real reason to, after all this -+ * was traditionally a regular shared library dependency which lives forever too. */ -+ pwquality_dl = TAKE_PTR(dl); -+ return 1; -+} -+ -+void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq) { -+ char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; -+ const char *path; -+ int r; -+ -+ assert(pwq); -+ -+ r = sym_pwquality_get_str_value(pwq, PWQ_SETTING_DICT_PATH, &path); -+ if (r < 0) { -+ log_debug("Failed to read libpwquality dictionary path, ignoring: %s", -+ sym_pwquality_strerror(buf, sizeof(buf), r, NULL)); -+ return; -+ } -+ -+ // REMOVE THIS AS SOON AS https://github.com/libpwquality/libpwquality/pull/21 IS MERGED AND RELEASED -+ if (isempty(path)) -+ path = "/usr/share/cracklib/pw_dict.pwd.gz"; -+ -+ if (isempty(path)) { -+ log_debug("Weird, no dictionary file configured, ignoring."); -+ return; -+ } -+ -+ if (access(path, F_OK) >= 0) -+ return; -+ -+ if (errno != ENOENT) { -+ log_debug_errno(errno, "Failed to check if dictionary file %s exists, ignoring: %m", path); -+ return; -+ } -+ -+ r = sym_pwquality_set_int_value(pwq, PWQ_SETTING_DICT_CHECK, 0); -+ if (r < 0) -+ log_debug("Failed to disable libpwquality dictionary check, ignoring: %s", -+ sym_pwquality_strerror(buf, sizeof(buf), r, NULL)); -+} -+ -+int pwq_allocate_context(pwquality_settings_t **ret) { -+ _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL; -+ char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; -+ void *auxerror; -+ int r; -+ -+ assert(ret); -+ -+ r = dlopen_pwquality(); -+ if (r < 0) -+ return r; -+ -+ pwq = sym_pwquality_default_settings(); -+ if (!pwq) -+ return -ENOMEM; -+ -+ r = sym_pwquality_read_config(pwq, NULL, &auxerror); -+ if (r < 0) -+ log_debug("Failed to read libpwquality configuration, ignoring: %s", -+ sym_pwquality_strerror(buf, sizeof(buf), r, auxerror)); -+ -+ pwq_maybe_disable_dictionary(pwq); -+ -+ *ret = TAKE_PTR(pwq); -+ return 0; -+} -+ -+#define N_SUGGESTIONS 6 -+ -+int suggest_passwords(void) { -+ _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL; -+ _cleanup_strv_free_erase_ char **suggestions = NULL; -+ _cleanup_(erase_and_freep) char *joined = NULL; -+ char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; -+ size_t i; -+ int r; -+ -+ r = pwq_allocate_context(&pwq); -+ if (ERRNO_IS_NOT_SUPPORTED(r)) -+ return 0; -+ if (r < 0) -+ return log_error_errno(r, "Failed to allocate libpwquality context: %m"); -+ -+ suggestions = new0(char*, N_SUGGESTIONS+1); -+ if (!suggestions) -+ return log_oom(); -+ -+ for (i = 0; i < N_SUGGESTIONS; i++) { -+ r = sym_pwquality_generate(pwq, 64, suggestions + i); -+ if (r < 0) -+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate password, ignoring: %s", -+ sym_pwquality_strerror(buf, sizeof(buf), r, NULL)); -+ } -+ -+ joined = strv_join(suggestions, " "); -+ if (!joined) -+ return log_oom(); -+ -+ log_info("Password suggestions: %s", joined); -+ return 1; -+} -+ -+int quality_check_password(const char *password, const char *username, char **ret_error) { -+ _cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL; -+ char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; -+ void *auxerror; -+ int r; -+ -+ assert(password); -+ -+ r = pwq_allocate_context(&pwq); -+ if (ERRNO_IS_NOT_SUPPORTED(r)) -+ return 0; -+ if (r < 0) -+ return log_debug_errno(r, "Failed to allocate libpwquality context: %m"); -+ -+ r = sym_pwquality_check(pwq, password, NULL, username, &auxerror); -+ if (r < 0) { -+ -+ if (ret_error) { -+ _cleanup_free_ char *e = NULL; -+ -+ e = strdup(sym_pwquality_strerror(buf, sizeof(buf), r, auxerror)); -+ if (!e) -+ return -ENOMEM; -+ -+ *ret_error = TAKE_PTR(e); -+ } -+ -+ return 0; /* all bad */ -+ } -+ -+ return 1; /* all good */ -+} -+ -+#endif -diff --git a/src/shared/pwquality-util.h b/src/shared/pwquality-util.h -new file mode 100644 -index 0000000..a49de07 ---- /dev/null -+++ b/src/shared/pwquality-util.h -@@ -0,0 +1,41 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#include "macro.h" -+ -+#if HAVE_PWQUALITY -+/* pwquality.h uses size_t but doesn't include sys/types.h on its own */ -+#include -+#include -+ -+extern int (*sym_pwquality_check)(pwquality_settings_t *pwq, const char *password, const char *oldpassword, const char *user, void **auxerror); -+extern pwquality_settings_t *(*sym_pwquality_default_settings)(void); -+extern void (*sym_pwquality_free_settings)(pwquality_settings_t *pwq); -+extern int (*sym_pwquality_generate)(pwquality_settings_t *pwq, int entropy_bits, char **password); -+extern int (*sym_pwquality_get_str_value)(pwquality_settings_t *pwq, int setting, const char **value); -+extern int (*sym_pwquality_read_config)(pwquality_settings_t *pwq, const char *cfgfile, void **auxerror); -+extern int (*sym_pwquality_set_int_value)(pwquality_settings_t *pwq, int setting, int value); -+extern const char* (*sym_pwquality_strerror)(char *buf, size_t len, int errcode, void *auxerror); -+ -+int dlopen_pwquality(void); -+ -+DEFINE_TRIVIAL_CLEANUP_FUNC(pwquality_settings_t*, sym_pwquality_free_settings); -+ -+void pwq_maybe_disable_dictionary(pwquality_settings_t *pwq); -+int pwq_allocate_context(pwquality_settings_t **ret); -+int suggest_passwords(void); -+int quality_check_password(const char *password, const char *username, char **ret_error); -+ -+#else -+ -+static inline int suggest_passwords(void) { -+ return 0; -+} -+ -+static inline int quality_check_password(const char *password, const char *username, char **ret_error) { -+ if (ret_error) -+ *ret_error = NULL; -+ return 1; /* all good */ -+} -+ -+#endif -diff --git a/src/shared/qrcode-util.c b/src/shared/qrcode-util.c -new file mode 100644 -index 0000000..a545daa ---- /dev/null -+++ b/src/shared/qrcode-util.c -@@ -0,0 +1,63 @@ -+#include "qrcode-util.h" -+#include "terminal-util.h" -+ -+#define ANSI_WHITE_ON_BLACK "\033[40;37;1m" -+ -+static void print_border(FILE *output, unsigned width) { -+ unsigned x, y; -+ -+ /* Four rows of border */ -+ for (y = 0; y < 4; y += 2) { -+ fputs(ANSI_WHITE_ON_BLACK, output); -+ -+ for (x = 0; x < 4 + width + 4; x++) -+ fputs("\342\226\210", output); -+ -+ fputs(ANSI_NORMAL "\n", output); -+ } -+} -+ -+void write_qrcode(FILE *output, QRcode *qr) { -+ unsigned x, y; -+ -+ assert(qr); -+ -+ if (!output) -+ output = stdout; -+ -+ print_border(output, qr->width); -+ -+ for (y = 0; y < (unsigned) qr->width; y += 2) { -+ const uint8_t *row1, *row2; -+ -+ row1 = qr->data + qr->width * y; -+ row2 = row1 + qr->width; -+ -+ fputs(ANSI_WHITE_ON_BLACK, output); -+ for (x = 0; x < 4; x++) -+ fputs("\342\226\210", output); -+ -+ for (x = 0; x < (unsigned) qr->width; x ++) { -+ bool a, b; -+ -+ a = row1[x] & 1; -+ b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false; -+ -+ if (a && b) -+ fputc(' ', output); -+ else if (a) -+ fputs("\342\226\204", output); -+ else if (b) -+ fputs("\342\226\200", output); -+ else -+ fputs("\342\226\210", output); -+ } -+ -+ for (x = 0; x < 4; x++) -+ fputs("\342\226\210", output); -+ fputs(ANSI_NORMAL "\n", output); -+ } -+ -+ print_border(output, qr->width); -+ fflush(output); -+} -diff --git a/src/shared/qrcode-util.h b/src/shared/qrcode-util.h -new file mode 100644 -index 0000000..9a21ffd ---- /dev/null -+++ b/src/shared/qrcode-util.h -@@ -0,0 +1,9 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+#pragma once -+ -+#if HAVE_QRENCODE -+#include -+#include -+ -+void write_qrcode(FILE *output, QRcode *qr); -+#endif -diff --git a/src/shared/reboot-util.h b/src/shared/reboot-util.h -index 5aeb348..1e98ee1 100644 ---- a/src/shared/reboot-util.h -+++ b/src/shared/reboot-util.h -@@ -6,7 +6,7 @@ int update_reboot_parameter_and_warn(const char *parameter, bool keep); - typedef enum RebootFlags { - REBOOT_LOG = 1 << 0, /* log about what we are going to do and all errors */ - REBOOT_DRY_RUN = 1 << 1, /* return 0 right before actually doing the reboot */ -- REBOOT_FALLBACK = 1 << 2, /* fallback to plain reboot() if argument-based reboot doesn't work, isn't configured or doesn't apply otherwise */ -+ REBOOT_FALLBACK = 1 << 2, /* fall back to plain reboot() if argument-based reboot doesn't work, isn't configured or doesn't apply otherwise */ - } RebootFlags; - - int read_reboot_parameter(char **parameter); -diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h -index 0524f1a..a7a9c77 100644 ---- a/src/shared/resolve-util.h -+++ b/src/shared/resolve-util.h -@@ -53,7 +53,7 @@ enum DnsOverTlsMode { - DNS_OVER_TLS_NO, - - /* Try to connect using DNS-over-TLS, but if connection fails, -- * fallback to using an unencrypted connection */ -+ * fall back to using an unencrypted connection */ - DNS_OVER_TLS_OPPORTUNISTIC, - - /* Enforce DNS-over-TLS and require valid server certificates */ -diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c -index a8dd069..358960d 100644 ---- a/src/shared/seccomp-util.c -+++ b/src/shared/seccomp-util.c -@@ -12,6 +12,7 @@ - - #include "af-list.h" - #include "alloc-util.h" -+#include "env-util.h" - #include "errno-list.h" - #include "macro.h" - #include "nsflags.h" -@@ -85,6 +86,8 @@ const uint32_t seccomp_local_archs[] = { - SCMP_ARCH_PPC64LE, /* native */ - #elif defined(__powerpc__) - SCMP_ARCH_PPC, -+#elif defined(__riscv) && __riscv_xlen == 64 && defined(SCMP_ARCH_RISCV64) -+ SCMP_ARCH_RISCV64, - #elif defined(__s390x__) - SCMP_ARCH_S390, - SCMP_ARCH_S390X, /* native */ -@@ -131,6 +134,10 @@ const char* seccomp_arch_to_string(uint32_t c) { - return "ppc64"; - case SCMP_ARCH_PPC64LE: - return "ppc64-le"; -+#ifdef SCMP_ARCH_RISCV64 -+ case SCMP_ARCH_RISCV64: -+ return "riscv64"; -+#endif - case SCMP_ARCH_S390: - return "s390"; - case SCMP_ARCH_S390X: -@@ -176,6 +183,10 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret) { - *ret = SCMP_ARCH_PPC64; - else if (streq(n, "ppc64-le")) - *ret = SCMP_ARCH_PPC64LE; -+#ifdef SCMP_ARCH_RISCV64 -+ else if (streq(n, "riscv64")) -+ *ret = SCMP_ARCH_RISCV64; -+#endif - else if (streq(n, "s390")) - *ret = SCMP_ARCH_S390; - else if (streq(n, "s390x")) -@@ -187,7 +198,7 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret) { - } - - int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_action) { -- scmp_filter_ctx seccomp; -+ _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; - int r; - - /* Much like seccomp_init(), but initializes the filter for one specific architecture only, without affecting -@@ -202,11 +213,11 @@ int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_ - - r = seccomp_arch_remove(seccomp, seccomp_arch_native()); - if (r < 0) -- goto finish; -+ return r; - - r = seccomp_arch_add(seccomp, arch); - if (r < 0) -- goto finish; -+ return r; - - assert(seccomp_arch_exist(seccomp, arch) >= 0); - assert(seccomp_arch_exist(seccomp, SCMP_ARCH_NATIVE) == -EEXIST); -@@ -218,18 +229,22 @@ int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_ - - r = seccomp_attr_set(seccomp, SCMP_FLTATR_ACT_BADARCH, SCMP_ACT_ALLOW); - if (r < 0) -- goto finish; -+ return r; - - r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); - if (r < 0) -- goto finish; -+ return r; - -- *ret = seccomp; -- return 0; -+#if SCMP_VER_MAJOR >= 3 || (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 4) -+ if (getenv_bool("SYSTEMD_LOG_SECCOMP") > 0) { -+ r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_LOG, 1); -+ if (r < 0) -+ log_debug_errno(r, "Failed to enable seccomp event logging: %m"); -+ } -+#endif - --finish: -- seccomp_release(seccomp); -- return r; -+ *ret = TAKE_PTR(seccomp); -+ return 0; - } - - static bool is_basic_seccomp_available(void) { -@@ -387,7 +402,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { - "pidfd_getfd\0" - "ptrace\0" - "rtas\0" --#ifdef __NR_s390_runtime_instr -+#if defined __s390__ || defined __s390x__ - "s390_runtime_instr\0" - #endif - "sys_debug_setcontext\0" -@@ -402,6 +417,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { - "close\0" - "creat\0" - "faccessat\0" -+ "faccessat2\0" - "fallocate\0" - "fchdir\0" - "fchmod\0" -@@ -463,9 +479,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { - "stat64\0" - "statfs\0" - "statfs64\0" --#ifdef __NR_statx - "statx\0" --#endif - "symlink\0" - "symlinkat\0" - "truncate\0" -@@ -711,10 +725,8 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { - "pciconfig_iobase\0" - "pciconfig_read\0" - "pciconfig_write\0" --#ifdef __NR_s390_pci_mmio_read -+#if defined __s390__ || defined __s390x__ - "s390_pci_mmio_read\0" --#endif --#ifdef __NR_s390_pci_mmio_write - "s390_pci_mmio_write\0" - #endif - }, -@@ -890,30 +902,50 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { - "timerfd_settime64\0" - "times\0" - }, -+ [SYSCALL_FILTER_SET_KNOWN] = { -+ .name = "@known", -+ .help = "All known syscalls declared in the kernel", -+ .value = -+#include "syscall-list.h" -+ }, - }; - - const SyscallFilterSet *syscall_filter_set_find(const char *name) { -- unsigned i; -- - if (isempty(name) || name[0] != '@') - return NULL; - -- for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) -+ for (unsigned i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) - if (streq(syscall_filter_sets[i].name, name)) - return syscall_filter_sets + i; - - return NULL; - } - --static int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action, char **exclude, bool log_missing); -+static int add_syscall_filter_set( -+ scmp_filter_ctx seccomp, -+ const SyscallFilterSet *set, -+ uint32_t action, -+ char **exclude, -+ bool log_missing, -+ char ***added); -+ -+int seccomp_add_syscall_filter_item( -+ scmp_filter_ctx *seccomp, -+ const char *name, -+ uint32_t action, -+ char **exclude, -+ bool log_missing, -+ char ***added) { - --int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, uint32_t action, char **exclude, bool log_missing) { - assert(seccomp); - assert(name); - - if (strv_contains(exclude, name)) - return 0; - -+ /* Any syscalls that are handled are added to the *added strv. The pointer -+ * must be either NULL or point to a valid pre-initialized possibly-empty strv. */ -+ - if (name[0] == '@') { - const SyscallFilterSet *other; - -@@ -923,7 +955,7 @@ int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, - "Filter set %s is not known!", - name); - -- return seccomp_add_syscall_filter_set(seccomp, other, action, exclude, log_missing); -+ return add_syscall_filter_set(seccomp, other, action, exclude, log_missing, added); - - } else { - int id, r; -@@ -947,25 +979,34 @@ int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, - return r; - } - -+ if (added) { -+ r = strv_extend(added, name); -+ if (r < 0) -+ return r; -+ } -+ - return 0; - } - } - --static int seccomp_add_syscall_filter_set( -+static int add_syscall_filter_set( - scmp_filter_ctx seccomp, - const SyscallFilterSet *set, - uint32_t action, - char **exclude, -- bool log_missing) { -+ bool log_missing, -+ char ***added) { - - const char *sys; - int r; - -+ /* Any syscalls that are handled are added to the *added strv. It needs to be initialized. */ -+ - assert(seccomp); - assert(set); - - NULSTR_FOREACH(sys, set->value) { -- r = seccomp_add_syscall_filter_item(seccomp, sys, action, exclude, log_missing); -+ r = seccomp_add_syscall_filter_item(seccomp, sys, action, exclude, log_missing, added); - if (r < 0) - return r; - } -@@ -991,7 +1032,7 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter - if (r < 0) - return r; - -- r = seccomp_add_syscall_filter_set(seccomp, set, action, NULL, log_missing); -+ r = add_syscall_filter_set(seccomp, set, action, NULL, log_missing, NULL); - if (r < 0) - return log_debug_errno(r, "Failed to add filter set: %m"); - -@@ -1017,7 +1058,6 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u - - SECCOMP_FOREACH_LOCAL_ARCH(arch) { - _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; -- Iterator i; - void *syscall_id, *val; - - log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); -@@ -1026,12 +1066,18 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u - if (r < 0) - return r; - -- HASHMAP_FOREACH_KEY(val, syscall_id, set, i) { -+ HASHMAP_FOREACH_KEY(val, syscall_id, set) { - uint32_t a = action; - int id = PTR_TO_INT(syscall_id) - 1; - int error = PTR_TO_INT(val); - -- if (action != SCMP_ACT_ALLOW && error >= 0) -+ if (error == SECCOMP_ERROR_NUMBER_KILL) -+ a = scmp_act_kill_process(); -+#ifdef SCMP_ACT_LOG -+ else if (action == SCMP_ACT_LOG) -+ a = SCMP_ACT_LOG; -+#endif -+ else if (action != SCMP_ACT_ALLOW && error >= 0) - a = SCMP_ACT_ERRNO(error); - - r = seccomp_rule_add_exact(seccomp, a, id, 0); -@@ -1148,7 +1194,6 @@ int seccomp_restrict_namespaces(unsigned long retain) { - - SECCOMP_FOREACH_LOCAL_ARCH(arch) { - _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; -- unsigned i; - - log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); - -@@ -1178,7 +1223,7 @@ int seccomp_restrict_namespaces(unsigned long retain) { - continue; - } - -- for (i = 0; namespace_flag_map[i].name; i++) { -+ for (unsigned i = 0; namespace_flag_map[i].name; i++) { - unsigned long f; - - f = namespace_flag_map[i].flag; -@@ -1255,7 +1300,13 @@ int seccomp_protect_sysctl(void) { - - log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); - -- if (IN_SET(arch, SCMP_ARCH_X32, SCMP_ARCH_AARCH64)) -+ if (IN_SET(arch, -+ SCMP_ARCH_AARCH64, -+#ifdef SCMP_ARCH_RISCV64 -+ SCMP_ARCH_RISCV64, -+#endif -+ SCMP_ARCH_X32 -+ )) - /* No _sysctl syscall */ - continue; - -@@ -1322,7 +1373,6 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) { - SECCOMP_FOREACH_LOCAL_ARCH(arch) { - _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; - bool supported; -- Iterator i; - - log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); - -@@ -1339,6 +1389,9 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) { - case SCMP_ARCH_MIPS64N32: - case SCMP_ARCH_MIPSEL64: - case SCMP_ARCH_MIPS64: -+#ifdef SCMP_ARCH_RISCV64 -+ case SCMP_ARCH_RISCV64: -+#endif - /* These we know we support (i.e. are the ones that do not use socketcall()) */ - supported = true; - break; -@@ -1363,15 +1416,15 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) { - return r; - - if (allow_list) { -- int af, first = 0, last = 0; -+ int first = 0, last = 0; - void *afp; - - /* If this is an allow list, we first block the address families that are out of - * range and then everything that is not in the set. First, we find the lowest and - * highest address family in the set. */ - -- SET_FOREACH(afp, address_families, i) { -- af = PTR_TO_INT(afp); -+ SET_FOREACH(afp, address_families) { -+ int af = PTR_TO_INT(afp); - - if (af <= 0 || af >= af_max()) - continue; -@@ -1425,7 +1478,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) { - } - - /* Block everything between the first and last entry */ -- for (af = 1; af < af_max(); af++) { -+ for (int af = 1; af < af_max(); af++) { - - if (set_contains(address_families, INT_TO_PTR(af))) - continue; -@@ -1451,8 +1504,7 @@ int seccomp_restrict_address_families(Set *address_families, bool allow_list) { - /* If this is a deny list, then generate one rule for each address family that are - * then combined in OR checks. */ - -- SET_FOREACH(af, address_families, i) { -- -+ SET_FOREACH(af, address_families) { - r = seccomp_rule_add_exact( - seccomp, - SCMP_ACT_ERRNO(EAFNOSUPPORT), -@@ -1576,7 +1628,7 @@ static int add_seccomp_syscall_filter(scmp_filter_ctx seccomp, - } - - /* For known architectures, check that syscalls are indeed defined or not. */ --#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) -+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64) - assert_cc(SCMP_SYS(shmget) > 0); - assert_cc(SCMP_SYS(shmat) > 0); - assert_cc(SCMP_SYS(shmdt) > 0); -@@ -1621,13 +1673,16 @@ int seccomp_memory_deny_write_execute(void) { - case SCMP_ARCH_X86_64: - case SCMP_ARCH_X32: - case SCMP_ARCH_AARCH64: -- filter_syscall = SCMP_SYS(mmap); /* amd64, x32 and arm64 have only mmap */ -+#ifdef SCMP_ARCH_RISCV64 -+ case SCMP_ARCH_RISCV64: -+#endif -+ filter_syscall = SCMP_SYS(mmap); /* amd64, x32, arm64 and riscv64 have only mmap */ - shmat_syscall = SCMP_SYS(shmat); - break; - - /* Please add more definitions here, if you port systemd to other architectures! */ - --#if !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__) && !defined(__powerpc64__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__s390__) && !defined(__s390x__) -+#if !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__) && !defined(__powerpc64__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__s390__) && !defined(__s390x__) && !(defined(__riscv) && __riscv_xlen == 64) - #warning "Consider adding the right mmap() syscall definitions here!" - #endif - } -@@ -1691,7 +1746,6 @@ int seccomp_memory_deny_write_execute(void) { - - int seccomp_restrict_archs(Set *archs) { - _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; -- Iterator i; - void *id; - int r; - -@@ -1709,7 +1763,7 @@ int seccomp_restrict_archs(Set *archs) { - if (!seccomp) - return -ENOMEM; - -- SET_FOREACH(id, archs, i) { -+ SET_FOREACH(id, archs) { - r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1); - if (r < 0 && r != -EEXIST) - return r; -@@ -1890,7 +1944,7 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) { - * - * Returns error if *everything* failed, and 0 otherwise. - */ -- int r = 0; -+ int r; - bool any = false; - - r = seccomp_rule_add_exact( -diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h -index ef97043..ff3b96d 100644 ---- a/src/shared/seccomp-util.h -+++ b/src/shared/seccomp-util.h -@@ -5,7 +5,10 @@ - #include - #include - -+#include "errno-list.h" -+#include "parse-util.h" - #include "set.h" -+#include "string-util.h" - - const char* seccomp_arch_to_string(uint32_t c); - int seccomp_arch_from_string(const char *n, uint32_t *ret); -@@ -21,7 +24,7 @@ typedef struct SyscallFilterSet { - } SyscallFilterSet; - - enum { -- /* Please leave DEFAULT first, but sort the rest alphabetically */ -+ /* Please leave DEFAULT first and KNOWN last, but sort the rest alphabetically */ - SYSCALL_FILTER_SET_DEFAULT, - SYSCALL_FILTER_SET_AIO, - SYSCALL_FILTER_SET_BASIC_IO, -@@ -50,6 +53,7 @@ enum { - SYSCALL_FILTER_SET_SYNC, - SYSCALL_FILTER_SET_SYSTEM_SERVICE, - SYSCALL_FILTER_SET_TIMER, -+ SYSCALL_FILTER_SET_KNOWN, - _SYSCALL_FILTER_SET_MAX - }; - -@@ -59,7 +63,13 @@ const SyscallFilterSet *syscall_filter_set_find(const char *name); - - int seccomp_filter_set_add(Hashmap *s, bool b, const SyscallFilterSet *set); - --int seccomp_add_syscall_filter_item(scmp_filter_ctx *ctx, const char *name, uint32_t action, char **exclude, bool log_missing); -+int seccomp_add_syscall_filter_item( -+ scmp_filter_ctx *ctx, -+ const char *name, -+ uint32_t action, -+ char **exclude, -+ bool log_missing, -+ char ***added); - - int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action, bool log_missing); - int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action, bool log_missing); -@@ -108,3 +118,25 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(scmp_filter_ctx, seccomp_release); - int parse_syscall_archs(char **l, Set **ret_archs); - - uint32_t scmp_act_kill_process(void); -+ -+/* This is a special value to be used where syscall filters otherwise expect errno numbers, will be -+ replaced with real seccomp action. */ -+enum { -+ SECCOMP_ERROR_NUMBER_KILL = INT_MAX - 1, -+}; -+ -+static inline bool seccomp_errno_or_action_is_valid(int n) { -+ return n == SECCOMP_ERROR_NUMBER_KILL || errno_is_valid(n); -+} -+ -+static inline int seccomp_parse_errno_or_action(const char *p) { -+ if (streq_ptr(p, "kill")) -+ return SECCOMP_ERROR_NUMBER_KILL; -+ return parse_errno(p); -+} -+ -+static inline const char *seccomp_errno_or_action_to_string(int num) { -+ if (num == SECCOMP_ERROR_NUMBER_KILL) -+ return "kill"; -+ return errno_to_name(num); -+} -diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c -index 0dccc8f..134ceda 100644 ---- a/src/shared/sleep-config.c -+++ b/src/shared/sleep-config.c -@@ -100,9 +100,8 @@ int parse_sleep_config(SleepConfig **ret_sleep_config) { - } - - int can_sleep_state(char **types) { -- char **type; -+ _cleanup_free_ char *text = NULL; - int r; -- _cleanup_free_ char *p = NULL; - - if (strv_isempty(types)) - return true; -@@ -113,34 +112,27 @@ int can_sleep_state(char **types) { - return false; - } - -- r = read_one_line_file("/sys/power/state", &p); -+ r = read_one_line_file("/sys/power/state", &text); - if (r < 0) { - log_debug_errno(r, "Failed to read /sys/power/state, cannot sleep: %m"); - return false; - } - -- STRV_FOREACH(type, types) { -- const char *word, *state; -- size_t l, k; -- -- k = strlen(*type); -- FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) -- if (l == k && memcmp(word, *type, l) == 0) { -- log_debug("Sleep mode \"%s\" is supported by the kernel.", *type); -- return true; -- } -- } -- -- if (DEBUG_LOGGING) { -+ const char *found; -+ r = string_contains_word_strv(text, NULL, types, &found); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to parse /sys/power/state: %m"); -+ if (r > 0) -+ log_debug("Sleep mode \"%s\" is supported by the kernel.", found); -+ else if (DEBUG_LOGGING) { - _cleanup_free_ char *t = strv_join(types, "/"); - log_debug("Sleep mode %s not supported by the kernel, sorry.", strnull(t)); - } -- return false; -+ return r; - } - - int can_sleep_disk(char **types) { -- _cleanup_free_ char *p = NULL; -- char **type; -+ _cleanup_free_ char *text = NULL; - int r; - - if (strv_isempty(types)) -@@ -152,29 +144,38 @@ int can_sleep_disk(char **types) { - return false; - } - -- r = read_one_line_file("/sys/power/disk", &p); -+ r = read_one_line_file("/sys/power/disk", &text); - if (r < 0) { - log_debug_errno(r, "Couldn't read /sys/power/disk: %m"); - return false; - } - -- STRV_FOREACH(type, types) { -- const char *word, *state; -- size_t l, k; -+ for (const char *p = text;;) { -+ _cleanup_free_ char *word = NULL; - -- k = strlen(*type); -- FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) { -- if (l == k && memcmp(word, *type, l) == 0) -- return true; -+ r = extract_first_word(&p, &word, NULL, 0); -+ if (r < 0) -+ return log_debug_errno(r, "Failed to parse /sys/power/disk: %m"); -+ if (r == 0) -+ break; -+ -+ char *s = word; -+ size_t l = strlen(s); -+ if (s[0] == '[' && s[l-1] == ']') { -+ s[l-1] = '\0'; -+ s++; -+ } - -- if (l == k + 2 && -- word[0] == '[' && -- memcmp(word + 1, *type, l - 2) == 0 && -- word[l-1] == ']') -- return true; -+ if (strv_contains(types, s)) { -+ log_debug("Disk sleep mode \"%s\" is supported by the kernel.", s); -+ return true; - } - } - -+ if (DEBUG_LOGGING) { -+ _cleanup_free_ char *t = strv_join(types, "/"); -+ log_debug("Disk sleep mode %s not supported by the kernel, sorry.", strnull(t)); -+ } - return false; - } - -@@ -403,6 +404,8 @@ int find_hibernate_location(HibernateLocation **ret_hibernate_location) { - r = swap_device_to_device_id(swap, &swap_device); - if (r < 0) - return log_debug_errno(r, "%s: failed to query device number: %m", swap->device); -+ if (swap_device == 0) -+ return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "%s: not backed by block device.", swap->device); - - hibernate_location = hibernate_location_free(hibernate_location); - hibernate_location = new(HibernateLocation, 1); -diff --git a/src/shared/socket-netlink.c b/src/shared/socket-netlink.c -index d72a705..23970db 100644 ---- a/src/shared/socket-netlink.c -+++ b/src/shared/socket-netlink.c -@@ -62,75 +62,23 @@ int socket_address_parse(SocketAddress *a, const char *s) { - assert(a); - assert(s); - -- *a = (SocketAddress) { -- .type = SOCK_STREAM, -- }; -- -- if (*s == '[') { -- uint16_t port; -- -- /* IPv6 in [x:.....:z]:p notation */ -- -- e = strchr(s+1, ']'); -- if (!e) -- return -EINVAL; -- -- n = strndup(s+1, e-s-1); -- if (!n) -- return -ENOMEM; -- -- errno = 0; -- if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) -- return errno_or_else(EINVAL); -- -- e++; -- if (*e != ':') -- return -EINVAL; -+ if (IN_SET(*s, '/', '@')) { -+ /* AF_UNIX socket */ -+ struct sockaddr_un un; - -- e++; -- r = parse_ip_port(e, &port); -+ r = sockaddr_un_set_path(&un, s); - if (r < 0) - return r; - -- a->sockaddr.in6.sin6_family = AF_INET6; -- a->sockaddr.in6.sin6_port = htobe16(port); -- a->size = sizeof(struct sockaddr_in6); -- -- } else if (*s == '/') { -- /* AF_UNIX socket */ -- -- size_t l; -- -- l = strlen(s); -- if (l >= sizeof(a->sockaddr.un.sun_path)) /* Note that we refuse non-NUL-terminated sockets when -- * parsing (the kernel itself is less strict here in what it -- * accepts) */ -- return -EINVAL; -- -- a->sockaddr.un.sun_family = AF_UNIX; -- memcpy(a->sockaddr.un.sun_path, s, l); -- a->size = offsetof(struct sockaddr_un, sun_path) + l + 1; -- -- } else if (*s == '@') { -- /* Abstract AF_UNIX socket */ -- size_t l; -- -- l = strlen(s+1); -- if (l >= sizeof(a->sockaddr.un.sun_path) - 1) /* Note that we refuse non-NUL-terminated sockets here -- * when parsing, even though abstract namespace sockets -- * explicitly allow embedded NUL bytes and don't consider -- * them special. But it's simply annoying to debug such -- * sockets. */ -- return -EINVAL; -- -- a->sockaddr.un.sun_family = AF_UNIX; -- memcpy(a->sockaddr.un.sun_path+1, s+1, l); -- a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l; -+ *a = (SocketAddress) { -+ .sockaddr.un = un, -+ .size = r, -+ }; - - } else if (startswith(s, "vsock:")) { - /* AF_VSOCK socket in vsock:cid:port notation */ - const char *cid_start = s + STRLEN("vsock:"); -- unsigned port; -+ unsigned port, cid; - - e = strchr(cid_start, ':'); - if (!e) -@@ -144,72 +92,82 @@ int socket_address_parse(SocketAddress *a, const char *s) { - if (!n) - return -ENOMEM; - -- if (!isempty(n)) { -- r = safe_atou(n, &a->sockaddr.vm.svm_cid); -+ if (isempty(n)) -+ cid = VMADDR_CID_ANY; -+ else { -+ r = safe_atou(n, &cid); - if (r < 0) - return r; -- } else -- a->sockaddr.vm.svm_cid = VMADDR_CID_ANY; -+ } - -- a->sockaddr.vm.svm_family = AF_VSOCK; -- a->sockaddr.vm.svm_port = port; -- a->size = sizeof(struct sockaddr_vm); -+ *a = (SocketAddress) { -+ .sockaddr.vm = { -+ .svm_cid = cid, -+ .svm_family = AF_VSOCK, -+ .svm_port = port, -+ }, -+ .size = sizeof(struct sockaddr_vm), -+ }; - - } else { - uint16_t port; - -- e = strchr(s, ':'); -- if (e) { -- r = parse_ip_port(e + 1, &port); -- if (r < 0) -- return r; -- -- n = strndup(s, e-s); -- if (!n) -- return -ENOMEM; -+ r = parse_ip_port(s, &port); -+ if (r == -ERANGE) -+ return r; /* Valid port syntax, but the numerical value is wrong for a port. */ -+ if (r >= 0) { -+ /* Just a port */ -+ if (socket_ipv6_is_supported()) -+ *a = (SocketAddress) { -+ .sockaddr.in6 = { -+ .sin6_family = AF_INET6, -+ .sin6_port = htobe16(port), -+ .sin6_addr = in6addr_any, -+ }, -+ .size = sizeof(struct sockaddr_in6), -+ }; -+ else -+ *a = (SocketAddress) { -+ .sockaddr.in = { -+ .sin_family = AF_INET, -+ .sin_port = htobe16(port), -+ .sin_addr.s_addr = INADDR_ANY, -+ }, -+ .size = sizeof(struct sockaddr_in), -+ }; - -- /* IPv4 in w.x.y.z:p notation? */ -- r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr); -- if (r < 0) -- return -errno; -- -- if (r > 0) { -- /* Gotcha, it's a traditional IPv4 address */ -- a->sockaddr.in.sin_family = AF_INET; -- a->sockaddr.in.sin_port = htobe16(port); -- a->size = sizeof(struct sockaddr_in); -- } else { -- int idx; -- -- /* Uh, our last resort, an interface name */ -- idx = resolve_ifname(NULL, n); -- if (idx < 0) -- return idx; -- -- a->sockaddr.in6.sin6_family = AF_INET6; -- a->sockaddr.in6.sin6_port = htobe16(port); -- a->sockaddr.in6.sin6_scope_id = idx; -- a->sockaddr.in6.sin6_addr = in6addr_any; -- a->size = sizeof(struct sockaddr_in6); -- } - } else { -+ union in_addr_union address; -+ int family, ifindex; - -- /* Just a port */ -- r = parse_ip_port(s, &port); -+ r = in_addr_port_ifindex_name_from_string_auto(s, &family, &address, &port, &ifindex, NULL); - if (r < 0) - return r; - -- if (socket_ipv6_is_supported()) { -- a->sockaddr.in6.sin6_family = AF_INET6; -- a->sockaddr.in6.sin6_port = htobe16(port); -- a->sockaddr.in6.sin6_addr = in6addr_any; -- a->size = sizeof(struct sockaddr_in6); -- } else { -- a->sockaddr.in.sin_family = AF_INET; -- a->sockaddr.in.sin_port = htobe16(port); -- a->sockaddr.in.sin_addr.s_addr = INADDR_ANY; -- a->size = sizeof(struct sockaddr_in); -- } -+ if (port == 0) /* No port, no go. */ -+ return -EINVAL; -+ -+ if (family == AF_INET) -+ *a = (SocketAddress) { -+ .sockaddr.in = { -+ .sin_family = AF_INET, -+ .sin_addr = address.in, -+ .sin_port = htobe16(port), -+ }, -+ .size = sizeof(struct sockaddr_in), -+ }; -+ else if (family == AF_INET6) -+ *a = (SocketAddress) { -+ .sockaddr.in6 = { -+ .sin6_family = AF_INET6, -+ .sin6_addr = address.in6, -+ .sin6_port = htobe16(port), -+ .sin6_scope_id = ifindex, -+ }, -+ .size = sizeof(struct sockaddr_in6), -+ }; -+ else -+ assert_not_reached("Family quarrel"); - } - } - -@@ -243,10 +201,6 @@ int socket_address_parse_netlink(SocketAddress *a, const char *s) { - assert(a); - assert(s); - -- *a = (SocketAddress) { -- .type = SOCK_RAW, -- }; -- - r = extract_first_word(&s, &word, NULL, 0); - if (r < 0) - return r; -@@ -263,12 +217,13 @@ int socket_address_parse_netlink(SocketAddress *a, const char *s) { - return r; - } - -- a->sockaddr.nl.nl_family = AF_NETLINK; -- a->sockaddr.nl.nl_groups = group; -- -- a->type = SOCK_RAW; -- a->size = sizeof(struct sockaddr_nl); -- a->protocol = family; -+ *a = (SocketAddress) { -+ .type = SOCK_RAW, -+ .sockaddr.nl.nl_family = AF_NETLINK, -+ .sockaddr.nl.nl_groups = group, -+ .protocol = family, -+ .size = sizeof(struct sockaddr_nl), -+ }; - - return 0; - } -@@ -345,10 +300,14 @@ int in_addr_port_ifindex_name_from_string_auto( - - /* This accepts the following: - * 192.168.0.1:53#example.com -- * [2001:4860:4860::8888]:53%eth0#example.com */ -- -- /* if ret_port is NULL, then strings with port cannot be specified. -- * Also, if ret_server_name is NULL, then server_name cannot be specified. */ -+ * [2001:4860:4860::8888]:53%eth0#example.com -+ * -+ * If ret_port is NULL, then the port cannot be specified. -+ * If ret_ifindex is NULL, then the interface index cannot be specified. -+ * If ret_server_name is NULL, then server_name cannot be specified. -+ * -+ * ret_family is always AF_INET or AF_INET6. -+ */ - - m = strchr(s, '#'); - if (m) { -@@ -369,15 +328,19 @@ int in_addr_port_ifindex_name_from_string_auto( - - m = strchr(s, '%'); - if (m) { -+ if (!ret_ifindex) -+ return -EINVAL; -+ - if (isempty(m + 1)) - return -EINVAL; - -- if (ret_ifindex) { -- /* If we shall return the interface index, try to parse it */ -- ifindex = resolve_interface(NULL, m + 1); -- if (ifindex < 0) -- return ifindex; -- } -+ if (!ifname_valid_full(m + 1, IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC)) -+ return -EINVAL; /* We want to return -EINVAL for syntactically invalid names, -+ * and -ENODEV for valid but nonexistent interfaces. */ -+ -+ ifindex = resolve_interface(NULL, m + 1); -+ if (ifindex < 0) -+ return ifindex; - - s = buf2 = strndup(s, m - s); - if (!buf2) -@@ -464,7 +427,14 @@ struct in_addr_full *in_addr_full_free(struct in_addr_full *a) { - return mfree(a); - } - --int in_addr_full_new(int family, union in_addr_union *a, uint16_t port, int ifindex, const char *server_name, struct in_addr_full **ret) { -+int in_addr_full_new( -+ int family, -+ const union in_addr_union *a, -+ uint16_t port, -+ int ifindex, -+ const char *server_name, -+ struct in_addr_full **ret) { -+ - _cleanup_free_ char *name = NULL; - struct in_addr_full *x; - -diff --git a/src/shared/socket-netlink.h b/src/shared/socket-netlink.h -index 9517f6d..e6cd7d9 100644 ---- a/src/shared/socket-netlink.h -+++ b/src/shared/socket-netlink.h -@@ -45,6 +45,6 @@ struct in_addr_full { - - struct in_addr_full *in_addr_full_free(struct in_addr_full *a); - DEFINE_TRIVIAL_CLEANUP_FUNC(struct in_addr_full*, in_addr_full_free); --int in_addr_full_new(int family, union in_addr_union *a, uint16_t port, int ifindex, const char *server_name, struct in_addr_full **ret); -+int in_addr_full_new(int family, const union in_addr_union *a, uint16_t port, int ifindex, const char *server_name, struct in_addr_full **ret); - int in_addr_full_new_from_string(const char *s, struct in_addr_full **ret); - const char *in_addr_full_to_string(struct in_addr_full *a); -diff --git a/src/shared/syscall-names.text b/src/shared/syscall-names.text -new file mode 100644 -index 0000000..40d18a8 ---- /dev/null -+++ b/src/shared/syscall-names.text -@@ -0,0 +1,597 @@ -+_llseek -+_newselect -+_sysctl -+accept -+accept4 -+access -+acct -+add_key -+adjtimex -+alarm -+arc_gettls -+arc_settls -+arc_usr_cmpxchg -+arch_prctl -+arm_fadvise64_64 -+arm_sync_file_range -+atomic_barrier -+atomic_cmpxchg_32 -+bdflush -+bfin_spinlock -+bind -+bpf -+brk -+cache_sync -+cachectl -+cacheflush -+capget -+capset -+chdir -+chmod -+chown -+chown32 -+chroot -+clock_adjtime -+clock_adjtime64 -+clock_getres -+clock_getres_time64 -+clock_gettime -+clock_gettime64 -+clock_nanosleep -+clock_nanosleep_time64 -+clock_settime -+clock_settime64 -+clone -+clone2 -+clone3 -+close -+close_range -+connect -+copy_file_range -+creat -+create_module -+delete_module -+dipc -+dup -+dup2 -+dup3 -+epoll_create -+epoll_create1 -+epoll_ctl -+epoll_ctl_old -+epoll_pwait -+epoll_wait -+epoll_wait_old -+eventfd -+eventfd2 -+exec_with_loader -+execv -+execve -+execveat -+exit -+exit_group -+faccessat -+faccessat2 -+fadvise64 -+fadvise64_64 -+fallocate -+fanotify_init -+fanotify_mark -+fchdir -+fchmod -+fchmodat -+fchown -+fchown32 -+fchownat -+fcntl -+fcntl64 -+fdatasync -+fgetxattr -+finit_module -+flistxattr -+flock -+fork -+fp_udfiex_crtl -+fremovexattr -+fsconfig -+fsetxattr -+fsmount -+fsopen -+fspick -+fstat -+fstat64 -+fstatat64 -+fstatfs -+fstatfs64 -+fsync -+ftruncate -+ftruncate64 -+futex -+futex_time64 -+futimesat -+get_kernel_syms -+get_mempolicy -+get_robust_list -+get_thread_area -+getcpu -+getcwd -+getdents -+getdents64 -+getdomainname -+getdtablesize -+getegid -+getegid32 -+geteuid -+geteuid32 -+getgid -+getgid32 -+getgroups -+getgroups32 -+gethostname -+getitimer -+getpagesize -+getpeername -+getpgid -+getpgrp -+getpid -+getpmsg -+getppid -+getpriority -+getrandom -+getresgid -+getresgid32 -+getresuid -+getresuid32 -+getrlimit -+getrusage -+getsid -+getsockname -+getsockopt -+gettid -+gettimeofday -+getuid -+getuid32 -+getunwind -+getxattr -+getxgid -+getxpid -+getxuid -+idle -+init_module -+inotify_add_watch -+inotify_init -+inotify_init1 -+inotify_rm_watch -+io_cancel -+io_destroy -+io_getevents -+io_pgetevents -+io_pgetevents_time64 -+io_setup -+io_submit -+io_uring_enter -+io_uring_register -+io_uring_setup -+ioctl -+ioperm -+iopl -+ioprio_get -+ioprio_set -+ipc -+kcmp -+kern_features -+kexec_file_load -+kexec_load -+keyctl -+kill -+lchown -+lchown32 -+lgetxattr -+link -+linkat -+listen -+listxattr -+llistxattr -+lookup_dcookie -+lremovexattr -+lseek -+lsetxattr -+lstat -+lstat64 -+madvise -+mbind -+membarrier -+memfd_create -+memory_ordering -+migrate_pages -+mincore -+mkdir -+mkdirat -+mknod -+mknodat -+mlock -+mlock2 -+mlockall -+mmap -+mmap2 -+modify_ldt -+mount -+move_mount -+move_pages -+mprotect -+mq_getsetattr -+mq_notify -+mq_open -+mq_timedreceive -+mq_timedreceive_time64 -+mq_timedsend -+mq_timedsend_time64 -+mq_unlink -+mremap -+msgctl -+msgget -+msgrcv -+msgsnd -+msync -+multiplexer -+munlock -+munlockall -+munmap -+name_to_handle_at -+nanosleep -+newfstatat -+nfsservctl -+ni_syscall -+nice -+old_adjtimex -+old_getpagesize -+oldfstat -+oldlstat -+oldolduname -+oldstat -+oldumount -+olduname -+open -+open_by_handle_at -+open_tree -+openat -+openat2 -+or1k_atomic -+osf_adjtime -+osf_afs_syscall -+osf_alt_plock -+osf_alt_setsid -+osf_alt_sigpending -+osf_asynch_daemon -+osf_audcntl -+osf_audgen -+osf_chflags -+osf_execve -+osf_exportfs -+osf_fchflags -+osf_fdatasync -+osf_fpathconf -+osf_fstat -+osf_fstatfs -+osf_fstatfs64 -+osf_fuser -+osf_getaddressconf -+osf_getdirentries -+osf_getdomainname -+osf_getfh -+osf_getfsstat -+osf_gethostid -+osf_getitimer -+osf_getlogin -+osf_getmnt -+osf_getrusage -+osf_getsysinfo -+osf_gettimeofday -+osf_kloadcall -+osf_kmodcall -+osf_lstat -+osf_memcntl -+osf_mincore -+osf_mount -+osf_mremap -+osf_msfs_syscall -+osf_msleep -+osf_mvalid -+osf_mwakeup -+osf_naccept -+osf_nfssvc -+osf_ngetpeername -+osf_ngetsockname -+osf_nrecvfrom -+osf_nrecvmsg -+osf_nsendmsg -+osf_ntp_adjtime -+osf_ntp_gettime -+osf_old_creat -+osf_old_fstat -+osf_old_getpgrp -+osf_old_killpg -+osf_old_lstat -+osf_old_open -+osf_old_sigaction -+osf_old_sigblock -+osf_old_sigreturn -+osf_old_sigsetmask -+osf_old_sigvec -+osf_old_stat -+osf_old_vadvise -+osf_old_vtrace -+osf_old_wait -+osf_oldquota -+osf_pathconf -+osf_pid_block -+osf_pid_unblock -+osf_plock -+osf_priocntlset -+osf_profil -+osf_proplist_syscall -+osf_reboot -+osf_revoke -+osf_sbrk -+osf_security -+osf_select -+osf_set_program_attributes -+osf_set_speculative -+osf_sethostid -+osf_setitimer -+osf_setlogin -+osf_setsysinfo -+osf_settimeofday -+osf_shmat -+osf_signal -+osf_sigprocmask -+osf_sigsendset -+osf_sigstack -+osf_sigwaitprim -+osf_sstk -+osf_stat -+osf_statfs -+osf_statfs64 -+osf_subsys_info -+osf_swapctl -+osf_swapon -+osf_syscall -+osf_sysinfo -+osf_table -+osf_uadmin -+osf_usleep_thread -+osf_uswitch -+osf_utc_adjtime -+osf_utc_gettime -+osf_utimes -+osf_utsname -+osf_wait4 -+osf_waitid -+pause -+pciconfig_iobase -+pciconfig_read -+pciconfig_write -+perf_event_open -+perfctr -+perfmonctl -+personality -+pidfd_getfd -+pidfd_open -+pidfd_send_signal -+pipe -+pipe2 -+pivot_root -+pkey_alloc -+pkey_free -+pkey_mprotect -+poll -+ppoll -+ppoll_time64 -+prctl -+pread64 -+preadv -+preadv2 -+prlimit64 -+process_vm_readv -+process_vm_writev -+pselect6 -+pselect6_time64 -+ptrace -+pwrite64 -+pwritev -+pwritev2 -+query_module -+quotactl -+read -+readahead -+readdir -+readlink -+readlinkat -+readv -+reboot -+recv -+recvfrom -+recvmmsg -+recvmmsg_time64 -+recvmsg -+remap_file_pages -+removexattr -+rename -+renameat -+renameat2 -+request_key -+restart_syscall -+riscv_flush_icache -+rmdir -+rseq -+rt_sigaction -+rt_sigpending -+rt_sigprocmask -+rt_sigqueueinfo -+rt_sigreturn -+rt_sigsuspend -+rt_sigtimedwait -+rt_sigtimedwait_time64 -+rt_tgsigqueueinfo -+rtas -+s390_guarded_storage -+s390_pci_mmio_read -+s390_pci_mmio_write -+s390_runtime_instr -+s390_sthyi -+sched_get_affinity -+sched_get_priority_max -+sched_get_priority_min -+sched_getaffinity -+sched_getattr -+sched_getparam -+sched_getscheduler -+sched_rr_get_interval -+sched_rr_get_interval_time64 -+sched_set_affinity -+sched_setaffinity -+sched_setattr -+sched_setparam -+sched_setscheduler -+sched_yield -+seccomp -+select -+semctl -+semget -+semop -+semtimedop -+semtimedop_time64 -+send -+sendfile -+sendfile64 -+sendmmsg -+sendmsg -+sendto -+set_mempolicy -+set_robust_list -+set_thread_area -+set_tid_address -+setdomainname -+setfsgid -+setfsgid32 -+setfsuid -+setfsuid32 -+setgid -+setgid32 -+setgroups -+setgroups32 -+sethae -+sethostname -+setitimer -+setns -+setpgid -+setpgrp -+setpriority -+setregid -+setregid32 -+setresgid -+setresgid32 -+setresuid -+setresuid32 -+setreuid -+setreuid32 -+setrlimit -+setsid -+setsockopt -+settimeofday -+setuid -+setuid32 -+setxattr -+sgetmask -+shmat -+shmctl -+shmdt -+shmget -+shutdown -+sigaction -+sigaltstack -+signal -+signalfd -+signalfd4 -+sigpending -+sigprocmask -+sigreturn -+sigsuspend -+socket -+socketcall -+socketpair -+splice -+spu_create -+spu_run -+ssetmask -+stat -+stat64 -+statfs -+statfs64 -+statx -+stime -+subpage_prot -+swapcontext -+swapoff -+swapon -+switch_endian -+symlink -+symlinkat -+sync -+sync_file_range -+sync_file_range2 -+syncfs -+sys_debug_setcontext -+syscall -+sysfs -+sysinfo -+syslog -+sysmips -+tee -+tgkill -+time -+timer_create -+timer_delete -+timer_getoverrun -+timer_gettime -+timer_gettime64 -+timer_settime -+timer_settime64 -+timerfd -+timerfd_create -+timerfd_gettime -+timerfd_gettime64 -+timerfd_settime -+timerfd_settime64 -+times -+tkill -+truncate -+truncate64 -+udftrap -+ugetrlimit -+umask -+umount -+umount2 -+uname -+unlink -+unlinkat -+unshare -+uselib -+userfaultfd -+ustat -+utime -+utimensat -+utimensat_time64 -+utimes -+utimesat -+utrap_install -+vfork -+vhangup -+vm86 -+vm86old -+vmsplice -+wait4 -+waitid -+waitpid -+write -+writev -diff --git a/src/shared/tests.c b/src/shared/tests.c -index ff662ec..a5cb486 100644 ---- a/src/shared/tests.c -+++ b/src/shared/tests.c -@@ -14,7 +14,13 @@ - #include - #undef basename - -+#include "sd-bus.h" -+ - #include "alloc-util.h" -+#include "bus-error.h" -+#include "bus-locator.h" -+#include "bus-util.h" -+#include "bus-wait-for-jobs.h" - #include "cgroup-setup.h" - #include "cgroup-util.h" - #include "env-file.h" -@@ -23,6 +29,7 @@ - #include "log.h" - #include "namespace-util.h" - #include "path-util.h" -+#include "process-util.h" - #include "random-util.h" - #include "strv.h" - #include "tests.h" -@@ -174,11 +181,88 @@ bool can_memlock(void) { - return b; - } - -+static int allocate_scope(void) { -+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; -+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -+ _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; -+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; -+ _cleanup_free_ char *scope = NULL; -+ const char *object; -+ int r; -+ -+ /* Let's try to run this test in a scope of its own, with delegation turned on, so that PID 1 doesn't -+ * interfere with our cgroup management. */ -+ -+ r = sd_bus_default_system(&bus); -+ if (r < 0) -+ return log_error_errno(r, "Failed to connect to system bus: %m"); -+ -+ r = bus_wait_for_jobs_new(bus, &w); -+ if (r < 0) -+ return log_oom(); -+ -+ if (asprintf(&scope, "%s-%" PRIx64 ".scope", program_invocation_short_name, random_u64()) < 0) -+ return log_oom(); -+ -+ r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ /* Name and Mode */ -+ r = sd_bus_message_append(m, "ss", scope, "fail"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ /* Properties */ -+ r = sd_bus_message_open_container(m, 'a', "(sv)"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid_cached()); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed"); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_message_close_container(m); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ /* Auxiliary units */ -+ r = sd_bus_message_append(m, "a(sa(sv))", 0); -+ if (r < 0) -+ return bus_log_create_error(r); -+ -+ r = sd_bus_call(bus, m, 0, &error, &reply); -+ if (r < 0) -+ return log_error_errno(r, "Failed to start transient scope unit: %s", bus_error_message(&error, r)); -+ -+ r = sd_bus_message_read(reply, "o", &object); -+ if (r < 0) -+ return bus_log_parse_error(r); -+ -+ r = bus_wait_for_jobs_one(w, object, false); -+ if (r < 0) -+ return r; -+ -+ return 0; -+} -+ - int enter_cgroup_subroot(char **ret_cgroup) { - _cleanup_free_ char *cgroup_root = NULL, *cgroup_subroot = NULL; - CGroupMask supported; - int r; - -+ r = allocate_scope(); -+ if (r < 0) -+ log_warning_errno(r, "Couldn't allocate a scope unit for this test, proceeding without."); -+ - r = cg_pid_get_path(NULL, 0, &cgroup_root); - if (r == -ENOMEDIUM) - return log_warning_errno(r, "cg_pid_get_path(NULL, 0, ...) failed: %m"); -@@ -200,5 +284,6 @@ int enter_cgroup_subroot(char **ret_cgroup) { - - if (ret_cgroup) - *ret_cgroup = TAKE_PTR(cgroup_subroot); -+ - return 0; - } -diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c -index 419c733..8b27a6d 100644 ---- a/src/shared/udev-util.c -+++ b/src/shared/udev-util.c -@@ -1,12 +1,14 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - - #include -+#include - - #include "alloc-util.h" - #include "device-util.h" - #include "env-file.h" - #include "log.h" - #include "parse-util.h" -+#include "path-util.h" - #include "signal-util.h" - #include "string-table.h" - #include "string-util.h" -@@ -108,48 +110,108 @@ int udev_parse_config_full( - return 0; - } - -+/* Note that if -ENOENT is returned, it will be logged at debug level rather than error, -+ * because it's an expected, common occurrence that the caller will handle with a fallback */ -+static int device_new_from_dev_path(const char *devlink, sd_device **ret_device) { -+ struct stat st; -+ int r; -+ -+ assert(devlink); -+ -+ r = stat(devlink, &st); -+ if (r < 0) -+ return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to stat() %s: %m", devlink); -+ -+ if (!S_ISBLK(st.st_mode)) -+ return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "%s does not point to a block device: %m", devlink); -+ -+ r = sd_device_new_from_devnum(ret_device, 'b', st.st_rdev); -+ if (r < 0) -+ return log_error_errno(r, "Failed to initialize device from %s: %m", devlink); -+ -+ return 0; -+} -+ - struct DeviceMonitorData { - const char *sysname; -+ const char *devlink; - sd_device *device; - }; - -+static void device_monitor_data_free(struct DeviceMonitorData *d) { -+ assert(d); -+ -+ sd_device_unref(d->device); -+} -+ - static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) { - struct DeviceMonitorData *data = userdata; - const char *sysname; - - assert(device); - assert(data); -- assert(data->sysname); -+ assert(data->sysname || data->devlink); - assert(!data->device); - -- if (sd_device_get_sysname(device, &sysname) >= 0 && streq(sysname, data->sysname)) { -- data->device = sd_device_ref(device); -- return sd_event_exit(sd_device_monitor_get_event(monitor), 0); -+ if (data->sysname && sd_device_get_sysname(device, &sysname) >= 0 && streq(sysname, data->sysname)) -+ goto found; -+ -+ if (data->devlink) { -+ const char *devlink; -+ -+ FOREACH_DEVICE_DEVLINK(device, devlink) -+ if (path_equal(devlink, data->devlink)) -+ goto found; -+ -+ if (sd_device_get_devname(device, &devlink) >= 0 && path_equal(devlink, data->devlink)) -+ goto found; - } - - return 0; -+ -+found: -+ data->device = sd_device_ref(device); -+ return sd_event_exit(sd_device_monitor_get_event(monitor), 0); - } - - static int device_timeout_handler(sd_event_source *s, uint64_t usec, void *userdata) { - return sd_event_exit(sd_event_source_get_event(s), -ETIMEDOUT); - } - --int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout, sd_device **ret) { -+static int device_wait_for_initialization_internal( -+ sd_device *_device, -+ const char *devlink, -+ const char *subsystem, -+ usec_t timeout, -+ sd_device **ret) { - _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; - _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL; - _cleanup_(sd_event_unrefp) sd_event *event = NULL; -- struct DeviceMonitorData data = {}; -+ /* Ensure that if !_device && devlink, device gets unrefd on errors since it will be new */ -+ _cleanup_(sd_device_unrefp) sd_device *device = sd_device_ref(_device); -+ _cleanup_(device_monitor_data_free) struct DeviceMonitorData data = { -+ .devlink = devlink, -+ }; - int r; - -- assert(device); -+ assert(device || (subsystem && devlink)); - -- if (sd_device_get_is_initialized(device) > 0) { -- if (ret) -- *ret = sd_device_ref(device); -- return 0; -+ /* Devlink might already exist, if it does get the device to use the sysname filtering */ -+ if (!device && devlink) { -+ r = device_new_from_dev_path(devlink, &device); -+ if (r < 0 && r != -ENOENT) -+ return r; - } - -- assert_se(sd_device_get_sysname(device, &data.sysname) >= 0); -+ if (device) { -+ if (sd_device_get_is_initialized(device) > 0) { -+ if (ret) -+ *ret = sd_device_ref(device); -+ return 0; -+ } -+ /* We need either the sysname or the devlink for filtering */ -+ assert_se(sd_device_get_sysname(device, &data.sysname) >= 0 || devlink); -+ } - - /* Wait until the device is initialized, so that we can get access to the ID_PATH property */ - -@@ -161,7 +223,7 @@ int device_wait_for_initialization(sd_device *device, const char *subsystem, use - if (r < 0) - return log_error_errno(r, "Failed to acquire monitor: %m"); - -- if (!subsystem) { -+ if (device && !subsystem) { - r = sd_device_get_subsystem(device, &subsystem); - if (r < 0 && r != -ENOENT) - return log_device_error_errno(device, r, "Failed to get subsystem: %m"); -@@ -182,16 +244,22 @@ int device_wait_for_initialization(sd_device *device, const char *subsystem, use - return log_error_errno(r, "Failed to start device monitor: %m"); - - if (timeout != USEC_INFINITY) { -- r = sd_event_add_time(event, &timeout_source, -- CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + timeout, 0, -- device_timeout_handler, NULL); -+ r = sd_event_add_time_relative( -+ event, &timeout_source, -+ CLOCK_MONOTONIC, timeout, 0, -+ device_timeout_handler, NULL); - if (r < 0) - return log_error_errno(r, "Failed to add timeout event source: %m"); - } - - /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized - * yet. */ -- if (sd_device_get_is_initialized(device) > 0) { -+ if (!device && devlink) { -+ r = device_new_from_dev_path(devlink, &device); -+ if (r < 0 && r != -ENOENT) -+ return r; -+ } -+ if (device && sd_device_get_is_initialized(device) > 0) { - if (ret) - *ret = sd_device_ref(device); - return 0; -@@ -206,6 +274,14 @@ int device_wait_for_initialization(sd_device *device, const char *subsystem, use - return 0; - } - -+int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout, sd_device **ret) { -+ return device_wait_for_initialization_internal(device, NULL, subsystem, timeout, ret); -+} -+ -+int device_wait_for_devlink(const char *devlink, const char *subsystem, usec_t timeout, sd_device **ret) { -+ return device_wait_for_initialization_internal(NULL, devlink, subsystem, timeout, ret); -+} -+ - int device_is_renaming(sd_device *dev) { - int r; - -diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h -index c35d293..04c7ce5 100644 ---- a/src/shared/udev-util.h -+++ b/src/shared/udev-util.h -@@ -29,5 +29,6 @@ static inline int udev_parse_config(void) { - } - - int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout, sd_device **ret); -+int device_wait_for_devlink(const char *path, const char *subsystem, usec_t timeout, sd_device **ret); - int device_is_renaming(sd_device *dev); - bool device_for_action(sd_device *dev, DeviceAction action); -diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c -index ed4affd..3b51c7c 100644 ---- a/src/shared/unit-file.c -+++ b/src/shared/unit-file.c -@@ -1,5 +1,7 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - -+#include "sd-id128.h" -+ - #include "dirent-util.h" - #include "fd-util.h" - #include "fs-util.h" -@@ -199,9 +201,14 @@ static bool lookup_paths_mtime_exclude(const LookupPaths *lp, const char *path) - streq_ptr(path, lp->runtime_control); - } - --bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime) { -- char **dir; -+#define HASH_KEY SD_ID128_MAKE(4e,86,1b,e3,39,b3,40,46,98,5d,b8,11,34,8f,c3,c1) -+ -+bool lookup_paths_timestamp_hash_same(const LookupPaths *lp, uint64_t timestamp_hash, uint64_t *ret_new) { -+ struct siphash state; - -+ siphash24_init(&state, HASH_KEY.bytes); -+ -+ char **dir; - STRV_FOREACH(dir, (char**) lp->search_path) { - struct stat st; - -@@ -217,18 +224,20 @@ bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime) { - continue; - } - -- if (timespec_load(&st.st_mtim) > mtime) { -- log_debug_errno(errno, "Unit dir %s has changed, need to update cache.", *dir); -- return false; -- } -+ siphash24_compress_usec_t(timespec_load(&st.st_mtim), &state); - } - -- return true; -+ uint64_t updated = siphash24_finalize(&state); -+ if (ret_new) -+ *ret_new = updated; -+ if (updated != timestamp_hash) -+ log_debug("Modification times have changed, need to update cache."); -+ return updated == timestamp_hash; - } - - int unit_file_build_name_map( - const LookupPaths *lp, -- usec_t *cache_mtime, -+ uint64_t *cache_timestamp_hash, - Hashmap **unit_ids_map, - Hashmap **unit_names_map, - Set **path_cache) { -@@ -245,14 +254,18 @@ int unit_file_build_name_map( - - _cleanup_hashmap_free_ Hashmap *ids = NULL, *names = NULL; - _cleanup_set_free_free_ Set *paths = NULL; -+ uint64_t timestamp_hash; - char **dir; - int r; -- usec_t mtime = 0; - -- /* Before doing anything, check if the mtime that was passed is still valid. If -- * yes, do nothing. If *cache_time == 0, always build the cache. */ -- if (cache_mtime && *cache_mtime > 0 && lookup_paths_mtime_good(lp, *cache_mtime)) -- return 0; -+ /* Before doing anything, check if the timestamp hash that was passed is still valid. -+ * If yes, do nothing. */ -+ if (cache_timestamp_hash && -+ lookup_paths_timestamp_hash_same(lp, *cache_timestamp_hash, ×tamp_hash)) -+ return 0; -+ -+ /* The timestamp hash is now set based on the mtimes from before when we start reading files. -+ * If anything is modified concurrently, we'll consider the cache outdated. */ - - if (path_cache) { - paths = set_new(&path_hash_ops_free); -@@ -263,7 +276,6 @@ int unit_file_build_name_map( - STRV_FOREACH(dir, (char**) lp->search_path) { - struct dirent *de; - _cleanup_closedir_ DIR *d = NULL; -- struct stat st; - - d = opendir(*dir); - if (!d) { -@@ -272,13 +284,6 @@ int unit_file_build_name_map( - continue; - } - -- /* Determine the latest lookup path modification time */ -- if (fstat(dirfd(d), &st) < 0) -- return log_error_errno(errno, "Failed to fstat %s: %m", *dir); -- -- if (!lookup_paths_mtime_exclude(lp, *dir)) -- mtime = MAX(mtime, timespec_load(&st.st_mtim)); -- - FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { - char *filename; - _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; -@@ -394,9 +399,8 @@ int unit_file_build_name_map( - } - - /* Let's also put the names in the reverse db. */ -- Iterator it; - const char *dummy, *src; -- HASHMAP_FOREACH_KEY(dummy, src, ids, it) { -+ HASHMAP_FOREACH_KEY(dummy, src, ids) { - const char *dst; - - r = unit_ids_map_get(ids, src, &dst); -@@ -417,8 +421,8 @@ int unit_file_build_name_map( - basename(dst), src); - } - -- if (cache_mtime) -- *cache_mtime = mtime; -+ if (cache_timestamp_hash) -+ *cache_timestamp_hash = timestamp_hash; - - hashmap_free_and_replace(*unit_ids_map, ids); - hashmap_free_and_replace(*unit_names_map, names); -diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h -index d6d041d..d36bb07 100644 ---- a/src/shared/unit-file.h -+++ b/src/shared/unit-file.h -@@ -43,19 +43,19 @@ bool unit_type_may_template(UnitType type) _const_; - int unit_symlink_name_compatible(const char *symlink, const char *target, bool instance_propagation); - int unit_validate_alias_symlink_and_warn(const char *filename, const char *target); - --bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime); -+bool lookup_paths_timestamp_hash_same(const LookupPaths *lp, uint64_t timestamp_hash, uint64_t *ret_new); - int unit_file_build_name_map( - const LookupPaths *lp, -- usec_t *ret_time, -- Hashmap **ret_unit_ids_map, -- Hashmap **ret_unit_names_map, -- Set **ret_path_cache); -+ uint64_t *cache_timestamp_hash, -+ Hashmap **unit_ids_map, -+ Hashmap **unit_names_map, -+ Set **path_cache); - - int unit_file_find_fragment( - Hashmap *unit_ids_map, - Hashmap *unit_name_map, - const char *unit_name, - const char **ret_fragment_path, -- Set **names); -+ Set **ret_names); - - const char* runlevel_to_target(const char *rl); -diff --git a/src/shared/user-record-nss.c b/src/shared/user-record-nss.c -index f265a2a..d06c8ab 100644 ---- a/src/shared/user-record-nss.c -+++ b/src/shared/user-record-nss.c -@@ -5,10 +5,36 @@ - #include "libcrypt-util.h" - #include "strv.h" - #include "user-record-nss.h" -+#include "user-util.h" -+#include "utf8.h" - - #define SET_IF(field, condition, value, fallback) \ - field = (condition) ? (value) : (fallback) - -+static inline const char* utf8_only(const char *s) { -+ return s && utf8_is_valid(s) ? s : NULL; -+} -+ -+static inline int strv_extend_strv_utf8_only(char ***dst, char **src, bool filter_duplicates) { -+ _cleanup_free_ char **t = NULL; -+ size_t l, j = 0; -+ -+ /* First, do a shallow copy of s, filtering for only valid utf-8 strings */ -+ l = strv_length(src); -+ t = new(char*, l + 1); -+ if (!t) -+ return -ENOMEM; -+ -+ for (size_t i = 0; i < l; i++) -+ if (utf8_is_valid(src[i])) -+ t[j++] = src[i]; -+ if (j == 0) -+ return 0; -+ -+ t[j] = NULL; -+ return strv_extend_strv(dst, t, filter_duplicates); -+} -+ - int nss_passwd_to_user_record( - const struct passwd *pwd, - const struct spwd *spwd, -@@ -34,23 +60,39 @@ int nss_passwd_to_user_record( - if (r < 0) - return r; - -- r = free_and_strdup(&hr->real_name, -- streq_ptr(pwd->pw_gecos, hr->user_name) ? NULL : empty_to_null(pwd->pw_gecos)); -- if (r < 0) -- return r; -+ /* Some bad NSS modules synthesize GECOS fields with embedded ":" or "\n" characters, which are not -+ * something we can output in /etc/passwd compatible format, since these are record separators -+ * there. We normally refuse that, but we need to maintain compatibility with arbitrary NSS modules, -+ * hence let's do what glibc does: mangle the data to fit the format. */ -+ if (isempty(pwd->pw_gecos) || streq_ptr(pwd->pw_gecos, hr->user_name)) -+ hr->real_name = mfree(hr->real_name); -+ else if (valid_gecos(pwd->pw_gecos)) { -+ r = free_and_strdup(&hr->real_name, pwd->pw_gecos); -+ if (r < 0) -+ return r; -+ } else { -+ _cleanup_free_ char *mangled = NULL; - -- r = free_and_strdup(&hr->home_directory, empty_to_null(pwd->pw_dir)); -+ mangled = mangle_gecos(pwd->pw_gecos); -+ if (!mangled) -+ return -ENOMEM; -+ -+ free_and_replace(hr->real_name, mangled); -+ } -+ -+ r = free_and_strdup(&hr->home_directory, utf8_only(empty_to_null(pwd->pw_dir))); - if (r < 0) - return r; - -- r = free_and_strdup(&hr->shell, empty_to_null(pwd->pw_shell)); -+ r = free_and_strdup(&hr->shell, utf8_only(empty_to_null(pwd->pw_shell))); - if (r < 0) - return r; - - hr->uid = pwd->pw_uid; - hr->gid = pwd->pw_gid; - -- if (spwd && hashed_password_valid(spwd->sp_pwdp)) { -+ if (spwd && -+ looks_like_hashed_password(utf8_only(spwd->sp_pwdp))) { /* Ignore locked, disabled, and mojibake passwords */ - strv_free_erase(hr->hashed_password); - hr->hashed_password = strv_new(spwd->sp_pwdp); - if (!hr->hashed_password) -@@ -274,3 +316,216 @@ int nss_user_record_by_uid( - (*ret)->incomplete = incomplete; - return 0; - } -+ -+int nss_group_to_group_record( -+ const struct group *grp, -+ const struct sgrp *sgrp, -+ GroupRecord **ret) { -+ -+ _cleanup_(group_record_unrefp) GroupRecord *g = NULL; -+ int r; -+ -+ assert(grp); -+ assert(ret); -+ -+ if (isempty(grp->gr_name)) -+ return -EINVAL; -+ -+ if (sgrp && !streq_ptr(sgrp->sg_namp, grp->gr_name)) -+ return -EINVAL; -+ -+ g = group_record_new(); -+ if (!g) -+ return -ENOMEM; -+ -+ g->group_name = strdup(grp->gr_name); -+ if (!g->group_name) -+ return -ENOMEM; -+ -+ r = strv_extend_strv_utf8_only(&g->members, grp->gr_mem, false); -+ if (r < 0) -+ return r; -+ -+ g->gid = grp->gr_gid; -+ -+ if (sgrp) { -+ if (looks_like_hashed_password(utf8_only(sgrp->sg_passwd))) { -+ g->hashed_password = strv_new(sgrp->sg_passwd); -+ if (!g->hashed_password) -+ return -ENOMEM; -+ } -+ -+ r = strv_extend_strv_utf8_only(&g->members, sgrp->sg_mem, true); -+ if (r < 0) -+ return r; -+ -+ r = strv_extend_strv_utf8_only(&g->administrators, sgrp->sg_adm, false); -+ if (r < 0) -+ return r; -+ } -+ -+ r = json_build(&g->json, JSON_BUILD_OBJECT( -+ JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(g->group_name)), -+ JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(g->gid)), -+ JSON_BUILD_PAIR_CONDITION(!strv_isempty(g->members), "members", JSON_BUILD_STRV(g->members)), -+ JSON_BUILD_PAIR_CONDITION(!strv_isempty(g->hashed_password), "privileged", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("hashedPassword", JSON_BUILD_STRV(g->hashed_password)))), -+ JSON_BUILD_PAIR_CONDITION(!strv_isempty(g->administrators), "administrators", JSON_BUILD_STRV(g->administrators)))); -+ if (r < 0) -+ return r; -+ -+ g->mask = USER_RECORD_REGULAR | -+ (!strv_isempty(g->hashed_password) ? USER_RECORD_PRIVILEGED : 0); -+ -+ *ret = TAKE_PTR(g); -+ return 0; -+} -+ -+int nss_sgrp_for_group(const struct group *grp, struct sgrp *ret_sgrp, char **ret_buffer) { -+ size_t buflen = 4096; -+ int r; -+ -+ assert(grp); -+ assert(ret_sgrp); -+ assert(ret_buffer); -+ -+ for (;;) { -+ _cleanup_free_ char *buf = NULL; -+ struct sgrp sgrp, *result; -+ -+ buf = malloc(buflen); -+ if (!buf) -+ return -ENOMEM; -+ -+ r = getsgnam_r(grp->gr_name, &sgrp, buf, buflen, &result); -+ if (r == 0) { -+ if (!result) -+ return -ESRCH; -+ -+ *ret_sgrp = *result; -+ *ret_buffer = TAKE_PTR(buf); -+ return 0; -+ } -+ if (r < 0) -+ return -EIO; /* Weird, this should not return negative! */ -+ if (r != ERANGE) -+ return -r; -+ -+ if (buflen > SIZE_MAX / 2) -+ return -ERANGE; -+ -+ buflen *= 2; -+ buf = mfree(buf); -+ } -+} -+ -+int nss_group_record_by_name( -+ const char *name, -+ bool with_shadow, -+ GroupRecord **ret) { -+ -+ _cleanup_free_ char *buf = NULL, *sbuf = NULL; -+ struct group grp, *result; -+ bool incomplete = false; -+ size_t buflen = 4096; -+ struct sgrp sgrp, *sresult = NULL; -+ int r; -+ -+ assert(name); -+ assert(ret); -+ -+ for (;;) { -+ buf = malloc(buflen); -+ if (!buf) -+ return -ENOMEM; -+ -+ r = getgrnam_r(name, &grp, buf, buflen, &result); -+ if (r == 0) { -+ if (!result) -+ return -ESRCH; -+ -+ break; -+ } -+ -+ if (r < 0) -+ return log_debug_errno(SYNTHETIC_ERRNO(EIO), "getgrnam_r() returned a negative value"); -+ if (r != ERANGE) -+ return -r; -+ if (buflen > SIZE_MAX / 2) -+ return -ERANGE; -+ -+ buflen *= 2; -+ buf = mfree(buf); -+ } -+ -+ if (with_shadow) { -+ r = nss_sgrp_for_group(result, &sgrp, &sbuf); -+ if (r < 0) { -+ log_debug_errno(r, "Failed to do shadow lookup for group %s, ignoring: %m", result->gr_name); -+ incomplete = ERRNO_IS_PRIVILEGE(r); -+ } else -+ sresult = &sgrp; -+ } else -+ incomplete = true; -+ -+ r = nss_group_to_group_record(result, sresult, ret); -+ if (r < 0) -+ return r; -+ -+ (*ret)->incomplete = incomplete; -+ return 0; -+} -+ -+int nss_group_record_by_gid( -+ gid_t gid, -+ bool with_shadow, -+ GroupRecord **ret) { -+ -+ _cleanup_free_ char *buf = NULL, *sbuf = NULL; -+ struct group grp, *result; -+ bool incomplete = false; -+ size_t buflen = 4096; -+ struct sgrp sgrp, *sresult = NULL; -+ int r; -+ -+ assert(ret); -+ -+ for (;;) { -+ buf = malloc(buflen); -+ if (!buf) -+ return -ENOMEM; -+ -+ r = getgrgid_r(gid, &grp, buf, buflen, &result); -+ if (r == 0) { -+ if (!result) -+ return -ESRCH; -+ break; -+ } -+ -+ if (r < 0) -+ return log_debug_errno(SYNTHETIC_ERRNO(EIO), "getgrgid_r() returned a negative value"); -+ if (r != ERANGE) -+ return -r; -+ if (buflen > SIZE_MAX / 2) -+ return -ERANGE; -+ -+ buflen *= 2; -+ buf = mfree(buf); -+ } -+ -+ if (with_shadow) { -+ r = nss_sgrp_for_group(result, &sgrp, &sbuf); -+ if (r < 0) { -+ log_debug_errno(r, "Failed to do shadow lookup for group %s, ignoring: %m", result->gr_name); -+ incomplete = ERRNO_IS_PRIVILEGE(r); -+ } else -+ sresult = &sgrp; -+ } else -+ incomplete = true; -+ -+ r = nss_group_to_group_record(result, sresult, ret); -+ if (r < 0) -+ return r; -+ -+ (*ret)->incomplete = incomplete; -+ return 0; -+} -diff --git a/src/shared/user-record-nss.h b/src/shared/user-record-nss.h -index 0eb78d5..e2a87f6 100644 ---- a/src/shared/user-record-nss.h -+++ b/src/shared/user-record-nss.h -@@ -1,15 +1,24 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - #pragma once - -+#include -+#include - #include - #include - -+#include "group-record.h" - #include "user-record.h" - --/* Synthesizes a UserRecord object from NSS data */ -+/* Synthesize UserRecord and GroupRecord objects from NSS data */ - - int nss_passwd_to_user_record(const struct passwd *pwd, const struct spwd *spwd, UserRecord **ret); - int nss_spwd_for_passwd(const struct passwd *pwd, struct spwd *ret_spwd, char **ret_buffer); - - int nss_user_record_by_name(const char *name, bool with_shadow, UserRecord **ret); - int nss_user_record_by_uid(uid_t uid, bool with_shadow, UserRecord **ret); -+ -+int nss_group_to_group_record(const struct group *grp, const struct sgrp *sgrp, GroupRecord **ret); -+int nss_sgrp_for_group(const struct group *grp, struct sgrp *ret_sgrp, char **ret_buffer); -+ -+int nss_group_record_by_name(const char *name, bool with_shadow, GroupRecord **ret); -+int nss_group_record_by_gid(gid_t gid, bool with_shadow, GroupRecord **ret); -diff --git a/src/shared/user-record-show.c b/src/shared/user-record-show.c -index 84ededd..33787c0 100644 ---- a/src/shared/user-record-show.c -+++ b/src/shared/user-record-show.c -@@ -2,7 +2,6 @@ - - #include "format-util.h" - #include "fs-util.h" --#include "group-record.h" - #include "process-util.h" - #include "rlimit-util.h" - #include "strv.h" -@@ -16,7 +15,7 @@ const char *user_record_state_color(const char *state) { - return ansi_grey(); - else if (streq(state, "active")) - return ansi_highlight_green(); -- else if (streq(state, "locked")) -+ else if (STR_IN_SET(state, "locked", "dirty")) - return ansi_highlight_yellow(); - - return NULL; -@@ -479,6 +478,9 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) { - if (hr->n_fido2_hmac_credential > 0) - printf(" FIDO2 Token: %zu\n", hr->n_fido2_hmac_credential); - -+ if (!strv_isempty(hr->recovery_key_type)) -+ printf("Recovery Key: %zu\n", strv_length(hr->recovery_key_type)); -+ - k = strv_length(hr->hashed_password); - if (k == 0) - printf(" Passwords: %snone%s\n", -@@ -503,3 +505,75 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) { - if (hr->service) - printf(" Service: %s\n", hr->service); - } -+ -+void group_record_show(GroupRecord *gr, bool show_full_user_info) { -+ int r; -+ -+ printf(" Group name: %s\n", -+ group_record_group_name_and_realm(gr)); -+ -+ printf(" Disposition: %s\n", user_disposition_to_string(group_record_disposition(gr))); -+ -+ if (gr->last_change_usec != USEC_INFINITY) { -+ char buf[FORMAT_TIMESTAMP_MAX]; -+ printf(" Last Change: %s\n", format_timestamp(buf, sizeof(buf), gr->last_change_usec)); -+ } -+ -+ if (gid_is_valid(gr->gid)) -+ printf(" GID: " GID_FMT "\n", gr->gid); -+ -+ if (show_full_user_info) { -+ _cleanup_(userdb_iterator_freep) UserDBIterator *iterator = NULL; -+ -+ r = membershipdb_by_group(gr->group_name, 0, &iterator); -+ if (r < 0) { -+ errno = -r; -+ printf(" Members: (can't acquire: %m)"); -+ } else { -+ const char *prefix = " Members:"; -+ -+ for (;;) { -+ _cleanup_free_ char *user = NULL; -+ -+ r = membershipdb_iterator_get(iterator, &user, NULL); -+ if (r == -ESRCH) -+ break; -+ if (r < 0) { -+ errno = -r; -+ printf("%s (can't iterate: %m\n", prefix); -+ break; -+ } -+ -+ printf("%s %s\n", prefix, user); -+ prefix = " "; -+ } -+ } -+ } else { -+ const char *prefix = " Members:"; -+ char **i; -+ -+ STRV_FOREACH(i, gr->members) { -+ printf("%s %s\n", prefix, *i); -+ prefix = " "; -+ } -+ } -+ -+ if (!strv_isempty(gr->administrators)) { -+ const char *prefix = " Admins:"; -+ char **i; -+ -+ STRV_FOREACH(i, gr->administrators) { -+ printf("%s %s\n", prefix, *i); -+ prefix = " "; -+ } -+ } -+ -+ if (gr->description && !streq(gr->description, gr->group_name)) -+ printf(" Description: %s\n", gr->description); -+ -+ if (!strv_isempty(gr->hashed_password)) -+ printf(" Passwords: %zu\n", strv_length(gr->hashed_password)); -+ -+ if (gr->service) -+ printf(" Service: %s\n", gr->service); -+} -diff --git a/src/shared/user-record-show.h b/src/shared/user-record-show.h -index bd22be2..4dcee18 100644 ---- a/src/shared/user-record-show.h -+++ b/src/shared/user-record-show.h -@@ -2,7 +2,9 @@ - #pragma once - - #include "user-record.h" -+#include "group-record.h" - - const char *user_record_state_color(const char *state); - - void user_record_show(UserRecord *hr, bool show_full_group_info); -+void group_record_show(GroupRecord *gr, bool show_full_user_info); -diff --git a/src/shared/user-record.c b/src/shared/user-record.c -index 16edaa4..e04df4d 100644 ---- a/src/shared/user-record.c -+++ b/src/shared/user-record.c -@@ -112,6 +112,14 @@ static void fido2_hmac_salt_done(Fido2HmacSalt *s) { - erase_and_free(s->hashed_password); - } - -+static void recovery_key_done(RecoveryKey *k) { -+ if (!k) -+ return; -+ -+ free(k->type); -+ erase_and_free(k->hashed_password); -+} -+ - static UserRecord* user_record_free(UserRecord *h) { - if (!h) - return NULL; -@@ -169,6 +177,10 @@ static UserRecord* user_record_free(UserRecord *h) { - for (size_t i = 0; i < h->n_fido2_hmac_salt; i++) - fido2_hmac_salt_done(h->fido2_hmac_salt + i); - -+ strv_free(h->recovery_key_type); -+ for (size_t i = 0; i < h->n_recovery_key; i++) -+ recovery_key_done(h->recovery_key + i); -+ - json_variant_unref(h->json); - - return mfree(h); -@@ -203,10 +215,9 @@ int json_dispatch_realm(const char *name, JsonVariant *variant, JsonDispatchFlag - return 0; - } - --static int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { -+int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { - char **s = userdata; - const char *n; -- int r; - - if (json_variant_is_null(variant)) { - *s = mfree(*s); -@@ -217,12 +228,20 @@ static int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispa - return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name)); - - n = json_variant_string(variant); -- if (!valid_gecos(n)) -- return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid GECOS compatible real name.", strna(name)); -+ if (valid_gecos(n)) { -+ if (free_and_strdup(s, n) < 0) -+ return json_log_oom(variant, flags); -+ } else { -+ _cleanup_free_ char *m = NULL; - -- r = free_and_strdup(s, n); -- if (r < 0) -- return json_log(variant, flags, r, "Failed to allocate string: %m"); -+ json_log(variant, flags|JSON_DEBUG, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid GECOS compatible string, mangling.", strna(name)); -+ -+ m = mangle_gecos(n); -+ if (!m) -+ return json_log_oom(variant, flags); -+ -+ free_and_replace(*s, m); -+ } - - return 0; - } -@@ -917,6 +936,46 @@ static int dispatch_fido2_hmac_salt(const char *name, JsonVariant *variant, Json - return 0; - } - -+static int dispatch_recovery_key(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { -+ UserRecord *h = userdata; -+ JsonVariant *e; -+ int r; -+ -+ if (!json_variant_is_array(variant)) -+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an array of objects.", strna(name)); -+ -+ JSON_VARIANT_ARRAY_FOREACH(e, variant) { -+ RecoveryKey *array, *k; -+ -+ static const JsonDispatch recovery_key_dispatch_table[] = { -+ { "type", JSON_VARIANT_STRING, json_dispatch_string, 0, JSON_MANDATORY }, -+ { "hashedPassword", JSON_VARIANT_STRING, json_dispatch_string, offsetof(RecoveryKey, hashed_password), JSON_MANDATORY }, -+ {}, -+ }; -+ -+ if (!json_variant_is_object(e)) -+ return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), "JSON array element is not an object."); -+ -+ array = reallocarray(h->recovery_key, h->n_recovery_key + 1, sizeof(RecoveryKey)); -+ if (!array) -+ return log_oom(); -+ -+ h->recovery_key = array; -+ k = h->recovery_key + h->n_recovery_key; -+ *k = (RecoveryKey) {}; -+ -+ r = json_dispatch(e, recovery_key_dispatch_table, NULL, flags, k); -+ if (r < 0) { -+ recovery_key_done(k); -+ return r; -+ } -+ -+ h->n_recovery_key++; -+ } -+ -+ return 0; -+} -+ - static int dispatch_privileged(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { - - static const JsonDispatch privileged_dispatch_table[] = { -@@ -925,6 +984,7 @@ static int dispatch_privileged(const char *name, JsonVariant *variant, JsonDispa - { "sshAuthorizedKeys", _JSON_VARIANT_TYPE_INVALID, json_dispatch_strv, offsetof(UserRecord, ssh_authorized_keys), 0 }, - { "pkcs11EncryptedKey", JSON_VARIANT_ARRAY, dispatch_pkcs11_key, 0, 0 }, - { "fido2HmacSalt", JSON_VARIANT_ARRAY, dispatch_fido2_hmac_salt, 0, 0 }, -+ { "recoveryKey", JSON_VARIANT_ARRAY, dispatch_recovery_key, 0, 0 }, - {}, - }; - -@@ -1468,6 +1528,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla - { "passwordChangeNow", JSON_VARIANT_BOOLEAN, json_dispatch_tristate, offsetof(UserRecord, password_change_now), 0 }, - { "pkcs11TokenUri", JSON_VARIANT_ARRAY, dispatch_pkcs11_uri_array, offsetof(UserRecord, pkcs11_token_uri), 0 }, - { "fido2HmacCredential", JSON_VARIANT_ARRAY, dispatch_fido2_hmac_credential_array, 0, 0 }, -+ { "recoveryKeyType", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(UserRecord, recovery_key_type), 0 }, - - { "secret", JSON_VARIANT_OBJECT, dispatch_secret, 0, 0 }, - { "privileged", JSON_VARIANT_OBJECT, dispatch_privileged, 0, 0 }, -@@ -1574,7 +1635,7 @@ UserStorage user_record_storage(UserRecord *h) { - const char *user_record_file_system_type(UserRecord *h) { - assert(h); - -- return h->file_system_type ?: "ext4"; -+ return h->file_system_type ?: "btrfs"; - } - - const char *user_record_skeleton_directory(UserRecord *h) { -diff --git a/src/shared/user-record.h b/src/shared/user-record.h -index 1bfd095..357c246 100644 ---- a/src/shared/user-record.h -+++ b/src/shared/user-record.h -@@ -206,6 +206,14 @@ typedef struct Fido2HmacSalt { - char *hashed_password; - } Fido2HmacSalt; - -+typedef struct RecoveryKey { -+ /* The type of recovery key, must be "modhex64" right now */ -+ char *type; -+ -+ /* A UNIX password hash of the normalized form of modhex64 */ -+ char *hashed_password; -+} RecoveryKey; -+ - typedef struct UserRecord { - /* The following three fields are not part of the JSON record */ - unsigned n_ref; -@@ -332,6 +340,10 @@ typedef struct UserRecord { - size_t n_fido2_hmac_salt; - int fido2_user_presence_permitted; - -+ char **recovery_key_type; -+ RecoveryKey *recovery_key; -+ size_t n_recovery_key; -+ - JsonVariant *json; - } UserRecord; - -@@ -388,6 +400,7 @@ int user_record_test_password_change_required(UserRecord *h); - - /* The following six are user by group-record.c, that's why we export them here */ - int json_dispatch_realm(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); -+int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); - int json_dispatch_user_group_list(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); - int json_dispatch_user_disposition(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); - -diff --git a/src/shared/userdb.c b/src/shared/userdb.c -index 9412086..57e58a6 100644 ---- a/src/shared/userdb.c -+++ b/src/shared/userdb.c -@@ -6,7 +6,6 @@ - #include "dlfcn-util.h" - #include "errno-util.h" - #include "fd-util.h" --#include "group-record-nss.h" - #include "missing_syscall.h" - #include "parse-util.h" - #include "set.h" -diff --git a/src/shared/varlink.c b/src/shared/varlink.c -index be3559d..86b5f08 100644 ---- a/src/shared/varlink.c -+++ b/src/shared/varlink.c -@@ -9,6 +9,7 @@ - #include "io-util.h" - #include "list.h" - #include "process-util.h" -+#include "selinux-util.h" - #include "set.h" - #include "socket-util.h" - #include "string-table.h" -@@ -579,11 +580,17 @@ static int varlink_parse_message(Varlink *v) { - - sz = e - begin + 1; - -- varlink_log(v, "New incoming message: %s", begin); -+ varlink_log(v, "New incoming message: %s", begin); /* FIXME: should we output the whole message here before validation? -+ * This may produce a non-printable journal entry if the message -+ * is invalid. We may also expose privileged information. */ - - r = json_parse(begin, 0, &v->current, NULL, NULL); -- if (r < 0) -- return r; -+ if (r < 0) { -+ /* If we encounter a parse failure flush all data. We cannot possibly recover from this, -+ * hence drop all buffered data now. */ -+ v->input_buffer_index = v->input_buffer_size = v->input_buffer_unscanned = 0; -+ return varlink_log_errno(v, r, "Failed to parse JSON: %m"); -+ } - - v->input_buffer_size -= sz; - -@@ -862,7 +869,7 @@ static int varlink_dispatch_method(Varlink *v) { - - /* We got an error back from the callback. Propagate it to the client if the method call remains unanswered. */ - if (!FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) { -- r = varlink_errorb(v, VARLINK_ERROR_SYSTEM, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("errno", JSON_BUILD_INTEGER(-r)))); -+ r = varlink_error_errno(v, r); - if (r < 0) - return r; - } -@@ -1038,10 +1045,8 @@ int varlink_wait(Varlink *v, usec_t timeout) { - return events; - - r = fd_wait_for_event(fd, events, t); -- if (r < 0) -+ if (r <= 0) - return r; -- if (r == 0) -- return 0; - - handle_revents(v, r); - return 1; -@@ -1659,6 +1664,13 @@ int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters) { - return -EINVAL; - } - -+int varlink_error_errno(Varlink *v, int error) { -+ return varlink_errorb( -+ v, -+ VARLINK_ERROR_SYSTEM, -+ JSON_BUILD_OBJECT(JSON_BUILD_PAIR("errno", JSON_BUILD_INTEGER(abs(error))))); -+} -+ - int varlink_notify(Varlink *v, JsonVariant *parameters) { - _cleanup_(json_variant_unrefp) JsonVariant *m = NULL; - int r; -@@ -2198,9 +2210,7 @@ int varlink_server_listen_fd(VarlinkServer *s, int fd) { - }; - - if (s->event) { -- _cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL; -- -- r = sd_event_add_io(s->event, &es, fd, EPOLLIN, connect_callback, ss); -+ r = sd_event_add_io(s->event, &ss->event_source, fd, EPOLLIN, connect_callback, ss); - if (r < 0) - return r; - -@@ -2236,9 +2246,11 @@ int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t - - (void) sockaddr_un_unlink(&sockaddr.un); - -- RUN_WITH_UMASK(~m & 0777) -- if (bind(fd, &sockaddr.sa, sockaddr_len) < 0) -- return -errno; -+ RUN_WITH_UMASK(~m & 0777) { -+ r = mac_selinux_bind(fd, &sockaddr.sa, sockaddr_len); -+ if (r < 0) -+ return r; -+ } - - if (listen(fd, SOMAXCONN) < 0) - return -errno; -diff --git a/src/shared/varlink.h b/src/shared/varlink.h -index 7440f2c..06a34b4 100644 ---- a/src/shared/varlink.h -+++ b/src/shared/varlink.h -@@ -100,6 +100,7 @@ int varlink_replyb(Varlink *v, ...); - int varlink_error(Varlink *v, const char *error_id, JsonVariant *parameters); - int varlink_errorb(Varlink *v, const char *error_id, ...); - int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters); -+int varlink_error_errno(Varlink *v, int error); - - /* Enqueue a "more" reply */ - int varlink_notify(Varlink *v, JsonVariant *parameters); -diff --git a/src/shared/vlan-util.c b/src/shared/vlan-util.c -index a4b42df..180f56e 100644 ---- a/src/shared/vlan-util.c -+++ b/src/shared/vlan-util.c -@@ -86,11 +86,13 @@ int config_parse_vlanid( - - r = parse_vlanid(rvalue, id); - if (r == -ERANGE) { -- log_syntax(unit, LOG_ERR, filename, line, r, "VLAN identifier outside of valid range 0…4094, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "VLAN identifier outside of valid range 0…4094, ignoring: %s", rvalue); - return 0; - } - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VLAN identifier value, ignoring: %s", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse VLAN identifier value, ignoring: %s", rvalue); - return 0; - } - -diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c -index 7029352..6bb1a04 100644 ---- a/src/sleep/sleep.c -+++ b/src/sleep/sleep.c -@@ -160,17 +160,13 @@ static int lock_all_homes(void) { - - r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC, &error, NULL); - if (r < 0) { -- if (sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN) || -- sd_bus_error_has_name(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER)) { -- log_debug("systemd-homed is not running, skipping locking of home directories."); -- return 0; -- } -+ if (!bus_error_is_unknown_service(&error)) -+ return log_error_errno(r, "Failed to lock home directories: %s", bus_error_message(&error, r)); - -- return log_error_errno(r, "Failed to lock home directories: %s", bus_error_message(&error, r)); -+ return log_debug("systemd-homed is not running, locking of home directories skipped."); - } - -- log_debug("Successfully requested for all home directories to be locked."); -- return 0; -+ return log_debug("Successfully requested locking of all home directories."); - } - - static int execute(char **modes, char **states) { -diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c -index b461aea..6042014 100644 ---- a/src/socket-proxy/socket-proxyd.c -+++ b/src/socket-proxy/socket-proxyd.c -@@ -95,16 +95,14 @@ static int idle_time_cb(sd_event_source *s, uint64_t usec, void *userdata) { - } - - static int connection_release(Connection *c) { -- int r; - Context *context = c->context; -- usec_t idle_instant; -+ int r; - - connection_free(c); - - if (arg_exit_idle_time < USEC_INFINITY && set_isempty(context->connections)) { -- idle_instant = usec_add(now(CLOCK_MONOTONIC), arg_exit_idle_time); - if (context->idle_time) { -- r = sd_event_source_set_time(context->idle_time, idle_instant); -+ r = sd_event_source_set_time_relative(context->idle_time, arg_exit_idle_time); - if (r < 0) - return log_error_errno(r, "Error while setting idle time: %m"); - -@@ -112,8 +110,9 @@ static int connection_release(Connection *c) { - if (r < 0) - return log_error_errno(r, "Error while enabling idle time: %m"); - } else { -- r = sd_event_add_time(context->event, &context->idle_time, CLOCK_MONOTONIC, -- idle_instant, 0, idle_time_cb, context); -+ r = sd_event_add_time_relative( -+ context->event, &context->idle_time, CLOCK_MONOTONIC, -+ arg_exit_idle_time, 0, idle_time_cb, context); - if (r < 0) - return log_error_errno(r, "Failed to create idle timer: %m"); - } -@@ -418,7 +417,6 @@ static int resolve_remote(Connection *c) { - static const struct addrinfo hints = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, -- .ai_flags = AI_ADDRCONFIG - }; - - const char *node, *service; -diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c -index 5274cd2..e44a043 100644 ---- a/src/sysctl/sysctl.c -+++ b/src/sysctl/sysctl.c -@@ -119,10 +119,9 @@ static int sysctl_write_or_warn(const char *key, const char *value, bool ignore_ - - static int apply_all(OrderedHashmap *sysctl_options) { - Option *option; -- Iterator i; - int r = 0; - -- ORDERED_HASHMAP_FOREACH(option, sysctl_options, i) { -+ ORDERED_HASHMAP_FOREACH(option, sysctl_options) { - int k; - - /* Ignore "negative match" options, they are there only to exclude stuff from globs. */ -diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c -index c58a19a..115983f 100644 ---- a/src/systemctl/systemctl.c -+++ b/src/systemctl/systemctl.c -@@ -81,6 +81,7 @@ - #include "stat-util.h" - #include "string-table.h" - #include "strv.h" -+#include "syslog-util.h" - #include "sysv-compat.h" - #include "terminal-util.h" - #include "tmpfile-util.h" -@@ -170,6 +171,7 @@ static bool arg_now = false; - static bool arg_jobs_before = false; - static bool arg_jobs_after = false; - static char **arg_clean_what = NULL; -+static TimestampStyle arg_timestamp_style = TIMESTAMP_PRETTY; - - /* This is a global cache that will be constructed on first use. */ - static Hashmap *cached_id_map = NULL; -@@ -278,17 +280,17 @@ static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) - if (!sd_bus_error_is_set(error)) - return r; - -- if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) || -- sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) || -- sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) || -- sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE)) -+ if (sd_bus_error_has_names(error, SD_BUS_ERROR_ACCESS_DENIED, -+ BUS_ERROR_ONLY_BY_DEPENDENCY, -+ BUS_ERROR_NO_ISOLATION, -+ BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE)) - return EXIT_NOPERMISSION; - - if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT)) - return EXIT_NOTINSTALLED; - -- if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) || -- sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED)) -+ if (sd_bus_error_has_names(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, -+ SD_BUS_ERROR_NOT_SUPPORTED)) - return EXIT_NOTIMPLEMENTED; - - if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) -@@ -551,8 +553,8 @@ static int get_unit_list( - return bus_log_create_error(r); - - r = sd_bus_call(bus, m, 0, &error, &reply); -- if (r < 0 && (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD) || -- sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED))) { -+ if (r < 0 && (sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD, -+ SD_BUS_ERROR_ACCESS_DENIED))) { - /* Fallback to legacy ListUnitsFiltered method */ - fallback = true; - log_debug_errno(r, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error, r)); -@@ -1063,7 +1065,7 @@ static int list_sockets(int argc, char *argv[], void *userdata) { - struct socket_info *s; - unsigned cs = 0; - size_t size = 0; -- int r = 0, n; -+ int r, n; - sd_bus *bus; - - r = acquire_bus(BUS_MANAGER, &bus); -@@ -1332,7 +1334,7 @@ static int list_timers(int argc, char *argv[], void *userdata) { - int n, c = 0; - dual_timestamp nw; - sd_bus *bus; -- int r = 0; -+ int r; - - r = acquire_bus(BUS_MANAGER, &bus); - if (r < 0) -@@ -1545,7 +1547,6 @@ static int list_unit_files(int argc, char *argv[], void *userdata) { - if (install_client_side()) { - Hashmap *h; - UnitFileList *u; -- Iterator i; - unsigned n_units; - - h = hashmap_new(&string_hash_ops); -@@ -1566,7 +1567,7 @@ static int list_unit_files(int argc, char *argv[], void *userdata) { - return log_oom(); - } - -- HASHMAP_FOREACH(u, h, i) { -+ HASHMAP_FOREACH(u, h) { - if (!output_show_unit_file(u, NULL, NULL)) - continue; - -@@ -1730,7 +1731,7 @@ static int list_dependencies_one( - - _cleanup_strv_free_ char **deps = NULL; - char **c; -- int r = 0; -+ int r; - - assert(bus); - assert(name); -@@ -2085,8 +2086,10 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat - if (streq(key, "systemd.unit")) { - if (proc_cmdline_value_missing(key, value)) - return 0; -- if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) -- return log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value); -+ if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { -+ log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value); -+ return 0; -+ } - - return free_and_strdup_warn(ret, key); - -@@ -2396,7 +2399,7 @@ static int list_jobs(int argc, char *argv[], void *userdata) { - static int cancel_job(int argc, char *argv[], void *userdata) { - sd_bus *bus; - char **name; -- int r = 0; -+ int r; - - if (argc <= 1) - return trivial_method(argc, argv, userdata); -@@ -2944,9 +2947,9 @@ fail: - - log_error_errno(r, "Failed to %s %s: %s", job_type, name, bus_error_message(error, r)); - -- if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) && -- !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED) && -- !sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE)) -+ if (!sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT, -+ BUS_ERROR_UNIT_MASKED, -+ BUS_ERROR_JOB_TYPE_NOT_APPLICABLE)) - log_error("See %s logs and 'systemctl%s status%s %s' for details.", - arg_scope == UNIT_FILE_SYSTEM ? "system" : "user", - arg_scope == UNIT_FILE_SYSTEM ? "" : " --user", -@@ -4195,7 +4198,7 @@ static void print_status_info( - i->active_exit_timestamp; - - s1 = format_timestamp_relative(since1, sizeof(since1), timestamp); -- s2 = format_timestamp(since2, sizeof(since2), timestamp); -+ s2 = format_timestamp_style(since2, sizeof(since2), timestamp, arg_timestamp_style); - - if (s1) - printf(" since %s; %s\n", s2, s1); -@@ -4229,7 +4232,7 @@ static void print_status_info( - dual_timestamp_get(&nw); - next_elapse = calc_next_elapse(&nw, &next); - next_rel_time = format_timestamp_relative(tstamp1, sizeof tstamp1, next_elapse); -- next_time = format_timestamp(tstamp2, sizeof tstamp2, next_elapse); -+ next_time = format_timestamp_style(tstamp2, sizeof tstamp2, next_elapse, arg_timestamp_style); - - if (next_time && next_rel_time) - printf("%s; %s\n", next_time, next_rel_time); -@@ -4254,7 +4257,7 @@ static void print_status_info( - int n = 0; - - s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp); -- s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp); -+ s2 = format_timestamp_style(since2, sizeof(since2), i->condition_timestamp, arg_timestamp_style); - - printf(" Condition: start %scondition failed%s at %s%s%s\n", - ansi_highlight_yellow(), ansi_normal(), -@@ -4276,7 +4279,7 @@ static void print_status_info( - - if (!i->assert_result && i->assert_timestamp > 0) { - s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp); -- s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp); -+ s2 = format_timestamp_style(since2, sizeof(since2), i->assert_timestamp, arg_timestamp_style); - - printf(" Assert: start %sassertion failed%s at %s%s%s\n", - ansi_highlight_red(), ansi_normal(), -@@ -4819,7 +4822,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m - - return 1; - -- } else if (STR_IN_SET(name, "SystemCallFilter", "RestrictAddressFamilies")) { -+ } else if (STR_IN_SET(name, "SystemCallFilter", "SystemCallLog", "RestrictAddressFamilies")) { - _cleanup_strv_free_ char **l = NULL; - int allow_list; - -@@ -5037,7 +5040,7 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m - while ((r = sd_bus_message_read(m, "(sst)", &base, &spec, &next_elapse)) > 0) { - char timestamp[FORMAT_TIMESTAMP_MAX] = "n/a"; - -- (void) format_timestamp(timestamp, sizeof(timestamp), next_elapse); -+ (void) format_timestamp_style(timestamp, sizeof(timestamp), next_elapse, arg_timestamp_style); - bus_print_property_valuef(name, expected_value, value, - "{ %s=%s ; next_elapse=%s }", base, spec, timestamp); - } -@@ -5077,8 +5080,8 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m - strna(info.path), - strna(tt), - strna(o), -- strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)), -- strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)), -+ strna(format_timestamp_style(timestamp1, sizeof(timestamp1), info.start_timestamp, arg_timestamp_style)), -+ strna(format_timestamp_style(timestamp2, sizeof(timestamp2), info.exit_timestamp, arg_timestamp_style)), - info.pid, - sigchld_code_to_string(info.code), - info.status, -@@ -5090,8 +5093,8 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m - strna(info.path), - strna(tt), - yes_no(info.ignore), -- strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)), -- strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)), -+ strna(format_timestamp_style(timestamp1, sizeof(timestamp1), info.start_timestamp, arg_timestamp_style)), -+ strna(format_timestamp_style(timestamp2, sizeof(timestamp2), info.exit_timestamp, arg_timestamp_style)), - info.pid, - sigchld_code_to_string(info.code), - info.status, -@@ -5408,6 +5411,71 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m - bus_print_property_value(name, expected_value, value, affinity); - - return 1; -+ } else if (streq(name, "MountImages")) { -+ _cleanup_free_ char *paths = NULL; -+ -+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssba(ss))"); -+ if (r < 0) -+ return bus_log_parse_error(r); -+ -+ for (;;) { -+ _cleanup_free_ char *str = NULL; -+ const char *source, *destination, *partition, *mount_options; -+ int ignore_enoent; -+ -+ r = sd_bus_message_enter_container(m, 'r', "ssba(ss)"); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_read(m, "ssb", &source, &destination, &ignore_enoent); -+ if (r <= 0) -+ break; -+ -+ str = strjoin(ignore_enoent ? "-" : "", -+ source, -+ ":", -+ destination); -+ if (!str) -+ return log_oom(); -+ -+ r = sd_bus_message_enter_container(m, 'a', "(ss)"); -+ if (r < 0) -+ return r; -+ -+ while ((r = sd_bus_message_read(m, "(ss)", &partition, &mount_options)) > 0) { -+ _cleanup_free_ char *previous = NULL; -+ -+ previous = TAKE_PTR(str); -+ str = strjoin(strempty(previous), previous ? ":" : "", partition, ":", mount_options); -+ if (!str) -+ return log_oom(); -+ } -+ if (r < 0) -+ return r; -+ -+ if (!strextend_with_separator(&paths, " ", str, NULL)) -+ return log_oom(); -+ -+ r = sd_bus_message_exit_container(m); -+ if (r < 0) -+ return r; -+ -+ r = sd_bus_message_exit_container(m); -+ if (r < 0) -+ return r; -+ } -+ if (r < 0) -+ return bus_log_parse_error(r); -+ -+ r = sd_bus_message_exit_container(m); -+ if (r < 0) -+ return bus_log_parse_error(r); -+ -+ if (all || !isempty(paths)) -+ bus_print_property_value(name, expected_value, value, strempty(paths)); -+ -+ return 1; -+ - } - - break; -@@ -5721,7 +5789,7 @@ static int show_system_status(sd_bus *bus) { - printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units); - - printf(" Since: %s; %s\n", -- format_timestamp(since2, sizeof(since2), mi.timestamp), -+ format_timestamp_style(since2, sizeof(since2), mi.timestamp, arg_timestamp_style), - format_timestamp_relative(since1, sizeof(since1), mi.timestamp)); - - printf(" CGroup: %s\n", mi.control_group ?: "/"); -@@ -6231,64 +6299,141 @@ static int switch_root(int argc, char *argv[], void *userdata) { - return 0; - } - --static int log_level(int argc, char *argv[], void *userdata) { -- sd_bus *bus; -- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -- int r; -+static void give_log_control1_hint(const char *name) { -+ _cleanup_free_ char *link = NULL; - -- r = acquire_bus(BUS_MANAGER, &bus); -- if (r < 0) -- return r; -+ if (arg_quiet) -+ return; - -- if (argc == 1) { -- _cleanup_free_ char *level = NULL; -+ (void) terminal_urlify_man("org.freedesktop.LogControl1", "5", &link); - -- r = bus_get_property_string(bus, bus_systemd_mgr, "LogLevel", &error, &level); -- if (r < 0) -- return log_error_errno(r, "Failed to get log level: %s", bus_error_message(&error, r)); -+ log_notice("Hint: the service must declare BusName= and implement the appropriate D-Bus interface.\n" -+ " See the %s for details.", link ?: "org.freedesktop.LogControl1(5) man page"); -+} -+ -+static int log_setting_internal(sd_bus *bus, const BusLocator* bloc, const char *verb, const char *value) { -+ assert(bus); -+ assert(STR_IN_SET(verb, "log-level", "log-target", "service-log-level", "service-log-target")); -+ -+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -+ bool level = endswith(verb, "log-level"); -+ int r; - -- puts(level); -+ if (value) { -+ if (level) { -+ if (log_level_from_string(value) < 0) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "\"%s\" is not a valid log level.", value); -+ } -+ -+ r = bus_set_property(bus, bloc, -+ level ? "LogLevel" : "LogTarget", -+ &error, "s", value); -+ if (r >= 0) -+ return 0; - -+ log_error_errno(r, "Failed to set log %s of %s to %s: %s", -+ level ? "level" : "target", -+ bloc->destination, value, bus_error_message(&error, r)); - } else { -- assert(argc == 2); -+ _cleanup_free_ char *t = NULL; - -- r = bus_set_property(bus, bus_systemd_mgr, "LogLevel", &error, "s", argv[1]); -- if (r < 0) -- return log_error_errno(r, "Failed to set log level: %s", bus_error_message(&error, r)); -+ r = bus_get_property_string(bus, bloc, -+ level ? "LogLevel" : "LogTarget", -+ &error, &t); -+ if (r >= 0) { -+ puts(t); -+ return 0; -+ } -+ -+ log_error_errno(r, "Failed to get log %s of %s: %s", -+ level ? "level" : "target", -+ bloc->destination, bus_error_message(&error, r)); - } - -- return 0; -+ if (sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD, -+ SD_BUS_ERROR_UNKNOWN_OBJECT, -+ SD_BUS_ERROR_UNKNOWN_INTERFACE, -+ SD_BUS_ERROR_UNKNOWN_PROPERTY)) -+ give_log_control1_hint(bloc->destination); -+ return r; - } - --static int log_target(int argc, char *argv[], void *userdata) { -+static int log_setting(int argc, char *argv[], void *userdata) { - sd_bus *bus; -- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - int r; - -+ assert(argc >= 1 && argc <= 2); -+ - r = acquire_bus(BUS_MANAGER, &bus); - if (r < 0) - return r; - -- if (argc == 1) { -- _cleanup_free_ char *target = NULL; -+ return log_setting_internal(bus, bus_systemd_mgr, argv[0], argv[1]); -+} - -- r = bus_get_property_string(bus, bus_systemd_mgr, "LogTarget", &error, &target); -- if (r < 0) -- return log_error_errno(r, "Failed to get log target: %s", bus_error_message(&error, r)); -+static int service_name_to_dbus(sd_bus *bus, const char *name, char **ret_dbus_name) { -+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -+ _cleanup_free_ char *bus_name = NULL; -+ int r; - -- puts(target); -+ /* First, look for the BusName= property */ -+ _cleanup_free_ char *dbus_path = unit_dbus_path_from_name(name); -+ if (!dbus_path) -+ return log_oom(); - -- } else { -- assert(argc == 2); -+ r = sd_bus_get_property_string( -+ bus, -+ "org.freedesktop.systemd1", -+ dbus_path, -+ "org.freedesktop.systemd1.Service", -+ "BusName", -+ &error, -+ &bus_name); -+ if (r < 0) -+ return log_error_errno(r, "Failed to obtain BusName= property of %s: %s", -+ name, bus_error_message(&error, r)); - -- r = bus_set_property(bus, bus_systemd_mgr, "LogTarget", &error, "s", argv[1]); -- if (r < 0) -- return log_error_errno(r, "Failed to set log target: %s", bus_error_message(&error, r)); -+ if (isempty(bus_name)) { -+ log_error("Unit %s doesn't declare BusName=.", name); -+ give_log_control1_hint(name); -+ return -ENOLINK; - } - -+ *ret_dbus_name = TAKE_PTR(bus_name); - return 0; - } - -+static int service_log_setting(int argc, char *argv[], void *userdata) { -+ sd_bus *bus; -+ _cleanup_free_ char *unit = NULL, *dbus_name = NULL; -+ int r; -+ -+ assert(argc >= 2 && argc <= 3); -+ -+ r = acquire_bus(BUS_FULL, &bus); -+ if (r < 0) -+ return r; -+ -+ r = unit_name_mangle_with_suffix(argv[1], argv[0], -+ arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, -+ ".service", &unit); -+ if (r < 0) -+ return log_error_errno(r, "Failed to mangle unit name: %m"); -+ -+ r = service_name_to_dbus(bus, unit, &dbus_name); -+ if (r < 0) -+ return r; -+ -+ const BusLocator bloc = { -+ .destination = dbus_name, -+ .path = "/org/freedesktop/LogControl1", -+ .interface = "org.freedesktop.LogControl1", -+ }; -+ -+ return log_setting_internal(bus, &bloc, argv[0], argv[2]); -+} -+ - static int service_watchdogs(int argc, char *argv[], void *userdata) { - sd_bus *bus; - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; -@@ -6907,7 +7052,7 @@ static int add_dependency(int argc, char *argv[], void *userdata) { - UnitFileChange *changes = NULL; - size_t n_changes = 0; - UnitDependency dep; -- int r = 0; -+ int r; - - if (!argv[1]) - return 0; -@@ -7247,19 +7392,30 @@ static int create_edit_temp_file(const char *new_path, const char *original_path - if (r < 0) - return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path); - -- r = mkdir_parents(new_path, 0755); -+ r = mkdir_parents_label(new_path, 0755); - if (r < 0) - return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path); - -+ r = mac_selinux_create_file_prepare(original_path, S_IFREG); -+ if (r < 0) -+ return r; -+ - r = copy_file(original_path, t, 0, 0644, 0, 0, COPY_REFLINK); - if (r == -ENOENT) { - - r = touch(t); -+ -+ mac_selinux_create_file_clear(); -+ - if (r < 0) - return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t); - -- } else if (r < 0) -- return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path); -+ } else { -+ mac_selinux_create_file_clear(); -+ -+ if (r < 0) -+ return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path); -+ } - - *ret_tmp_fn = TAKE_PTR(t); - -@@ -7538,6 +7694,10 @@ static int edit(int argc, char *argv[], void *userdata) { - if (r < 0) - return log_error_errno(r, "Failed to determine unit paths: %m"); - -+ r = mac_selinux_init(); -+ if (r < 0) -+ return r; -+ - r = acquire_bus(BUS_MANAGER, &bus); - if (r < 0) - return r; -@@ -7626,6 +7786,16 @@ static int systemctl_help(void) { - " ordered by address\n" - " list-timers [PATTERN...] List timer units currently in memory,\n" - " ordered by next elapse\n" -+ " is-active PATTERN... Check whether units are active\n" -+ " is-failed PATTERN... Check whether units are failed\n" -+ " status [PATTERN...|PID...] Show runtime status of one or more units\n" -+ " show [PATTERN...|JOB...] Show properties of one or more\n" -+ " units/jobs or the manager\n" -+ " cat PATTERN... Show files and drop-ins of specified units\n" -+ " help PATTERN...|PID... Show manual for one or more units\n" -+ " list-dependencies [UNIT...] Recursively show units which are required\n" -+ " or wanted by the units or by which those\n" -+ " units are required or wanted\n" - " start UNIT... Start (activate) one or more units\n" - " stop UNIT... Stop (deactivate) one or more units\n" - " reload UNIT... Reload one or more units\n" -@@ -7641,19 +7811,11 @@ static int systemctl_help(void) { - " configuration of unit\n" - " freeze PATTERN... Freeze execution of unit processes\n" - " thaw PATTERN... Resume execution of a frozen unit\n" -- " is-active PATTERN... Check whether units are active\n" -- " is-failed PATTERN... Check whether units are failed\n" -- " status [PATTERN...|PID...] Show runtime status of one or more units\n" -- " show [PATTERN...|JOB...] Show properties of one or more\n" -- " units/jobs or the manager\n" -- " cat PATTERN... Show files and drop-ins of specified units\n" - " set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n" -- " help PATTERN...|PID... Show manual for one or more units\n" -+ " service-log-level SERVICE [LEVEL] Get/set logging threshold for service\n" -+ " service-log-target SERVICE [TARGET] Get/set logging target for service\n" - " reset-failed [PATTERN...] Reset failed state for all, one, or more\n" -- " units\n" -- " list-dependencies [UNIT...] Recursively show units which are required\n" -- " or wanted by the units or by which those\n" -- " units are required or wanted" -+ " units" - "\n%3$sUnit File Commands:%4$s\n" - " list-unit-files [PATTERN...] List installed unit files\n" - " enable [UNIT...|PATH...] Enable one or more unit files\n" -@@ -7718,7 +7880,7 @@ static int systemctl_help(void) { - " -M --machine=CONTAINER Operate on a local container\n" - " -t --type=TYPE List units of a particular type\n" - " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n" -- " --failed Shorcut for --state=failed\n" -+ " --failed Shortcut for --state=failed\n" - " -p --property=NAME Show only properties by this name\n" - " -P NAME Equivalent to --value --property=NAME\n" - " -a --all Show all properties/all units currently in memory,\n" -@@ -7771,6 +7933,11 @@ static int systemctl_help(void) { - " --boot-loader-entry=NAME\n" - " Boot into a specific boot loader entry on next boot\n" - " --plain Print unit dependencies as a list instead of a tree\n" -+ " --timestamp=FORMAT Change format of printed timestamps.\n" -+ " 'pretty' (default): 'Day YYYY-MM-DD HH:MM:SS TZ\n" -+ " 'us': 'Day YYYY-MM-DD HH:MM:SS.UUUUUU TZ\n" -+ " 'utc': 'Day YYYY-MM-DD HH:MM:SS UTC\n" -+ " 'us+utc': 'Day YYYY-MM-DD HH:MM:SS.UUUUUU UTC\n" - "\nSee the %2$s for details.\n" - , program_invocation_short_name - , link -@@ -8019,6 +8186,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { - ARG_WAIT, - ARG_WHAT, - ARG_REBOOT_ARG, -+ ARG_TIMESTAMP_STYLE, - }; - - static const struct option options[] = { -@@ -8073,6 +8241,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { - { "show-transaction", no_argument, NULL, 'T' }, - { "what", required_argument, NULL, ARG_WHAT }, - { "reboot-argument", required_argument, NULL, ARG_REBOOT_ARG }, -+ { "timestamp", required_argument, NULL, ARG_TIMESTAMP_STYLE }, - {} - }; - -@@ -8472,6 +8641,19 @@ static int systemctl_parse_argv(int argc, char *argv[]) { - arg_reboot_argument = optarg; - break; - -+ case ARG_TIMESTAMP_STYLE: -+ if (streq(optarg, "help")) { -+ DUMP_STRING_TABLE(timestamp_style, TimestampStyle, _TIMESTAMP_STYLE_MAX); -+ return 0; -+ } -+ -+ arg_timestamp_style = timestamp_style_from_string(optarg); -+ if (arg_timestamp_style < 0) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "Invalid value: %s.", optarg); -+ -+ break; -+ - case '.': - /* Output an error mimicking getopt, and print a hint afterwards */ - log_error("%s: invalid option -- '.'", program_invocation_name); -@@ -8930,8 +9112,10 @@ static int systemctl_main(int argc, char *argv[]) { - { "help", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show }, - { "daemon-reload", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload }, - { "daemon-reexec", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload }, -- { "log-level", VERB_ANY, 2, VERB_ONLINE_ONLY, log_level }, -- { "log-target", VERB_ANY, 2, VERB_ONLINE_ONLY, log_target }, -+ { "log-level", VERB_ANY, 2, VERB_ONLINE_ONLY, log_setting }, -+ { "log-target", VERB_ANY, 2, VERB_ONLINE_ONLY, log_setting }, -+ { "service-log-level", 2, 3, VERB_ONLINE_ONLY, service_log_setting }, -+ { "service-log-target", 2, 3, VERB_ONLINE_ONLY, service_log_setting }, - { "service-watchdogs", VERB_ANY, 2, VERB_ONLINE_ONLY, service_watchdogs }, - { "show-environment", VERB_ANY, 1, VERB_ONLINE_ONLY, show_environment }, - { "set-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment }, -@@ -9097,7 +9281,7 @@ static int logind_schedule_shutdown(void) { - return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r)); - - if (!arg_quiet) -- log_info("%s scheduled for %s, use 'shutdown -c' to cancel.", log_action, format_timestamp(date, sizeof(date), arg_when)); -+ log_info("%s scheduled for %s, use 'shutdown -c' to cancel.", log_action, format_timestamp_style(date, sizeof(date), arg_when, arg_timestamp_style)); - return 0; - #else - return log_error_errno(SYNTHETIC_ERRNO(ENOSYS), -diff --git a/src/systemd/_sd-common.h b/src/systemd/_sd-common.h -index 8158ee7..1055b00 100644 ---- a/src/systemd/_sd-common.h -+++ b/src/systemd/_sd-common.h -@@ -19,7 +19,7 @@ - - /* This is a private header; never even think of including this directly! */ - --#if defined(__INCLUDE_LEVEL__) && __INCLUDE_LEVEL__ <= 1 -+#if defined(__INCLUDE_LEVEL__) && __INCLUDE_LEVEL__ <= 1 && !defined(__COVERITY__) - # error "Do not include _sd-common.h directly; it is a private header." - #endif - -diff --git a/src/systemd/sd-bus-protocol.h b/src/systemd/sd-bus-protocol.h -index a3f4e74..8883ec6 100644 ---- a/src/systemd/sd-bus-protocol.h -+++ b/src/systemd/sd-bus-protocol.h -@@ -94,6 +94,12 @@ enum { - #define SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED \ - "org.freedesktop.DBus.Error.InteractiveAuthorizationRequired" - -+/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-signature */ -+#define SD_BUS_MAXIMUM_SIGNATURE_LENGTH 255 -+ -+/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names */ -+#define SD_BUS_MAXIMUM_NAME_LENGTH 255 -+ - _SD_END_DECLARATIONS; - - #endif -diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h -index d4b6bef..9c37e7e 100644 ---- a/src/systemd/sd-bus.h -+++ b/src/systemd/sd-bus.h -@@ -34,12 +34,6 @@ _SD_BEGIN_DECLARATIONS; - #define SD_BUS_DEFAULT_USER ((sd_bus *) 2) - #define SD_BUS_DEFAULT_SYSTEM ((sd_bus *) 3) - --/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-signature */ --#define SD_BUS_MAXIMUM_SIGNATURE_LENGTH 255 -- --/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names */ --#define SD_BUS_MAXIMUM_NAME_LENGTH 255 -- - /* Types */ - - typedef struct sd_bus sd_bus; -@@ -458,6 +452,8 @@ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e); - int sd_bus_error_move(sd_bus_error *dest, sd_bus_error *e); - int sd_bus_error_is_set(const sd_bus_error *e); - int sd_bus_error_has_name(const sd_bus_error *e, const char *name); -+int sd_bus_error_has_names_sentinel(const sd_bus_error *e, ...) _sd_sentinel_; -+#define sd_bus_error_has_names(e, ...) sd_bus_error_has_names_sentinel(e, __VA_ARGS__, NULL) - - #define SD_BUS_ERROR_MAP(_name, _code) \ - { \ -diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h -index 3c5c88c..53092d2 100644 ---- a/src/systemd/sd-device.h -+++ b/src/systemd/sd-device.h -@@ -64,6 +64,8 @@ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec); - - const char *sd_device_get_tag_first(sd_device *device); - const char *sd_device_get_tag_next(sd_device *device); -+const char *sd_device_get_current_tag_first(sd_device *device); -+const char *sd_device_get_current_tag_next(sd_device *device); - const char *sd_device_get_devlink_first(sd_device *device); - const char *sd_device_get_devlink_next(sd_device *device); - const char *sd_device_get_property_first(sd_device *device, const char **value); -@@ -72,10 +74,12 @@ const char *sd_device_get_sysattr_first(sd_device *device); - const char *sd_device_get_sysattr_next(sd_device *device); - - int sd_device_has_tag(sd_device *device, const char *tag); -+int sd_device_has_current_tag(sd_device *device, const char *tag); - int sd_device_get_property_value(sd_device *device, const char *key, const char **value); - int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value); - - int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *value); -+int sd_device_set_sysattr_valuef(sd_device *device, const char *sysattr, const char *format, ...) _sd_printf_(3, 4); - - /* device enumerator */ - -diff --git a/src/systemd/sd-dhcp6-lease.h b/src/systemd/sd-dhcp6-lease.h -index 4301c6d..240df74 100644 ---- a/src/systemd/sd-dhcp6-lease.h -+++ b/src/systemd/sd-dhcp6-lease.h -@@ -43,6 +43,7 @@ int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **addrs) - int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains); - int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr **addrs); - int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn); -+int sd_dhcp6_lease_get_fqdn(sd_dhcp6_lease *lease, const char **fqdn); - - sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease); - sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease); -diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h -index 2ec726a..dc96bfa 100644 ---- a/src/systemd/sd-event.h -+++ b/src/systemd/sd-event.h -@@ -88,6 +88,7 @@ sd_event* sd_event_unref(sd_event *e); - - int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata); - int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); -+int sd_event_add_time_relative(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); - int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata); - int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata); - int sd_event_add_child_pidfd(sd_event *e, sd_event_source **s, int pidfd, int options, sd_event_child_handler_t callback, void *userdata); -@@ -138,6 +139,7 @@ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events); - int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents); - int sd_event_source_get_time(sd_event_source *s, uint64_t *usec); - int sd_event_source_set_time(sd_event_source *s, uint64_t usec); -+int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec); - int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec); - int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec); - int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock); -diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h -index e18f01b..6a8c206 100644 ---- a/src/systemd/sd-login.h -+++ b/src/systemd/sd-login.h -@@ -180,7 +180,11 @@ int sd_seat_get_active(const char *seat, char **session, uid_t *uid); - - /* Return sessions and users on seat. Returns number of sessions. - * If sessions is NULL, this returns only the number of sessions. */ --int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids); -+int sd_seat_get_sessions( -+ const char *seat, -+ char ***ret_sessions, -+ uid_t **ret_uids, -+ unsigned *ret_n_uids); - - /* Return whether the seat is multi-session capable */ - int sd_seat_can_multi_session(const char *seat) _sd_deprecated_; -@@ -195,7 +199,7 @@ int sd_seat_can_graphical(const char *seat); - int sd_machine_get_class(const char *machine, char **clazz); - - /* Return the list if host-side network interface indices of a machine */ --int sd_machine_get_ifindices(const char *machine, int **ifindices); -+int sd_machine_get_ifindices(const char *machine, int **ret_ifindices); - - /* Get all seats, store in *seats. Returns the number of seats. If - * seats is NULL, this only returns the number of seats. */ -diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h -index a4e9680..05f00ed 100644 ---- a/src/systemd/sd-messages.h -+++ b/src/systemd/sd-messages.h -@@ -140,6 +140,8 @@ _SD_BEGIN_DECLARATIONS; - #define SD_MESSAGE_SYSTEM_UNDOCKED_STR SD_ID128_MAKE_STR(51,e1,71,bd,58,52,48,56,81,10,14,4c,51,7c,ca,53) - #define SD_MESSAGE_POWER_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) - #define SD_MESSAGE_POWER_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) -+#define SD_MESSAGE_REBOOT_KEY SD_ID128_MAKE(9f,a9,d2,c0,12,13,4e,c3,85,45,1f,fe,31,6f,97,d0) -+#define SD_MESSAGE_REBOOT_KEY_STR SD_ID128_MAKE_STR(9f,a9,d2,c0,12,13,4e,c3,85,45,1f,fe,31,6f,97,d0) - #define SD_MESSAGE_SUSPEND_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) - #define SD_MESSAGE_SUSPEND_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) - #define SD_MESSAGE_HIBERNATE_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,73) -diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h -index f919649..ce7ed36 100644 ---- a/src/systemd/sd-netlink.h -+++ b/src/systemd/sd-netlink.h -@@ -216,6 +216,8 @@ int sd_rtnl_message_new_tclass(sd_netlink *rtnl, sd_netlink_message **ret, uint1 - int sd_rtnl_message_set_tclass_parent(sd_netlink_message *m, uint32_t parent); - int sd_rtnl_message_set_tclass_handle(sd_netlink_message *m, uint32_t handle); - -+int sd_rtnl_message_new_mdb(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int mdb_ifindex); -+ - /* genl */ - int sd_genl_socket_open(sd_netlink **nl); - int sd_genl_message_new(sd_netlink *nl, sd_genl_family family, uint8_t cmd, sd_netlink_message **m); -diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c -index b5e7e08..cdfceb2 100644 ---- a/src/sysusers/sysusers.c -+++ b/src/sysusers/sysusers.c -@@ -7,17 +7,19 @@ - #include "conf-files.h" - #include "copy.h" - #include "def.h" -+#include "dissect-image.h" - #include "fd-util.h" - #include "fileio.h" - #include "format-util.h" - #include "fs-util.h" - #include "hashmap.h" - #include "main-func.h" -+#include "mount-util.h" - #include "pager.h" - #include "path-util.h" - #include "pretty-print.h" --#include "set.h" - #include "selinux-util.h" -+#include "set.h" - #include "smack-util.h" - #include "specifier.h" - #include "string-util.h" -@@ -63,6 +65,7 @@ typedef struct Item { - } Item; - - static char *arg_root = NULL; -+static char *arg_image = NULL; - static bool arg_cat_config = false; - static const char *arg_replace = NULL; - static bool arg_inline = false; -@@ -93,6 +96,7 @@ STATIC_DESTRUCTOR_REGISTER(database_by_groupname, hashmap_freep); - STATIC_DESTRUCTOR_REGISTER(database_groups, set_free_freep); - STATIC_DESTRUCTOR_REGISTER(uid_range, freep); - STATIC_DESTRUCTOR_REGISTER(arg_root, freep); -+STATIC_DESTRUCTOR_REGISTER(arg_image, freep); - - static int errno_is_not_exists(int code) { - /* See getpwnam(3) and getgrnam(3): those codes and others can be returned if the user or group are -@@ -353,7 +357,6 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char - _cleanup_fclose_ FILE *original = NULL, *passwd = NULL; - _cleanup_(unlink_and_freep) char *passwd_tmp = NULL; - struct passwd *pw = NULL; -- Iterator iterator; - Item *i; - int r; - -@@ -402,7 +405,7 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char - return -errno; - } - -- ORDERED_HASHMAP_FOREACH(i, todo_uids, iterator) { -+ ORDERED_HASHMAP_FOREACH(i, todo_uids) { - struct passwd n = { - .pw_name = i->name, - .pw_uid = i->uid, -@@ -452,7 +455,6 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char - _cleanup_fclose_ FILE *original = NULL, *shadow = NULL; - _cleanup_(unlink_and_freep) char *shadow_tmp = NULL; - struct spwd *sp = NULL; -- Iterator iterator; - long lstchg; - Item *i; - int r; -@@ -504,7 +506,7 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char - return -errno; - } - -- ORDERED_HASHMAP_FOREACH(i, todo_uids, iterator) { -+ ORDERED_HASHMAP_FOREACH(i, todo_uids) { - struct spwd n = { - .sp_namp = i->name, - .sp_pwdp = (char*) "!*", /* lock this password, and make it invalid */ -@@ -552,7 +554,6 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char ** - _cleanup_(unlink_and_freep) char *group_tmp = NULL; - bool group_changed = false; - struct group *gr = NULL; -- Iterator iterator; - Item *i; - int r; - -@@ -607,7 +608,7 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char ** - return -errno; - } - -- ORDERED_HASHMAP_FOREACH(i, todo_gids, iterator) { -+ ORDERED_HASHMAP_FOREACH(i, todo_gids) { - struct group n = { - .gr_name = i->name, - .gr_gid = i->gid, -@@ -650,7 +651,6 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch - _cleanup_fclose_ FILE *original = NULL, *gshadow = NULL; - _cleanup_(unlink_and_freep) char *gshadow_tmp = NULL; - bool group_changed = false; -- Iterator iterator; - Item *i; - int r; - -@@ -693,7 +693,7 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch - return -errno; - } - -- ORDERED_HASHMAP_FOREACH(i, todo_gids, iterator) { -+ ORDERED_HASHMAP_FOREACH(i, todo_gids) { - struct sgrp n = { - .sg_namp = i->name, - .sg_passwd = (char*) "!!", -@@ -1263,11 +1263,10 @@ DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_hash_ops, char, string_hash_f - - static int add_implicit(void) { - char *g, **l; -- Iterator iterator; - int r; - - /* Implicitly create additional users and groups, if they were listed in "m" lines */ -- ORDERED_HASHMAP_FOREACH_KEY(l, g, members, iterator) { -+ ORDERED_HASHMAP_FOREACH_KEY(l, g, members) { - char **m; - - STRV_FOREACH(m, l) -@@ -1739,6 +1738,7 @@ static int help(void) { - " --version Show package version\n" - " --cat-config Show configuration files\n" - " --root=PATH Operate on an alternate filesystem root\n" -+ " --image=PATH Operate on disk image as filesystem root\n" - " --replace=PATH Treat arguments as replacement for PATH\n" - " --inline Treat arguments as configuration lines\n" - " --no-pager Do not pipe output into a pager\n" -@@ -1756,6 +1756,7 @@ static int parse_argv(int argc, char *argv[]) { - ARG_VERSION = 0x100, - ARG_CAT_CONFIG, - ARG_ROOT, -+ ARG_IMAGE, - ARG_REPLACE, - ARG_INLINE, - ARG_NO_PAGER, -@@ -1766,6 +1767,7 @@ static int parse_argv(int argc, char *argv[]) { - { "version", no_argument, NULL, ARG_VERSION }, - { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, - { "root", required_argument, NULL, ARG_ROOT }, -+ { "image", required_argument, NULL, ARG_IMAGE }, - { "replace", required_argument, NULL, ARG_REPLACE }, - { "inline", no_argument, NULL, ARG_INLINE }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, -@@ -1797,6 +1799,12 @@ static int parse_argv(int argc, char *argv[]) { - return r; - break; - -+ case ARG_IMAGE: -+ r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_image); -+ if (r < 0) -+ return r; -+ break; -+ - case ARG_REPLACE: - if (!path_is_absolute(optarg) || - !endswith(optarg, ".conf")) -@@ -1829,6 +1837,9 @@ static int parse_argv(int argc, char *argv[]) { - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "When --replace= is given, some configuration items must be specified"); - -+ if (arg_image && arg_root) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported."); -+ - return 1; - } - -@@ -1880,8 +1891,10 @@ static int read_config_files(char **args) { - } - - static int run(int argc, char *argv[]) { -+ _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; -+ _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL; -+ _cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL; - _cleanup_close_ int lock = -1; -- Iterator iterator; - Item *i; - int r; - -@@ -1900,6 +1913,23 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return r; - -+ if (arg_image) { -+ assert(!arg_root); -+ -+ r = mount_image_privately_interactively( -+ arg_image, -+ DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK, -+ &unlink_dir, -+ &loop_device, -+ &decrypted_image); -+ if (r < 0) -+ return r; -+ -+ arg_root = strdup(unlink_dir); -+ if (!arg_root) -+ return log_oom(); -+ } -+ - /* If command line arguments are specified along with --replace, read all - * configuration files and insert the positional arguments at the specified - * place. Otherwise, if command line arguments are specified, execute just -@@ -1944,10 +1974,10 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return log_error_errno(r, "Failed to read group database: %m"); - -- ORDERED_HASHMAP_FOREACH(i, groups, iterator) -+ ORDERED_HASHMAP_FOREACH(i, groups) - (void) process_item(i); - -- ORDERED_HASHMAP_FOREACH(i, users, iterator) -+ ORDERED_HASHMAP_FOREACH(i, users) - (void) process_item(i); - - r = write_files(); -diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c -index a2c72d1..7d6be31 100644 ---- a/src/sysv-generator/sysv-generator.c -+++ b/src/sysv-generator/sysv-generator.c -@@ -655,7 +655,6 @@ static int load_sysv(SysvStub *s) { - - static int fix_order(SysvStub *s, Hashmap *all_services) { - SysvStub *other; -- Iterator j; - int r; - - assert(s); -@@ -666,7 +665,7 @@ static int fix_order(SysvStub *s, Hashmap *all_services) { - if (s->sysv_start_priority < 0) - return 0; - -- HASHMAP_FOREACH(other, all_services, j) { -+ HASHMAP_FOREACH(other, all_services) { - if (s == other) - continue; - -@@ -817,7 +816,6 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic - Set *runlevel_services[ELEMENTSOF(rcnd_table)] = {}; - _cleanup_strv_free_ char **sysvrcnd_path = NULL; - SysvStub *service; -- Iterator j; - char **p; - int r; - -@@ -892,7 +890,7 @@ static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_servic - } - - for (unsigned i = 0; i < ELEMENTSOF(rcnd_table); i++) -- SET_FOREACH(service, runlevel_services[i], j) { -+ SET_FOREACH(service, runlevel_services[i]) { - r = strv_extend(&service->before, rcnd_table[i].target); - if (r < 0) { - log_oom(); -@@ -918,7 +916,6 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) - _cleanup_(free_sysvstub_hashmapp) Hashmap *all_services = NULL; - _cleanup_(lookup_paths_free) LookupPaths lp = {}; - SysvStub *service; -- Iterator j; - int r; - - assert_se(arg_dest = dest_late); -@@ -939,10 +936,10 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) - if (r < 0) - return r; - -- HASHMAP_FOREACH(service, all_services, j) -+ HASHMAP_FOREACH(service, all_services) - (void) load_sysv(service); - -- HASHMAP_FOREACH(service, all_services, j) { -+ HASHMAP_FOREACH(service, all_services) { - (void) fix_order(service, all_services); - (void) generate_unit_file(service); - } -diff --git a/src/test/meson.build b/src/test/meson.build -index 132989f..7eb3431 100644 ---- a/src/test/meson.build -+++ b/src/test/meson.build -@@ -421,11 +421,6 @@ tests += [ - [], - '', 'manual'], - -- [['src/test/test-dissect-image.c'], -- [], -- [libblkid], -- '', 'manual'], -- - [['src/test/test-signal-util.c'], - [], - []], -@@ -658,6 +653,10 @@ tests += [ - [], - []], - -+ [['src/test/test-rm-rf.c'], -+ [], -+ []], -+ - [['src/test/test-chase-symlinks.c'], - [], - [], -@@ -753,7 +752,8 @@ tests += [ - librt, - libblkid, - libkmod, -- libacl], -+ libacl, -+ libselinux], - '', 'manual', '-DLOG_REALM=LOG_REALM_UDEV'], - - [['src/test/test-id128.c'], -diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c -index df87974..08764fa 100644 ---- a/src/test/test-acl-util.c -+++ b/src/test/test-acl-util.c -@@ -6,18 +6,23 @@ - #include - - #include "acl-util.h" -+#include "errno-util.h" - #include "fd-util.h" -+#include "format-util.h" - #include "string-util.h" -+#include "tests.h" - #include "tmpfile-util.h" - #include "user-util.h" - --static void test_add_acls_for_user(void) { -+static int test_add_acls_for_user(void) { - char fn[] = "/tmp/test-empty.XXXXXX"; - _cleanup_close_ int fd = -1; - char *cmd; - uid_t uid; - int r; - -+ log_info("/* %s */", __func__); -+ - fd = mkostemp_safe(fn); - assert_se(fd >= 0); - -@@ -38,7 +43,11 @@ static void test_add_acls_for_user(void) { - } else - uid = getuid(); - -- r = add_acls_for_user(fd, uid); -+ r = fd_add_uid_acl_permission(fd, uid, ACL_READ); -+ if (ERRNO_IS_NOT_SUPPORTED(r)) -+ return log_tests_skipped("no ACL support on /tmp"); -+ -+ log_info_errno(r, "fd_add_uid_acl_permission(%i, "UID_FMT", ACL_READ): %m", fd, uid); - assert_se(r >= 0); - - cmd = strjoina("ls -l ", fn); -@@ -49,7 +58,7 @@ static void test_add_acls_for_user(void) { - - /* set the acls again */ - -- r = add_acls_for_user(fd, uid); -+ r = fd_add_uid_acl_permission(fd, uid, ACL_READ); - assert_se(r >= 0); - - cmd = strjoina("ls -l ", fn); -@@ -58,11 +67,10 @@ static void test_add_acls_for_user(void) { - cmd = strjoina("getfacl -p ", fn); - assert_se(system(cmd) == 0); - -- unlink(fn); -+ (void) unlink(fn); -+ return 0; - } - - int main(int argc, char **argv) { -- test_add_acls_for_user(); -- -- return 0; -+ return test_add_acls_for_user(); - } -diff --git a/src/test/test-bitmap.c b/src/test/test-bitmap.c -index f73d36e..b281c1a 100644 ---- a/src/test/test-bitmap.c -+++ b/src/test/test-bitmap.c -@@ -4,7 +4,6 @@ - - int main(int argc, const char *argv[]) { - _cleanup_bitmap_free_ Bitmap *b = NULL, *b2 = NULL; -- Iterator it; - unsigned n = (unsigned) -1, i = 0; - - b = bitmap_new(); -@@ -46,14 +45,14 @@ int main(int argc, const char *argv[]) { - assert_se(bitmap_isset(b, 32) == true); - bitmap_unset(b, 32); - -- BITMAP_FOREACH(n, NULL, it) -+ BITMAP_FOREACH(n, NULL) - assert_not_reached("NULL bitmap"); - - assert_se(bitmap_set(b, 0) == 0); - assert_se(bitmap_set(b, 1) == 0); - assert_se(bitmap_set(b, 256) == 0); - -- BITMAP_FOREACH(n, b, it) { -+ BITMAP_FOREACH(n, b) { - assert_se(n == i); - if (i == 0) - i = 1; -@@ -67,7 +66,7 @@ int main(int argc, const char *argv[]) { - - i = 0; - -- BITMAP_FOREACH(n, b, it) { -+ BITMAP_FOREACH(n, b) { - assert_se(n == i); - if (i == 0) - i = 1; -diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c -index 9e2ae55..d566638 100644 ---- a/src/test/test-calendarspec.c -+++ b/src/test/test-calendarspec.c -@@ -58,7 +58,7 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_ - - u = after; - r = calendar_spec_next_usec(c, after, &u); -- printf("At: %s\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u)); -+ printf("At: %s\n", r < 0 ? strerror_safe(r) : format_timestamp_style(buf, sizeof buf, u, TIMESTAMP_US)); - if (expect != (usec_t)-1) - assert_se(r >= 0 && u == expect); - else -@@ -83,7 +83,7 @@ static void test_timestamp(void) { - - x = now(CLOCK_REALTIME); - -- assert_se(format_timestamp_us(buf, sizeof(buf), x)); -+ assert_se(format_timestamp_style(buf, sizeof(buf), x, TIMESTAMP_US)); - printf("%s\n", buf); - assert_se(calendar_spec_from_string(buf, &c) >= 0); - assert_se(calendar_spec_to_string(c, &t) >= 0); -@@ -104,11 +104,11 @@ static void test_hourly_bug_4031(void) { - n = now(CLOCK_REALTIME); - assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0); - -- printf("Now: %s (%"PRIu64")\n", format_timestamp_us(buf, sizeof buf, n), n); -- printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u), u); -+ printf("Now: %s (%"PRIu64")\n", format_timestamp_style(buf, sizeof buf, n, TIMESTAMP_US), n); -+ printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_style(buf, sizeof buf, u, TIMESTAMP_US), u); - - assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0); -- printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(zaf, sizeof zaf, w), w); -+ printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_style(zaf, sizeof zaf, w, TIMESTAMP_US), w); - - assert_se(n < u); - assert_se(u <= n + USEC_PER_HOUR); -diff --git a/src/test/test-capability.c b/src/test/test-capability.c -index 249323f..2d47c77 100644 ---- a/src/test/test-capability.c -+++ b/src/test/test-capability.c -@@ -7,6 +7,8 @@ - #include - #include - -+#define TEST_CAPABILITY_C -+ - #include "alloc-util.h" - #include "capability-util.h" - #include "errno-util.h" -diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c -index daafba4..27bfcdc 100644 ---- a/src/test/test-cgroup-mask.c -+++ b/src/test/test-cgroup-mask.c -@@ -85,7 +85,7 @@ static int test_cgroup_mask(void) { - ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent_deep), CGROUP_MASK_MEMORY); - ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO)); - ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(nomem_parent), 0); -- ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO)); -+ ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); - ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(root), 0); - - /* Verify aggregation of member masks */ -@@ -94,7 +94,7 @@ static int test_cgroup_mask(void) { - ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(grandchild), 0); - ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent_deep), 0); - ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY)); -- ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO)); -+ ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); - ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_leaf), 0); - ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(root), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); - -@@ -105,7 +105,7 @@ static int test_cgroup_mask(void) { - ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent_deep), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY)); - ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); - ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_parent), (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); -- ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO)); -+ ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); - ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(root), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); - - /* Verify aggregation of target masks. */ -@@ -118,6 +118,16 @@ static int test_cgroup_mask(void) { - ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_leaf), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported)); - ASSERT_CGROUP_MASK(unit_get_target_mask(root), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); - -+ /* Verify aggregation of enable masks. */ -+ ASSERT_CGROUP_MASK(unit_get_enable_mask(son), 0); -+ ASSERT_CGROUP_MASK(unit_get_enable_mask(daughter), 0); -+ ASSERT_CGROUP_MASK(unit_get_enable_mask(grandchild), 0); -+ ASSERT_CGROUP_MASK(unit_get_enable_mask(parent_deep), 0); -+ ASSERT_CGROUP_MASK(unit_get_enable_mask(parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported)); -+ ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported)); -+ ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_leaf), 0); -+ ASSERT_CGROUP_MASK(unit_get_enable_mask(root), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); -+ - return 0; - } - -diff --git a/src/test/test-condition.c b/src/test/test-condition.c -index ddf2e66..d209c13 100644 ---- a/src/test/test-condition.c -+++ b/src/test/test-condition.c -@@ -438,20 +438,6 @@ static void test_condition_test_kernel_version(void) { - condition_free(condition); - } - --static void test_condition_test_null(void) { -- Condition *condition; -- -- condition = condition_new(CONDITION_NULL, NULL, false, false); -- assert_se(condition); -- assert_se(condition_test(condition, environ) > 0); -- condition_free(condition); -- -- condition = condition_new(CONDITION_NULL, NULL, false, true); -- assert_se(condition); -- assert_se(condition_test(condition, environ) == 0); -- condition_free(condition); --} -- - static void test_condition_test_security(void) { - Condition *condition; - -@@ -868,7 +854,6 @@ int main(int argc, char *argv[]) { - test_condition_test_architecture(); - test_condition_test_kernel_command_line(); - test_condition_test_kernel_version(); -- test_condition_test_null(); - test_condition_test_security(); - print_securities(); - test_condition_test_virtualization(); -diff --git a/src/test/test-copy.c b/src/test/test-copy.c -index 0e8d687..6ed655a 100644 ---- a/src/test/test-copy.c -+++ b/src/test/test-copy.c -@@ -81,10 +81,12 @@ static void test_copy_tree(void) { - char original_dir[] = "/tmp/test-copy_tree/"; - char copy_dir[] = "/tmp/test-copy_tree-copy/"; - char **files = STRV_MAKE("file", "dir1/file", "dir1/dir2/file", "dir1/dir2/dir3/dir4/dir5/file"); -- char **links = STRV_MAKE("link", "file", -- "link2", "dir1/file"); -+ char **symlinks = STRV_MAKE("link", "file", -+ "link2", "dir1/file"); -+ char **hardlinks = STRV_MAKE("hlink", "file", -+ "hlink2", "dir1/file"); - const char *unixsockp; -- char **p, **link; -+ char **p, **ll; - struct stat st; - int xattr_worked = -1; /* xattr support is optional in temporary directories, hence use it if we can, - * but don't fail if we can't */ -@@ -110,20 +112,30 @@ static void test_copy_tree(void) { - xattr_worked = k >= 0; - } - -- STRV_FOREACH_PAIR(link, p, links) { -+ STRV_FOREACH_PAIR(ll, p, symlinks) { - _cleanup_free_ char *f, *l; - - assert_se(f = path_join(original_dir, *p)); -- assert_se(l = path_join(original_dir, *link)); -+ assert_se(l = path_join(original_dir, *ll)); - - assert_se(mkdir_parents(l, 0755) >= 0); - assert_se(symlink(f, l) == 0); - } - -+ STRV_FOREACH_PAIR(ll, p, hardlinks) { -+ _cleanup_free_ char *f, *l; -+ -+ assert_se(f = path_join(original_dir, *p)); -+ assert_se(l = path_join(original_dir, *ll)); -+ -+ assert_se(mkdir_parents(l, 0755) >= 0); -+ assert_se(link(f, l) == 0); -+ } -+ - unixsockp = strjoina(original_dir, "unixsock"); - assert_se(mknod(unixsockp, S_IFSOCK|0644, 0) >= 0); - -- assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE) == 0); -+ assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS) == 0); - - STRV_FOREACH(p, files) { - _cleanup_free_ char *buf, *f, *c = NULL; -@@ -147,16 +159,30 @@ static void test_copy_tree(void) { - } - } - -- STRV_FOREACH_PAIR(link, p, links) { -+ STRV_FOREACH_PAIR(ll, p, symlinks) { - _cleanup_free_ char *target, *f, *l; - - assert_se(f = strjoin(original_dir, *p)); -- assert_se(l = strjoin(copy_dir, *link)); -+ assert_se(l = strjoin(copy_dir, *ll)); - - assert_se(chase_symlinks(l, NULL, 0, &target, NULL) == 1); - assert_se(path_equal(f, target)); - } - -+ STRV_FOREACH_PAIR(ll, p, hardlinks) { -+ _cleanup_free_ char *f, *l; -+ struct stat a, b; -+ -+ assert_se(f = strjoin(copy_dir, *p)); -+ assert_se(l = strjoin(copy_dir, *ll)); -+ -+ assert_se(lstat(f, &a) >= 0); -+ assert_se(lstat(l, &b) >= 0); -+ -+ assert_se(a.st_ino == b.st_ino); -+ assert_se(a.st_dev == b.st_dev); -+ } -+ - unixsockp = strjoina(copy_dir, "unixsock"); - assert_se(stat(unixsockp, &st) >= 0); - assert_se(S_ISSOCK(st.st_mode)); -diff --git a/src/test/test-date.c b/src/test/test-date.c -index 7d27cfa..f39eca6 100644 ---- a/src/test/test-date.c -+++ b/src/test/test-date.c -@@ -11,7 +11,7 @@ static void test_should_pass(const char *p) { - - log_info("Test: %s", p); - assert_se(parse_timestamp(p, &t) >= 0); -- assert_se(format_timestamp_us(buf, sizeof(buf), t)); -+ assert_se(format_timestamp_style(buf, sizeof(buf), t, TIMESTAMP_US)); - log_info("\"%s\" → \"%s\"", p, buf); - - assert_se(parse_timestamp(buf, &q) >= 0); -@@ -19,7 +19,7 @@ static void test_should_pass(const char *p) { - char tmp[FORMAT_TIMESTAMP_MAX]; - - log_error("round-trip failed: \"%s\" → \"%s\"", -- buf, format_timestamp_us(tmp, sizeof(tmp), q)); -+ buf, format_timestamp_style(tmp, sizeof(tmp), q, TIMESTAMP_US)); - } - assert_se(q == t); - -diff --git a/src/test/test-dev-setup.c b/src/test/test-dev-setup.c -index 038484e..11196cd 100644 ---- a/src/test/test-dev-setup.c -+++ b/src/test/test-dev-setup.c -@@ -3,6 +3,7 @@ - #include "capability-util.h" - #include "dev-setup.h" - #include "fs-util.h" -+#include "mkdir.h" - #include "path-util.h" - #include "rm-rf.h" - #include "tmpfile-util.h" -@@ -17,8 +18,8 @@ int main(int argc, char *argv[]) { - - assert_se(mkdtemp_malloc("/tmp/test-dev-setupXXXXXX", &p) >= 0); - -- f = prefix_roota(p, "/run"); -- assert_se(mkdir(f, 0755) >= 0); -+ f = prefix_roota(p, "/run/systemd"); -+ assert_se(mkdir_p(f, 0755) >= 0); - - assert_se(make_inaccessible_nodes(f, 1, 1) >= 0); - -diff --git a/src/test/test-dissect-image.c b/src/test/test-dissect-image.c -deleted file mode 100644 -index 13ff8ad..0000000 ---- a/src/test/test-dissect-image.c -+++ /dev/null -@@ -1,51 +0,0 @@ --/* SPDX-License-Identifier: LGPL-2.1+ */ -- --#include --#include --#include -- --#include "dissect-image.h" --#include "log.h" --#include "loop-util.h" --#include "string-util.h" --#include "tests.h" -- --int main(int argc, char *argv[]) { -- _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; -- _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; -- int r, i; -- -- test_setup_logging(LOG_DEBUG); -- -- if (argc < 2) { -- log_error("Requires one command line argument."); -- return EXIT_FAILURE; -- } -- -- r = loop_device_make_by_path(argv[1], O_RDONLY, LO_FLAGS_PARTSCAN, &d); -- if (r < 0) { -- log_error_errno(r, "Failed to set up loopback device: %m"); -- return EXIT_FAILURE; -- } -- -- r = dissect_image(d->fd, NULL, 0, NULL, DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_RELAX_VAR_CHECK, &m); -- if (r < 0) { -- log_error_errno(r, "Failed to dissect image: %m"); -- return EXIT_FAILURE; -- } -- -- for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { -- -- if (!m->partitions[i].found) -- continue; -- -- printf("Found %s partition, %s of type %s at #%i (%s)\n", -- partition_designator_to_string(i), -- m->partitions[i].rw ? "writable" : "read-only", -- strna(m->partitions[i].fstype), -- m->partitions[i].partno, -- strna(m->partitions[i].node)); -- } -- -- return EXIT_SUCCESS; --} -diff --git a/src/test/test-env-file.c b/src/test/test-env-file.c -index 47f86a5..23779b9 100644 ---- a/src/test/test-env-file.c -+++ b/src/test/test-env-file.c -@@ -2,6 +2,7 @@ - - #include "env-file.h" - #include "fd-util.h" -+#include "fileio.h" - #include "fs-util.h" - #include "macro.h" - #include "strv.h" -@@ -132,6 +133,46 @@ static void test_load_env_file_5(void) { - assert_se(data[2] == NULL); - } - -+static void test_write_and_load_env_file(void) { -+ const char *v; -+ -+ /* Make sure that our writer, parser and the shell agree on what our env var files mean */ -+ -+ FOREACH_STRING(v, -+ "obbardc-laptop", -+ "obbardc\\-laptop", -+ "obbardc-lap\\top", -+ "obbardc-lap\\top", -+ "obbardc-lap\\\\top", -+ "double\"quote", -+ "single\'quote", -+ "dollar$dollar", -+ "newline\nnewline") { -+ _cleanup_(unlink_and_freep) char *p = NULL; -+ _cleanup_strv_free_ char **l = NULL; -+ _cleanup_free_ char *j = NULL, *w = NULL, *cmd = NULL, *from_shell = NULL; -+ _cleanup_pclose_ FILE *f = NULL; -+ size_t sz; -+ -+ assert_se(tempfn_random_child(NULL, NULL, &p) >= 0); -+ -+ assert_se(j = strjoin("TEST=", v)); -+ assert_se(write_env_file(p, STRV_MAKE(j)) >= 0); -+ -+ assert_se(cmd = strjoin(". ", p, " && /bin/echo -n \"$TEST\"")); -+ assert_se(f = popen(cmd, "re")); -+ assert_se(read_full_stream(f, &from_shell, &sz) >= 0); -+ assert_se(sz == strlen(v)); -+ assert_se(streq(from_shell, v)); -+ -+ assert_se(load_env_file(NULL, p, &l) >= 0); -+ assert_se(strv_equal(l, STRV_MAKE(j))); -+ -+ assert_se(parse_env_file(NULL, p, "TEST", &w) >= 0); -+ assert_se(streq_ptr(w, v)); -+ } -+} -+ - int main(int argc, char *argv[]) { - test_setup_logging(LOG_INFO); - -@@ -140,4 +181,8 @@ int main(int argc, char *argv[]) { - test_load_env_file_3(); - test_load_env_file_4(); - test_load_env_file_5(); -+ -+ test_write_and_load_env_file(); -+ -+ return 0; - } -diff --git a/src/test/test-execute.c b/src/test/test-execute.c -index 9ca0620..f10e32b 100644 ---- a/src/test/test-execute.c -+++ b/src/test/test-execute.c -@@ -434,6 +434,8 @@ static void test_exec_systemcallfilter(Manager *m) { - test(__func__, m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED); - test(__func__, m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED); - test(__func__, m, "exec-systemcallfilter-with-errno-multi.service", errno_from_name("EILSEQ"), CLD_EXITED); -+ test(__func__, m, "exec-systemcallfilter-override-error-action.service", SIGSYS, CLD_KILLED); -+ test(__func__, m, "exec-systemcallfilter-override-error-action2.service", errno_from_name("EILSEQ"), CLD_EXITED); - #endif - } - -@@ -543,7 +545,29 @@ static void test_exec_supplementarygroups(Manager *m) { - test(__func__, m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED); - } - -+static char* private_directory_bad(Manager *m) { -+ /* This mirrors setup_exec_directory(). */ -+ -+ for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { -+ _cleanup_free_ char *p = NULL; -+ struct stat st; -+ -+ assert_se(p = path_join(m->prefix[dt], "private")); -+ -+ if (stat(p, &st) >= 0 && -+ (st.st_mode & (S_IRWXG|S_IRWXO))) -+ return TAKE_PTR(p); -+ } -+ -+ return NULL; -+} -+ - static void test_exec_dynamicuser(Manager *m) { -+ _cleanup_free_ char *bad = private_directory_bad(m); -+ if (bad) { -+ log_warning("%s: %s has bad permissions, skipping test.", __func__, bad); -+ return; -+ } - - test(__func__, m, "exec-dynamicuser-fixeduser.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); - if (check_user_has_group_with_same_name("adm")) -@@ -554,10 +578,14 @@ static void test_exec_dynamicuser(Manager *m) { - test(__func__, m, "exec-dynamicuser-supplementarygroups.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); - test(__func__, m, "exec-dynamicuser-statedir.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); - -+ (void) rm_rf("/var/lib/quux", REMOVE_ROOT|REMOVE_PHYSICAL); - (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); - (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL); -+ (void) rm_rf("/var/lib/waldo", REMOVE_ROOT|REMOVE_PHYSICAL); -+ (void) rm_rf("/var/lib/private/quux", REMOVE_ROOT|REMOVE_PHYSICAL); - (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); - (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL); -+ (void) rm_rf("/var/lib/private/waldo", REMOVE_ROOT|REMOVE_PHYSICAL); - - test(__func__, m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED); - test(__func__, m, "exec-dynamicuser-statedir-migrate-step2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); -@@ -782,7 +810,6 @@ typedef struct test_entry { - #define entry(x) {x, #x} - - static int run_tests(UnitFileScope scope, const test_entry tests[], char **patterns) { -- const test_entry *test = NULL; - _cleanup_(manager_freep) Manager *m = NULL; - int r; - -@@ -795,7 +822,7 @@ static int run_tests(UnitFileScope scope, const test_entry tests[], char **patte - assert_se(r >= 0); - assert_se(manager_startup(m, NULL, NULL) >= 0); - -- for (test = tests; test && test->f; test++) -+ for (const test_entry *test = tests; test->f; test++) - if (strv_fnmatch_or_empty(patterns, test->name, FNM_NOESCAPE)) - test->f(m); - else -diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c -index 4ca5755..cc1f293 100644 ---- a/src/test/test-extract-word.c -+++ b/src/test/test-extract-word.c -@@ -11,6 +11,8 @@ static void test_extract_first_word(void) { - const char *p, *original; - char *t; - -+ log_info("/* %s */", __func__); -+ - p = original = "foobar waldo"; - assert_se(extract_first_word(&p, &t, NULL, 0) > 0); - assert_se(streq(t, "foobar")); -@@ -341,12 +343,54 @@ static void test_extract_first_word(void) { - assert_se(streq(t, "foo\\xbar")); - free(t); - assert_se(p == NULL); -+ -+ p = "\\:"; -+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1); -+ assert_se(streq(t, ":")); -+ free(t); -+ assert_se(p == NULL); -+ -+ p = "a\\:b"; -+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1); -+ assert_se(streq(t, "a:b")); -+ free(t); -+ assert_se(p == NULL); -+ -+ p = "a\\ b:c"; -+ assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1); -+ assert_se(streq(t, "a b")); -+ free(t); -+ assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1); -+ assert_se(streq(t, "c")); -+ free(t); -+ assert_se(p == NULL); -+ -+ p = "\\:"; -+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE) == -EINVAL); -+ -+ p = "a\\:b"; -+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE) == -EINVAL); -+ assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE) == 1); -+ assert_se(streq(t, "b")); -+ free(t); -+ -+ p = "a\\ b:c"; -+ assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE) == -EINVAL); -+ assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE) == 1); -+ assert_se(streq(t, "b")); -+ free(t); -+ assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE) == 1); -+ assert_se(streq(t, "c")); -+ free(t); -+ assert_se(p == NULL); - } - - static void test_extract_first_word_and_warn(void) { - const char *p, *original; - char *t; - -+ log_info("/* %s */", __func__); -+ - p = original = "foobar waldo"; - assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); - assert_se(streq(t, "foobar")); -@@ -489,7 +533,9 @@ static void test_extract_first_word_and_warn(void) { - - static void test_extract_many_words(void) { - const char *p, *original; -- char *a, *b, *c; -+ char *a, *b, *c, *d, *e, *f; -+ -+ log_info("/* %s */", __func__); - - p = original = "foobar waldi piep"; - assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3); -@@ -501,6 +547,24 @@ static void test_extract_many_words(void) { - free(b); - free(c); - -+ p = original = "foobar:waldi:piep ba1:ba2"; -+ assert_se(extract_many_words(&p, ":" WHITESPACE, 0, &a, &b, &c, NULL) == 3); -+ assert_se(!isempty(p)); -+ assert_se(streq_ptr(a, "foobar")); -+ assert_se(streq_ptr(b, "waldi")); -+ assert_se(streq_ptr(c, "piep")); -+ assert_se(extract_many_words(&p, ":" WHITESPACE, 0, &d, &e, &f, NULL) == 2); -+ assert_se(isempty(p)); -+ assert_se(streq_ptr(d, "ba1")); -+ assert_se(streq_ptr(e, "ba2")); -+ assert_se(isempty(f)); -+ free(a); -+ free(b); -+ free(c); -+ free(d); -+ free(e); -+ free(f); -+ - p = original = "'foobar' wa\"ld\"i "; - assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2); - assert_se(isempty(p)); -diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c -index fb9d397..212fe0d 100644 ---- a/src/test/test-fdset.c -+++ b/src/test/test-fdset.c -@@ -115,7 +115,6 @@ static void test_fdset_iterate(void) { - int fd = -1; - FDSet *fdset = NULL; - char name[] = "/tmp/test-fdset_iterate.XXXXXX"; -- Iterator i; - int c = 0; - int a; - -@@ -128,7 +127,7 @@ static void test_fdset_iterate(void) { - assert_se(fdset_put(fdset, fd) >= 0); - assert_se(fdset_put(fdset, fd) >= 0); - -- FDSET_FOREACH(a, fdset, i) { -+ FDSET_FOREACH(a, fdset) { - c++; - assert_se(a == fd); - } -diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c -index 95dcd4f..ce5af43 100644 ---- a/src/test/test-fileio.c -+++ b/src/test/test-fileio.c -@@ -151,6 +151,18 @@ static void test_parse_env_file(void) { - assert_se(r >= 0); - } - -+static void test_one_shell_var(const char *file, const char *variable, const char *value) { -+ _cleanup_free_ char *cmd = NULL, *from_shell = NULL; -+ _cleanup_pclose_ FILE *f = NULL; -+ size_t sz; -+ -+ assert_se(cmd = strjoin(". ", file, " && /bin/echo -n \"$", variable, "\"")); -+ assert_se(f = popen(cmd, "re")); -+ assert_se(read_full_stream(f, &from_shell, &sz) >= 0); -+ assert_se(sz == strlen(value)); -+ assert_se(streq(from_shell, value)); -+} -+ - static void test_parse_multiline_env_file(void) { - _cleanup_(unlink_tempfilep) char - t[] = "/tmp/test-fileio-in-XXXXXX", -@@ -162,8 +174,8 @@ static void test_parse_multiline_env_file(void) { - - assert_se(fmkostemp_safe(t, "w", &f) == 0); - fputs("one=BAR\\\n" -- " VAR\\\n" -- "\tGAR\n" -+ "\\ \\ \\ \\ VAR\\\n" -+ "\\\tGAR\n" - "#comment\n" - "two=\"bar\\\n" - " var\\\n" -@@ -173,9 +185,13 @@ static void test_parse_multiline_env_file(void) { - " var \\\n" - "\tgar \"\n", f); - -- fflush(f); -+ assert_se(fflush_and_check(f) >= 0); - fclose(f); - -+ test_one_shell_var(t, "one", "BAR VAR\tGAR"); -+ test_one_shell_var(t, "two", "bar var\tgar"); -+ test_one_shell_var(t, "tri", "bar var \tgar "); -+ - r = load_env_file(NULL, t, &a); - assert_se(r >= 0); - -diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c -index dfea70c..f2df2e3 100644 ---- a/src/test/test-fs-util.c -+++ b/src/test/test-fs-util.c -@@ -615,8 +615,8 @@ static void test_touch_file(void) { - assert_se(timespec_load(&st.st_mtim) == test_mtime); - - if (geteuid() == 0) { -- a = strjoina(p, "/cdev"); -- r = mknod(a, 0775 | S_IFCHR, makedev(0, 0)); -+ a = strjoina(p, "/bdev"); -+ r = mknod(a, 0775 | S_IFBLK, makedev(0, 0)); - if (r < 0 && errno == EPERM && detect_container() > 0) { - log_notice("Running in unprivileged container? Skipping remaining tests in %s", __func__); - return; -@@ -626,17 +626,17 @@ static void test_touch_file(void) { - assert_se(lstat(a, &st) >= 0); - assert_se(st.st_uid == test_uid); - assert_se(st.st_gid == test_gid); -- assert_se(S_ISCHR(st.st_mode)); -+ assert_se(S_ISBLK(st.st_mode)); - assert_se((st.st_mode & 0777) == 0640); - assert_se(timespec_load(&st.st_mtim) == test_mtime); - -- a = strjoina(p, "/bdev"); -- assert_se(mknod(a, 0775 | S_IFBLK, makedev(0, 0)) >= 0); -+ a = strjoina(p, "/cdev"); -+ assert_se(mknod(a, 0775 | S_IFCHR, makedev(0, 0)) >= 0); - assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0); - assert_se(lstat(a, &st) >= 0); - assert_se(st.st_uid == test_uid); - assert_se(st.st_gid == test_gid); -- assert_se(S_ISBLK(st.st_mode)); -+ assert_se(S_ISCHR(st.st_mode)); - assert_se((st.st_mode & 0777) == 0640); - assert_se(timespec_load(&st.st_mtim) == test_mtime); - } -@@ -850,11 +850,12 @@ static void test_path_is_encrypted_one(const char *p, int expect) { - int r; - - r = path_is_encrypted(p); -- if (r == -ENOENT) /* This might fail, if btrfs is used and we run in a container. In that case we -- * cannot resolve the device node paths that BTRFS_IOC_DEV_INFO returns, because -- * the device nodes are unlikely to exist in the container. But if we can't stat() -- * them we cannot determine the dev_t of them, and thus cannot figure out if they -- * are enrypted. Hence let's just ignore ENOENT here. */ -+ if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* This might fail, if btrfs is used and we run in a -+ * container. In that case we cannot resolve the device node paths that -+ * BTRFS_IOC_DEV_INFO returns, because the device nodes are unlikely to exist in -+ * the container. But if we can't stat() them we cannot determine the dev_t of -+ * them, and thus cannot figure out if they are enrypted. Hence let's just ignore -+ * ENOENT here. Also skip the test if we lack privileges. */ - return; - assert_se(r >= 0); - -diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c -index 09fe71f..5ff5d09 100644 ---- a/src/test/test-hashmap-plain.c -+++ b/src/test/test-hashmap-plain.c -@@ -469,7 +469,6 @@ static void test_hashmap_ensure_allocated(void) { - - static void test_hashmap_foreach_key(void) { - Hashmap *m; -- Iterator i; - bool key_found[] = { false, false, false, false }; - const char *s; - const char *key; -@@ -486,7 +485,7 @@ static void test_hashmap_foreach_key(void) { - NULSTR_FOREACH(key, key_table) - hashmap_put(m, key, (void*) (const char*) "my dummy val"); - -- HASHMAP_FOREACH_KEY(s, key, m, i) { -+ HASHMAP_FOREACH_KEY(s, key, m) { - assert(s); - if (!key_found[0] && streq(key, "key 1")) - key_found[0] = true; -@@ -506,7 +505,6 @@ static void test_hashmap_foreach_key(void) { - - static void test_hashmap_foreach(void) { - Hashmap *m; -- Iterator i; - bool value_found[] = { false, false, false, false }; - char *val1, *val2, *val3, *val4, *s; - unsigned count; -@@ -525,14 +523,14 @@ static void test_hashmap_foreach(void) { - m = NULL; - - count = 0; -- HASHMAP_FOREACH(s, m, i) -+ HASHMAP_FOREACH(s, m) - count++; - assert_se(count == 0); - - m = hashmap_new(&string_hash_ops); - - count = 0; -- HASHMAP_FOREACH(s, m, i) -+ HASHMAP_FOREACH(s, m) - count++; - assert_se(count == 0); - -@@ -541,7 +539,7 @@ static void test_hashmap_foreach(void) { - hashmap_put(m, "Key 3", val3); - hashmap_put(m, "Key 4", val4); - -- HASHMAP_FOREACH(s, m, i) { -+ HASHMAP_FOREACH(s, m) { - if (!value_found[0] && streq(s, val1)) - value_found[0] = true; - else if (!value_found[1] && streq(s, val2)) -diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c -index 94dbbf1..8527128 100644 ---- a/src/test/test-hashmap.c -+++ b/src/test/test-hashmap.c -@@ -54,7 +54,6 @@ static void test_string_compare_func(void) { - static void compare_cache(Hashmap *map, IteratedCache *cache) { - const void **keys = NULL, **values = NULL; - unsigned num, idx; -- Iterator iter; - void *k, *v; - - assert_se(iterated_cache_get(cache, &keys, &values, &num) == 0); -@@ -62,7 +61,7 @@ static void compare_cache(Hashmap *map, IteratedCache *cache) { - assert_se(num == 0 || values); - - idx = 0; -- HASHMAP_FOREACH_KEY(v, k, map, iter) { -+ HASHMAP_FOREACH_KEY(v, k, map) { - assert_se(v == values[idx]); - assert_se(k == keys[idx]); - -diff --git a/src/test/test-in-addr-util.c b/src/test/test-in-addr-util.c -index 916bd35..a9ecd06 100644 ---- a/src/test/test-in-addr-util.c -+++ b/src/test/test-in-addr-util.c -@@ -58,6 +58,8 @@ static void test_in_addr_prefix_from_string_one( - } - - static void test_in_addr_prefix_from_string(void) { -+ log_info("/* %s */", __func__); -+ - test_in_addr_prefix_from_string_one("", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); - test_in_addr_prefix_from_string_one("/", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); - test_in_addr_prefix_from_string_one("/8", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); -@@ -90,7 +92,7 @@ static void test_in_addr_prefix_to_string_valid(int family, const char *p) { - union in_addr_union u; - unsigned char l; - -- log_info("/* %s */", p); -+ log_info("%s: %s", __func__, p); - - assert_se(in_addr_prefix_from_string(p, family, &u, &l) >= 0); - assert_se(in_addr_prefix_to_string(family, &u, l, &str) >= 0); -@@ -102,7 +104,7 @@ static void test_in_addr_prefix_to_string_unoptimized(int family, const char *p) - union in_addr_union u1, u2; - unsigned char len1, len2; - -- log_info("/* %s */", p); -+ log_info("%s: %s", __func__, p); - - assert_se(in_addr_prefix_from_string(p, family, &u1, &len1) >= 0); - assert_se(in_addr_prefix_to_string(family, &u1, len1, &str1) >= 0); -@@ -115,6 +117,8 @@ static void test_in_addr_prefix_to_string_unoptimized(int family, const char *p) - } - - static void test_in_addr_prefix_to_string(void) { -+ log_info("/* %s */", __func__); -+ - test_in_addr_prefix_to_string_valid(AF_INET, "0.0.0.0/32"); - test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/0"); - test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/24"); -@@ -137,6 +141,8 @@ static void test_in_addr_random_prefix(void) { - _cleanup_free_ char *str = NULL; - union in_addr_union a; - -+ log_info("/* %s */", __func__); -+ - assert_se(in_addr_from_string(AF_INET, "192.168.10.1", &a) >= 0); - - assert_se(in_addr_random_prefix(AF_INET, &a, 31, 32) >= 0); -@@ -177,10 +183,163 @@ static void test_in_addr_random_prefix(void) { - str = mfree(str); - } - -+static void test_in_addr_is_null(void) { -+ union in_addr_union i = {}; -+ -+ log_info("/* %s */", __func__); -+ -+ assert_se(in_addr_is_null(AF_INET, &i) == true); -+ assert_se(in_addr_is_null(AF_INET6, &i) == true); -+ -+ i.in.s_addr = 0x1000000; -+ assert_se(in_addr_is_null(AF_INET, &i) == false); -+ assert_se(in_addr_is_null(AF_INET6, &i) == false); -+ -+ assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT); -+} -+ -+static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) { -+ union in_addr_union ua, ub; -+ -+ assert_se(in_addr_from_string(f, a, &ua) >= 0); -+ assert_se(in_addr_from_string(f, b, &ub) >= 0); -+ -+ assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result); -+} -+ -+static void test_in_addr_prefix_intersect(void) { -+ log_info("/* %s */", __func__); -+ -+ test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0); -+ test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1); -+ test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1); -+ -+ test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1); -+ test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0); -+ -+ test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1); -+ test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1); -+ test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1); -+ test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0); -+ -+ test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", 128, 0); -+ test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1); -+ test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1); -+ -+ test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1); -+ test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0); -+ -+ test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1); -+ test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1); -+ test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1); -+ test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0); -+} -+ -+static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) { -+ union in_addr_union ubefore, uafter, t; -+ -+ assert_se(in_addr_from_string(f, before, &ubefore) >= 0); -+ -+ t = ubefore; -+ assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after); -+ -+ if (after) { -+ assert_se(in_addr_from_string(f, after, &uafter) >= 0); -+ assert_se(in_addr_equal(f, &t, &uafter) > 0); -+ } -+} -+ -+static void test_in_addr_prefix_next(void) { -+ log_info("/* %s */", __func__); -+ -+ test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0"); -+ test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0"); -+ test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0"); -+ -+ test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1"); -+ test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL); -+ test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL); -+ -+ test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001"); -+ test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100"); -+ test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002"); -+ test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::"); -+ test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::"); -+ -+ test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1"); -+ -+ test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL); -+ test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL); -+} -+ -+static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) { -+ union in_addr_union ubefore, uafter, t; -+ -+ assert_se(in_addr_from_string(f, before, &ubefore) >= 0); -+ -+ t = ubefore; -+ assert_se((in_addr_prefix_nth(f, &t, pl, nth) > 0) == !!after); -+ -+ if (after) { -+ assert_se(in_addr_from_string(f, after, &uafter) >= 0); -+ assert_se(in_addr_equal(f, &t, &uafter) > 0); -+ } -+} -+ -+static void test_in_addr_prefix_nth(void) { -+ log_info("/* %s */", __func__); -+ -+ test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0"); -+ test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 1, "192.168.1.0"); -+ test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0"); -+ test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128"); -+ test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128"); -+ test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 24, 0, "192.168.255.0"); -+ test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 32, 1, NULL); -+ test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 0, 1, NULL); -+ -+ test_in_addr_prefix_nth_one(AF_INET6, "4400::", 8, 1, "4500::"); -+ test_in_addr_prefix_nth_one(AF_INET6, "4400::", 7, 1, "4600::"); -+ test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 1, "4400:0:0:1::"); -+ test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 2, "4400:0:0:2::"); -+ test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 0xbad, "4400:0:0:0bad::"); -+ test_in_addr_prefix_nth_one(AF_INET6, "4400:0:0:ffff::", 64, 1, "4400:0:1::"); -+ test_in_addr_prefix_nth_one(AF_INET6, "4400::", 56, ((uint64_t)1<<48) -1, "44ff:ffff:ffff:ff00::"); -+ test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 255, "ff00::"); -+ test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL); -+ test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL); -+ test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL); -+} -+ -+static void test_in_addr_to_string_one(int f, const char *addr) { -+ union in_addr_union ua; -+ _cleanup_free_ char *r = NULL; -+ -+ assert_se(in_addr_from_string(f, addr, &ua) >= 0); -+ assert_se(in_addr_to_string(f, &ua, &r) >= 0); -+ printf("test_in_addr_to_string_one: %s == %s\n", addr, r); -+ assert_se(streq(addr, r)); -+} -+ -+static void test_in_addr_to_string(void) { -+ log_info("/* %s */", __func__); -+ -+ test_in_addr_to_string_one(AF_INET, "192.168.0.1"); -+ test_in_addr_to_string_one(AF_INET, "10.11.12.13"); -+ test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); -+ test_in_addr_to_string_one(AF_INET6, "::1"); -+ test_in_addr_to_string_one(AF_INET6, "fe80::"); -+} -+ - int main(int argc, char *argv[]) { - test_in_addr_prefix_from_string(); - test_in_addr_random_prefix(); - test_in_addr_prefix_to_string(); -+ test_in_addr_is_null(); -+ test_in_addr_prefix_intersect(); -+ test_in_addr_prefix_next(); -+ test_in_addr_prefix_nth(); -+ test_in_addr_to_string(); - - return 0; - } -diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c -index f309160..6fb2fd4 100644 ---- a/src/test/test-install-root.c -+++ b/src/test/test-install-root.c -@@ -548,7 +548,6 @@ static void test_preset_and_list(const char *root) { - const char *p, *q; - UnitFileState state; - bool got_yes = false, got_no = false; -- Iterator j; - UnitFileList *fl; - Hashmap *h; - -@@ -631,7 +630,7 @@ static void test_preset_and_list(const char *root) { - p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service"); - q = strjoina(root, "/usr/lib/systemd/system/preset-no.service"); - -- HASHMAP_FOREACH(fl, h, j) { -+ HASHMAP_FOREACH(fl, h) { - assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0); - assert_se(fl->state == state); - -diff --git a/src/test/test-install.c b/src/test/test-install.c -index 62daacc..f1423fb 100644 ---- a/src/test/test-install.c -+++ b/src/test/test-install.c -@@ -22,7 +22,6 @@ static void dump_changes(UnitFileChange *c, unsigned n) { - int main(int argc, char* argv[]) { - Hashmap *h; - UnitFileList *p; -- Iterator i; - int r; - const char *const files[] = { "avahi-daemon.service", NULL }; - const char *const files2[] = { "/home/lennart/test.service", NULL }; -@@ -36,7 +35,7 @@ int main(int argc, char* argv[]) { - r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL); - assert_se(r == 0); - -- HASHMAP_FOREACH(p, h, i) { -+ HASHMAP_FOREACH(p, h) { - UnitFileState s = _UNIT_FILE_STATE_INVALID; - - r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path), &s); -diff --git a/src/test/test-json.c b/src/test/test-json.c -index 032619a..6da93d6 100644 ---- a/src/test/test-json.c -+++ b/src/test/test-json.c -@@ -3,6 +3,7 @@ - #include - - #include "alloc-util.h" -+#include "escape.h" - #include "fd-util.h" - #include "fileio.h" - #include "json-internal.h" -@@ -17,6 +18,10 @@ static void test_tokenizer(const char *data, ...) { - void *state = NULL; - va_list ap; - -+ _cleanup_free_ char *cdata; -+ assert_se(cdata = cescape(data)); -+ log_info("/* %s data=\"%s\" */", __func__, cdata); -+ - va_start(ap, data); - - for (;;) { -@@ -82,6 +87,10 @@ static void test_variant(const char *data, Test test) { - _cleanup_free_ char *s = NULL; - int r; - -+ _cleanup_free_ char *cdata; -+ assert_se(cdata = cescape(data)); -+ log_info("/* %s data=\"%s\" */", __func__, cdata); -+ - r = json_parse(data, 0, &v, NULL, NULL); - assert_se(r == 0); - assert_se(v); -@@ -140,6 +149,8 @@ static void test_1(JsonVariant *v) { - JsonVariant *p, *q; - unsigned i; - -+ log_info("/* %s */", __func__); -+ - /* 3 keys + 3 values */ - assert_se(json_variant_elements(v) == 6); - -@@ -173,6 +184,8 @@ static void test_1(JsonVariant *v) { - static void test_2(JsonVariant *v) { - JsonVariant *p, *q; - -+ log_info("/* %s */", __func__); -+ - /* 2 keys + 2 values */ - assert_se(json_variant_elements(v) == 4); - -@@ -216,13 +229,12 @@ static void test_2(JsonVariant *v) { - } - - static void test_zeroes(JsonVariant *v) { -- size_t i; -- - /* Make sure zero is how we expect it. */ -+ log_info("/* %s */", __func__); - - assert_se(json_variant_elements(v) == 13); - -- for (i = 0; i < json_variant_elements(v); i++) { -+ for (size_t i = 0; i < json_variant_elements(v); i++) { - JsonVariant *w; - size_t j; - -@@ -255,6 +267,8 @@ static void test_zeroes(JsonVariant *v) { - } - - static void test_build(void) { -+ log_info("/* %s */", __func__); -+ - _cleanup_(json_variant_unrefp) JsonVariant *a = NULL, *b = NULL; - _cleanup_free_ char *s = NULL, *t = NULL; - -@@ -355,6 +369,8 @@ static void test_source(void) { - "false, 7.5, {} ]\n" - "}\n"; - -+ log_info("/* %s */", __func__); -+ - _cleanup_fclose_ FILE *f = NULL; - _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; - -@@ -376,15 +392,16 @@ static void test_source(void) { - } - - static void test_depth(void) { -+ log_info("/* %s */", __func__); -+ - _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; -- unsigned i; - int r; - - v = JSON_VARIANT_STRING_CONST("start"); - - /* Let's verify that the maximum depth checks work */ - -- for (i = 0;; i++) { -+ for (unsigned i = 0;; i++) { - _cleanup_(json_variant_unrefp) JsonVariant *w = NULL; - - assert_se(i <= UINT16_MAX); -@@ -415,6 +432,8 @@ static void test_depth(void) { - } - - static void test_normalize(void) { -+ log_info("/* %s */", __func__); -+ - _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL; - _cleanup_free_ char *t = NULL; - -@@ -459,12 +478,13 @@ static void test_normalize(void) { - } - - static void test_bisect(void) { -+ log_info("/* %s */", __func__); -+ - _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; -- char c; - - /* Tests the bisection logic in json_variant_by_key() */ - -- for (c = 'z'; c >= 'a'; c--) { -+ for (char c = 'z'; c >= 'a'; c--) { - - if ((c % 3) == 0) - continue; -@@ -484,7 +504,7 @@ static void test_bisect(void) { - - json_variant_dump(v, JSON_FORMAT_COLOR|JSON_FORMAT_PRETTY, NULL, NULL); - -- for (c = 'a'; c <= 'z'; c++) { -+ for (char c = 'a'; c <= 'z'; c++) { - JsonVariant *k; - const char *z; - -@@ -543,7 +563,7 @@ int main(int argc, char *argv[]) { - - test_variant("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1); - test_variant("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"thisisaverylongproperty\": 1.27}", test_2); -- test_variant("{\"foo\" : \"\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFFFFF\\\"\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFF\\uDBFF\\uDFFFF\\uDBFF\\uDFFF\\uDBFF\\uDFFF\\uDBFF\\uDFFF\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFFFF\\\"\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFF\\uDBFF\\uDFFF\"}", NULL); -+ test_variant("{\"foo\" : \"\\u0935\\u093f\\u0935\\u0947\\u0915\\u0916\\u094d\\u092f\\u093e\\u0924\\u093f\\u0930\\u0935\\u093f\\u092a\\u094d\\u0932\\u0935\\u093e\\u0020\\u0939\\u093e\\u0928\\u094b\\u092a\\u093e\\u092f\\u0903\\u0964\"}", NULL); - - test_variant("[ 0, -0, 0.0, -0.0, 0.000, -0.000, 0e0, -0e0, 0e+0, -0e-0, 0e-0, -0e000, 0e+000 ]", test_zeroes); - -diff --git a/src/test/test-list.c b/src/test/test-list.c -index 24e0496..ca5361a 100644 ---- a/src/test/test-list.c -+++ b/src/test/test-list.c -@@ -12,11 +12,14 @@ int main(int argc, const char *argv[]) { - LIST_FIELDS(struct list_item, item); - } list_item; - LIST_HEAD(list_item, head); -+ LIST_HEAD(list_item, head2); - list_item items[4]; - list_item *cursor; - - LIST_HEAD_INIT(head); -+ LIST_HEAD_INIT(head2); - assert_se(head == NULL); -+ assert_se(head2 == NULL); - - for (i = 0; i < ELEMENTSOF(items); i++) { - LIST_INIT(item, &items[i]); -@@ -203,5 +206,49 @@ int main(int argc, const char *argv[]) { - - assert_se(head == NULL); - -+ for (i = 0; i < ELEMENTSOF(items) / 2; i++) { -+ LIST_INIT(item, &items[i]); -+ assert_se(LIST_JUST_US(item, &items[i])); -+ LIST_PREPEND(item, head, &items[i]); -+ } -+ -+ for (i = ELEMENTSOF(items) / 2; i < ELEMENTSOF(items); i++) { -+ LIST_INIT(item, &items[i]); -+ assert_se(LIST_JUST_US(item, &items[i])); -+ LIST_PREPEND(item, head2, &items[i]); -+ } -+ -+ assert_se(items[0].item_next == NULL); -+ assert_se(items[1].item_next == &items[0]); -+ assert_se(items[2].item_next == NULL); -+ assert_se(items[3].item_next == &items[2]); -+ -+ assert_se(items[0].item_prev == &items[1]); -+ assert_se(items[1].item_prev == NULL); -+ assert_se(items[2].item_prev == &items[3]); -+ assert_se(items[3].item_prev == NULL); -+ -+ LIST_JOIN(item, head2, head); -+ assert_se(head == NULL); -+ -+ assert_se(items[0].item_next == NULL); -+ assert_se(items[1].item_next == &items[0]); -+ assert_se(items[2].item_next == &items[1]); -+ assert_se(items[3].item_next == &items[2]); -+ -+ assert_se(items[0].item_prev == &items[1]); -+ assert_se(items[1].item_prev == &items[2]); -+ assert_se(items[2].item_prev == &items[3]); -+ assert_se(items[3].item_prev == NULL); -+ -+ LIST_JOIN(item, head, head2); -+ assert_se(head2 == NULL); -+ assert_se(!LIST_IS_EMPTY(head)); -+ -+ for (i = 0; i < ELEMENTSOF(items); i++) -+ LIST_REMOVE(item, head, &items[i]); -+ -+ assert_se(head == NULL); -+ - return 0; - } -diff --git a/src/test/test-load-fragment.c b/src/test/test-load-fragment.c -index 0293d1c..66925c2 100644 ---- a/src/test/test-load-fragment.c -+++ b/src/test/test-load-fragment.c -@@ -33,7 +33,6 @@ - static int test_unit_file_get_set(void) { - int r; - Hashmap *h; -- Iterator i; - UnitFileList *p; - - h = hashmap_new(&string_hash_ops); -@@ -48,7 +47,7 @@ static int test_unit_file_get_set(void) { - if (r < 0) - return EXIT_FAILURE; - -- HASHMAP_FOREACH(p, h, i) -+ HASHMAP_FOREACH(p, h) - printf("%s = %s\n", p->path, unit_file_state_to_string(p->state)); - - unit_file_list_free(h); -diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c -index 499873f..30b00ae 100644 ---- a/src/test/test-mountpoint-util.c -+++ b/src/test/test-mountpoint-util.c -@@ -38,7 +38,6 @@ static void test_mount_propagation_flags(const char *name, int ret, unsigned lon - static void test_mnt_id(void) { - _cleanup_fclose_ FILE *f = NULL; - _cleanup_hashmap_free_free_ Hashmap *h = NULL; -- Iterator i; - char *p; - void *k; - int r; -@@ -72,7 +71,7 @@ static void test_mnt_id(void) { - path = NULL; - } - -- HASHMAP_FOREACH_KEY(p, k, h, i) { -+ HASHMAP_FOREACH_KEY(p, k, h) { - int mnt_id = PTR_TO_INT(k), mnt_id2; - - r = path_get_mnt_id(p, &mnt_id2); -diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c -index a7ad482..3972207 100644 ---- a/src/test/test-namespace.c -+++ b/src/test/test-namespace.c -@@ -150,6 +150,7 @@ static void test_protect_kernel_logs(void) { - assert_se(fd > 0); - - r = setup_namespace(NULL, -+ NULL, - NULL, - &ns_info, - NULL, -@@ -158,11 +159,11 @@ static void test_protect_kernel_logs(void) { - NULL, - NULL, 0, - NULL, 0, -+ NULL, 0, -+ NULL, - NULL, - NULL, - NULL, -- PROTECT_HOME_NO, -- PROTECT_SYSTEM_NO, - 0, - NULL, - 0, -diff --git a/src/test/test-ns.c b/src/test/test-ns.c -index cbc41b7..5d7931f 100644 ---- a/src/test/test-ns.c -+++ b/src/test/test-ns.c -@@ -36,6 +36,8 @@ int main(int argc, char *argv[]) { - .protect_control_groups = true, - .protect_kernel_tunables = true, - .protect_kernel_modules = true, -+ .protect_proc = PROTECT_PROC_NOACCESS, -+ .proc_subset = PROC_SUBSET_PID, - }; - - char *root_directory; -@@ -62,6 +64,7 @@ int main(int argc, char *argv[]) { - log_info("Not chrooted"); - - r = setup_namespace(root_directory, -+ NULL, - NULL, - &ns_info, - (char **) writable, -@@ -70,11 +73,12 @@ int main(int argc, char *argv[]) { - NULL, - &(BindMount) { .source = (char*) "/usr/bin", .destination = (char*) "/etc/systemd", .read_only = true }, 1, - &(TemporaryFileSystem) { .path = (char*) "/var", .options = (char*) "ro" }, 1, -+ NULL, -+ 0, - tmp_dir, - var_tmp_dir, - NULL, -- PROTECT_HOME_NO, -- PROTECT_SYSTEM_NO, -+ NULL, - 0, - NULL, - 0, -diff --git a/src/test/test-nss.c b/src/test/test-nss.c -index 6ba0f68..293d7a8 100644 ---- a/src/test/test-nss.c -+++ b/src/test/test-nss.c -@@ -54,7 +54,7 @@ static const char* af_to_string(int family, char *buf, size_t buf_len) { - return buf; - } - --static void* open_handle(const char* dir, const char* module, int flags) { -+static void* open_handle(const char *dir, const char *module, int flags) { - const char *path = NULL; - void *handle; - -@@ -63,6 +63,7 @@ static void* open_handle(const char* dir, const char* module, int flags) { - if (!path || access(path, F_OK) < 0) - path = strjoina("libnss_", module, ".so.2"); - -+ log_debug("Using %s", path); - handle = dlopen(path, flags); - if (!handle) - log_error("Failed to load module %s: %s", module, dlerror()); -@@ -70,10 +71,9 @@ static void* open_handle(const char* dir, const char* module, int flags) { - } - - static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) { -- const struct gaih_addrtuple *it; - int n = 0; - -- for (it = tuples; it; it = it->next) { -+ for (const struct gaih_addrtuple *it = tuples; it; it = it->next) { - _cleanup_free_ char *a = NULL; - union in_addr_union u; - int r; -@@ -147,7 +147,10 @@ static void test_gethostbyname4_r(void *handle, const char *module, const char * - fname = strjoina("_nss_", module, "_gethostbyname4_r"); - f = dlsym(handle, fname); - log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); -- assert_se(f); -+ if (!f) { -+ log_info("%s not defined", fname); -+ return; -+ } - - status = f(name, &pat, buffer, sizeof buffer, &errno1, &errno2, &ttl); - if (status == NSS_STATUS_SUCCESS) { -@@ -197,7 +200,10 @@ static void test_gethostbyname3_r(void *handle, const char *module, const char * - fname = strjoina("_nss_", module, "_gethostbyname3_r"); - f = dlsym(handle, fname); - log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); -- assert_se(f); -+ if (!f) { -+ log_info("%s not defined", fname); -+ return; -+ } - - status = f(name, af, &host, buffer, sizeof buffer, &errno1, &errno2, &ttl, &canon); - log_info("%s(\"%s\", %s) → status=%s%-20serrno=%d/%s h_errno=%d/%s ttl=%"PRIi32, -@@ -223,7 +229,10 @@ static void test_gethostbyname2_r(void *handle, const char *module, const char * - fname = strjoina("_nss_", module, "_gethostbyname2_r"); - f = dlsym(handle, fname); - log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); -- assert_se(f); -+ if (!f) { -+ log_info("%s not defined", fname); -+ return; -+ } - - status = f(name, af, &host, buffer, sizeof buffer, &errno1, &errno2); - log_info("%s(\"%s\", %s) → status=%s%-20serrno=%d/%s h_errno=%d/%s", -@@ -247,7 +256,10 @@ static void test_gethostbyname_r(void *handle, const char *module, const char *n - fname = strjoina("_nss_", module, "_gethostbyname_r"); - f = dlsym(handle, fname); - log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); -- assert_se(f); -+ if (!f) { -+ log_info("%s not defined", fname); -+ return; -+ } - - status = f(name, &host, buffer, sizeof buffer, &errno1, &errno2); - log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s", -@@ -279,8 +291,10 @@ static void test_gethostbyaddr2_r(void *handle, - - log_full_errno(f ? LOG_DEBUG : LOG_INFO, errno, - "dlsym(0x%p, %s) → 0x%p: %m", handle, fname, f); -- if (!f) -+ if (!f) { -+ log_info("%s not defined", fname); - return; -+ } - - assert_se(in_addr_to_string(af, addr, &addr_pretty) >= 0); - -@@ -314,8 +328,10 @@ static void test_gethostbyaddr_r(void *handle, - - log_full_errno(f ? LOG_DEBUG : LOG_INFO, errno, - "dlsym(0x%p, %s) → 0x%p: %m", handle, fname, f); -- if (!f) -+ if (!f) { -+ log_info("%s not defined", fname); - return; -+ } - - assert_se(in_addr_to_string(af, addr, &addr_pretty) >= 0); - -@@ -388,14 +404,13 @@ static int make_addresses(struct local_address **addresses) { - return 0; - } - --static int test_one_module(const char* dir, -+static int test_one_module(const char *dir, - const char *module, - char **names, - struct local_address *addresses, - int n_addresses) { - void *handle; - char **name; -- int i; - - log_info("======== %s ========", module); - -@@ -406,7 +421,7 @@ static int test_one_module(const char* dir, - STRV_FOREACH(name, names) - test_byname(handle, module, *name); - -- for (i = 0; i < n_addresses; i++) -+ for (int i = 0; i < n_addresses; i++) - test_byaddr(handle, module, - &addresses[i].address, - FAMILY_ADDRESS_SIZE(addresses[i].family), -diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c -index 3ca5e1e..3806c3f 100644 ---- a/src/test/test-parse-util.c -+++ b/src/test/test-parse-util.c -@@ -10,6 +10,9 @@ - #include "log.h" - #include "parse-util.h" - #include "string-util.h" -+#if HAVE_SECCOMP -+#include "seccomp-util.h" -+#endif - - static void test_parse_boolean(void) { - assert_se(parse_boolean("1") == 1); -@@ -852,6 +855,7 @@ static void test_parse_errno(void) { - } - - static void test_parse_syscall_and_errno(void) { -+#if HAVE_SECCOMP - _cleanup_free_ char *n = NULL; - int e; - -@@ -882,11 +886,16 @@ static void test_parse_syscall_and_errno(void) { - assert_se(e == 255); - n = mfree(n); - -+ assert_se(parse_syscall_and_errno("hoge:kill", &n, &e) >= 0); -+ assert_se(streq(n, "hoge")); -+ assert_se(e == SECCOMP_ERROR_NUMBER_KILL); -+ n = mfree(n); -+ - /* The function checks the syscall name is empty or not. */ - assert_se(parse_syscall_and_errno("", &n, &e) == -EINVAL); - assert_se(parse_syscall_and_errno(":255", &n, &e) == -EINVAL); - -- /* errno must be a valid errno name or number between 0 and ERRNO_MAX == 4095 */ -+ /* errno must be a valid errno name or number between 0 and ERRNO_MAX == 4095, or "kill" */ - assert_se(parse_syscall_and_errno("hoge:4096", &n, &e) == -ERANGE); - assert_se(parse_syscall_and_errno("hoge:-3", &n, &e) == -ERANGE); - assert_se(parse_syscall_and_errno("hoge:12.3", &n, &e) == -EINVAL); -@@ -896,6 +905,7 @@ static void test_parse_syscall_and_errno(void) { - assert_se(parse_syscall_and_errno("hoge:-EINVAL", &n, &e) == -EINVAL); - assert_se(parse_syscall_and_errno("hoge:EINVALaaa", &n, &e) == -EINVAL); - assert_se(parse_syscall_and_errno("hoge:", &n, &e) == -EINVAL); -+#endif - } - - static void test_parse_mtu(void) { -diff --git a/src/test/test-path.c b/src/test/test-path.c -index 1075f31..cf89d89 100644 ---- a/src/test/test-path.c -+++ b/src/test/test-path.c -@@ -350,7 +350,7 @@ int main(int argc, char *argv[]) { - assert_se(set_unit_path(test_path) >= 0); - assert_se(runtime_dir = setup_fake_runtime_dir()); - -- for (const test_function_t *test = tests; test && *test; test++) { -+ for (const test_function_t *test = tests; *test; test++) { - Manager *m = NULL; - int r; - -diff --git a/src/test/test-rm-rf.c b/src/test/test-rm-rf.c -new file mode 100644 -index 0000000..d6e426c ---- /dev/null -+++ b/src/test/test-rm-rf.c -@@ -0,0 +1,74 @@ -+/* SPDX-License-Identifier: LGPL-2.1+ */ -+ -+#include -+ -+#include "alloc-util.h" -+#include "process-util.h" -+#include "rm-rf.h" -+#include "string-util.h" -+#include "tests.h" -+#include "tmpfile-util.h" -+ -+static void test_rm_rf_chmod_inner(void) { -+ _cleanup_free_ char *d = NULL; -+ const char *x, *y; -+ -+ assert_se(getuid() != 0); -+ -+ assert_se(mkdtemp_malloc(NULL, &d) >= 0); -+ -+ x = strjoina(d, "/d"); -+ assert_se(mkdir(x, 0700) >= 0); -+ y = strjoina(x, "/f"); -+ assert_se(mknod(y, S_IFREG | 0600, 0) >= 0); -+ -+ assert_se(chmod(y, 0400) >= 0); -+ assert_se(chmod(x, 0500) >= 0); -+ assert_se(chmod(d, 0500) >= 0); -+ -+ assert_se(rm_rf(d, REMOVE_PHYSICAL|REMOVE_ROOT) == -EACCES); -+ -+ assert_se(access(d, F_OK) >= 0); -+ assert_se(access(x, F_OK) >= 0); -+ assert_se(access(y, F_OK) >= 0); -+ -+ assert_se(rm_rf(d, REMOVE_PHYSICAL|REMOVE_ROOT|REMOVE_CHMOD) >= 0); -+ -+ errno = 0; -+ assert_se(access(d, F_OK) < 0 && errno == ENOENT); -+} -+ -+static void test_rm_rf_chmod(void) { -+ int r; -+ -+ log_info("/* %s */", __func__); -+ -+ if (getuid() == 0) { -+ /* This test only works unpriv (as only then the access mask for the owning user matters), -+ * hence drop privs here */ -+ -+ r = safe_fork("(setresuid)", FORK_DEATHSIG|FORK_WAIT, NULL); -+ assert_se(r >= 0); -+ -+ if (r == 0) { -+ /* child */ -+ -+ assert_se(setresuid(1, 1, 1) >= 0); -+ -+ test_rm_rf_chmod_inner(); -+ _exit(EXIT_SUCCESS); -+ } -+ -+ return; -+ } -+ -+ test_rm_rf_chmod_inner(); -+} -+ -+int main(int argc, char **argv) { -+ test_setup_logging(LOG_DEBUG); -+ -+ test_rm_rf_chmod(); -+ -+ return 0; -+} -diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c -index eec2779..697130e 100644 ---- a/src/test/test-seccomp.c -+++ b/src/test/test-seccomp.c -@@ -73,6 +73,9 @@ static void test_architecture_table(void) { - "ppc\0" - "ppc64\0" - "ppc64-le\0" -+#ifdef SCMP_ARCH_RISCV64 -+ "riscv64\0" -+#endif - "s390\0" - "s390x\0") { - uint32_t c; -@@ -98,9 +101,6 @@ static void test_syscall_filter_set_find(void) { - } - - static void test_filter_sets(void) { -- unsigned i; -- int r; -- - log_info("/* %s */", __func__); - - if (!is_seccomp_available()) { -@@ -112,7 +112,7 @@ static void test_filter_sets(void) { - return; - } - -- for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { -+ for (unsigned i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { - pid_t pid; - - log_info("Testing %s", syscall_filter_sets[i].name); -@@ -121,10 +121,12 @@ static void test_filter_sets(void) { - assert_se(pid >= 0); - - if (pid == 0) { /* Child? */ -- int fd; -+ int fd, r; - - /* If we look at the default set (or one that includes it), allow-list instead of deny-list */ -- if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_SYSTEM_SERVICE)) -+ if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, -+ SYSCALL_FILTER_SET_SYSTEM_SERVICE, -+ SYSCALL_FILTER_SET_KNOWN)) - r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW, true); - else - r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN), true); -@@ -148,22 +150,25 @@ static void test_filter_sets(void) { - } - - static void test_filter_sets_ordered(void) { -- size_t i; -- - log_info("/* %s */", __func__); - - /* Ensure "@default" always remains at the beginning of the list */ - assert_se(SYSCALL_FILTER_SET_DEFAULT == 0); - assert_se(streq(syscall_filter_sets[0].name, "@default")); - -- for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { -+ /* Ensure "@known" always remains at the end of the list */ -+ assert_se(SYSCALL_FILTER_SET_KNOWN == _SYSCALL_FILTER_SET_MAX - 1); -+ assert_se(streq(syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].name, "@known")); -+ -+ for (size_t i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { - const char *k, *p = NULL; - - /* Make sure each group has a description */ - assert_se(!isempty(syscall_filter_sets[0].help)); - -- /* Make sure the groups are ordered alphabetically, except for the first entry */ -- assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0); -+ /* Make sure the groups are ordered alphabetically, except for the first and last entries */ -+ assert_se(i < 2 || i == _SYSCALL_FILTER_SET_MAX - 1 || -+ strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0); - - NULSTR_FOREACH(k, syscall_filter_sets[i].value) { - -diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c -index b9d63d6..6dee202 100644 ---- a/src/test/test-sizeof.c -+++ b/src/test/test-sizeof.c -@@ -16,6 +16,11 @@ - - DISABLE_WARNING_TYPE_LIMITS; - -+#define info_no_sign(t) \ -+ printf("%s → %zu bits, %zu byte alignment\n", STRINGIFY(t), \ -+ sizeof(t)*CHAR_BIT, \ -+ __alignof__(t)) -+ - #define info(t) \ - printf("%s → %zu bits%s, %zu byte alignment\n", STRINGIFY(t), \ - sizeof(t)*CHAR_BIT, \ -@@ -37,6 +42,12 @@ enum BigEnum2 { - }; - - int main(void) { -+ int (*function_pointer)(void); -+ -+ info_no_sign(function_pointer); -+ info_no_sign(void*); -+ info(char*); -+ - info(char); - info(signed char); - info(unsigned char); -diff --git a/src/test/test-socket-netlink.c b/src/test/test-socket-netlink.c -index 0a2007f..afb7038 100644 ---- a/src/test/test-socket-netlink.c -+++ b/src/test/test-socket-netlink.c -@@ -1,6 +1,7 @@ - /* SPDX-License-Identifier: LGPL-2.1+ */ - - #include "alloc-util.h" -+#include "missing_network.h" - #include "tests.h" - #include "socket-netlink.h" - #include "string-util.h" -@@ -11,11 +12,20 @@ static void test_socket_address_parse_one(const char *in, int ret, int family, c - int r; - - r = socket_address_parse(&a, in); -- if (r >= 0) -- assert_se(socket_address_print(&a, &out) >= 0); -+ if (r >= 0) { -+ r = socket_address_print(&a, &out); -+ if (r < 0) -+ log_error_errno(r, "Printing failed for \"%s\": %m", in); -+ assert(r >= 0); -+ assert_se(a.type == 0); -+ } - -- log_info("\"%s\" → %s → \"%s\" (expect \"%s\")", in, -- r >= 0 ? "✓" : "✗", empty_to_dash(out), r >= 0 ? expected ?: in : "-"); -+ log_info("\"%s\" → %s %d → \"%s\" (expect %d / \"%s\")", -+ in, -+ r >= 0 ? "✓" : "✗", r, -+ empty_to_dash(out), -+ ret, -+ ret >= 0 ? expected ?: in : "-"); - assert_se(r == ret); - if (r >= 0) { - assert_se(a.sockaddr.sa.sa_family == family); -@@ -49,14 +59,24 @@ static void test_socket_address_parse(void) { - test_socket_address_parse_one("[::1]:0", -EINVAL, 0, NULL); - test_socket_address_parse_one("[::1]:65536", -ERANGE, 0, NULL); - test_socket_address_parse_one("[a:b:1]:8888", -EINVAL, 0, NULL); -+ test_socket_address_parse_one("[::1]%lo:1234", -EINVAL, 0, NULL); -+ test_socket_address_parse_one("[::1]%lo:0", -EINVAL, 0, NULL); -+ test_socket_address_parse_one("[::1]%lo", -EINVAL, 0, NULL); -+ test_socket_address_parse_one("[::1]%lo%lo:1234", -EINVAL, 0, NULL); -+ test_socket_address_parse_one("[::1]% lo:1234", -EINVAL, 0, NULL); - - test_socket_address_parse_one("8888", 0, default_family, "[::]:8888"); - test_socket_address_parse_one("[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888", 0, AF_INET6, - "[2001:db8:0:85a3::ac1f:8001]:8888"); - test_socket_address_parse_one("[::1]:8888", 0, AF_INET6, NULL); -+ test_socket_address_parse_one("[::1]:1234%lo", 0, AF_INET6, NULL); -+ test_socket_address_parse_one("[::1]:0%lo", -EINVAL, 0, NULL); -+ test_socket_address_parse_one("[::1]%lo", -EINVAL, 0, NULL); -+ test_socket_address_parse_one("[::1]:1234%lo%lo", -ENODEV, 0, NULL); -+ test_socket_address_parse_one("[::1]:1234%xxxxasdf", -ENODEV, 0, NULL); - test_socket_address_parse_one("192.168.1.254:8888", 0, AF_INET, NULL); - test_socket_address_parse_one("/foo/bar", 0, AF_UNIX, NULL); -- test_socket_address_parse_one("/", 0, AF_UNIX, NULL); -+ test_socket_address_parse_one("/", -EINVAL, 0, NULL); - test_socket_address_parse_one("@abstract", 0, AF_UNIX, NULL); - - { -@@ -197,9 +217,13 @@ static void test_socket_address_is(void) { - log_info("/* %s */", __func__); - - assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); -- assert_se(socket_address_is(&a, "192.168.1.1:8888", SOCK_STREAM)); -+ assert_se( socket_address_is(&a, "192.168.1.1:8888", 0 /* unspecified yet */)); -+ assert_se(!socket_address_is(&a, "route", 0)); - assert_se(!socket_address_is(&a, "route", SOCK_STREAM)); - assert_se(!socket_address_is(&a, "192.168.1.1:8888", SOCK_RAW)); -+ assert_se(!socket_address_is(&a, "192.168.1.1:8888", SOCK_STREAM)); -+ a.type = SOCK_STREAM; -+ assert_se( socket_address_is(&a, "192.168.1.1:8888", SOCK_STREAM)); - } - - static void test_socket_address_is_netlink(void) { -@@ -208,11 +232,160 @@ static void test_socket_address_is_netlink(void) { - log_info("/* %s */", __func__); - - assert_se(socket_address_parse_netlink(&a, "route 10") >= 0); -- assert_se(socket_address_is_netlink(&a, "route 10")); -+ assert_se( socket_address_is_netlink(&a, "route 10")); - assert_se(!socket_address_is_netlink(&a, "192.168.1.1:8888")); - assert_se(!socket_address_is_netlink(&a, "route 1")); - } - -+static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) { -+ _cleanup_free_ char *r = NULL; -+ union in_addr_union ua, uuaa; -+ int ff, ifindex2; -+ -+ assert_se(in_addr_from_string(f, a, &ua) >= 0); -+ assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0); -+ printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r); -+ assert_se(streq(b, r)); -+ -+ assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0); -+ assert_se(ff == f); -+ assert_se(in_addr_equal(f, &ua, &uuaa)); -+ assert_se(ifindex2 == ifindex || ifindex2 == 0); -+} -+ -+static void test_in_addr_ifindex_to_string(void) { -+ log_info("/* %s */", __func__); -+ -+ test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1"); -+ test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13"); -+ test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); -+ test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1"); -+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12"); -+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::"); -+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12"); -+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15"); -+ test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1"); -+} -+ -+static void test_in_addr_ifindex_from_string_auto(void) { -+ int family, ifindex; -+ union in_addr_union ua; -+ -+ log_info("/* %s */", __func__); -+ /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */ -+ -+ assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0); -+ assert_se(family == AF_INET6); -+ assert_se(ifindex == 0); -+ -+ assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0); -+ assert_se(family == AF_INET6); -+ assert_se(ifindex == 19); -+ -+ assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0); -+ assert_se(family == AF_INET6); -+ assert_se(ifindex == LOOPBACK_IFINDEX); -+ -+ assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV); -+} -+ -+static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) { -+ int family, ifindex; -+ union in_addr_union ua; -+ _cleanup_free_ char *server_name = NULL; -+ -+ assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0); -+ assert_se(streq_ptr(server_name, expected)); -+} -+ -+static void test_in_addr_ifindex_name_from_string_auto(void) { -+ log_info("/* %s */", __func__); -+ -+ test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL); -+ test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com"); -+ test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL); -+ test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com"); -+} -+ -+static void test_in_addr_port_ifindex_name_from_string_auto_one(const char *str, int family, uint16_t port, int ifindex, -+ const char *server_name, const char *str_repr) { -+ union in_addr_union a; -+ uint16_t p; -+ int f, i; -+ char *fake; -+ -+ log_info("%s: %s", __func__, str); -+ -+ { -+ _cleanup_free_ char *name = NULL, *x = NULL; -+ assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, &name) == 0); -+ assert_se(family == f); -+ assert_se(port == p); -+ assert_se(ifindex == i); -+ assert_se(streq_ptr(server_name, name)); -+ assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, i, name, &x) >= 0); -+ assert_se(streq(str_repr ?: str, x)); -+ } -+ -+ if (port > 0) -+ assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, NULL, &i, &fake) == -EINVAL); -+ else { -+ _cleanup_free_ char *name = NULL, *x = NULL; -+ assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, NULL, &i, &name) == 0); -+ assert_se(family == f); -+ assert_se(ifindex == i); -+ assert_se(streq_ptr(server_name, name)); -+ assert_se(in_addr_port_ifindex_name_to_string(f, &a, 0, i, name, &x) >= 0); -+ assert_se(streq(str_repr ?: str, x)); -+ } -+ -+ if (ifindex > 0) -+ assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, NULL, &fake) == -EINVAL); -+ else { -+ _cleanup_free_ char *name = NULL, *x = NULL; -+ assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, NULL, &name) == 0); -+ assert_se(family == f); -+ assert_se(port == p); -+ assert_se(streq_ptr(server_name, name)); -+ assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, 0, name, &x) >= 0); -+ assert_se(streq(str_repr ?: str, x)); -+ } -+ -+ if (server_name) -+ assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, NULL) == -EINVAL); -+ else { -+ _cleanup_free_ char *x = NULL; -+ assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, NULL) == 0); -+ assert_se(family == f); -+ assert_se(port == p); -+ assert_se(ifindex == i); -+ assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, i, NULL, &x) >= 0); -+ assert_se(streq(str_repr ?: str, x)); -+ } -+} -+ -+static void test_in_addr_port_ifindex_name_from_string_auto(void) { -+ log_info("/* %s */", __func__); -+ -+ test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1", AF_INET, 0, 0, NULL, NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1#test.com", AF_INET, 0, 0, "test.com", NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53", AF_INET, 53, 0, NULL, NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53#example.com", AF_INET, 53, 0, "example.com", NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18", AF_INET6, 0, 0, NULL, NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18#hoge.com", AF_INET6, 0, 0, "hoge.com", NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19", AF_INET6, 0, 19, NULL, NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%lo", AF_INET6, 0, 1, NULL, "fe80::18%1"); -+ test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53", AF_INET6, 53, 0, NULL, NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL, NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo", AF_INET6, 53, 1, NULL, "[fe80::18]:53%1"); -+ test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19#hoge.com", AF_INET6, 0, 19, "hoge.com", NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53#hoge.com", AF_INET6, 53, 0, "hoge.com", NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL, NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19#hoge.com", AF_INET6, 53, 19, "hoge.com", NULL); -+ test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo", AF_INET6, 53, 1, NULL, "[fe80::18]:53%1"); -+ test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%lo#hoge.com", AF_INET6, 53, 1, "hoge.com", "[fe80::18]:53%1#hoge.com"); -+} -+ - int main(int argc, char *argv[]) { - test_setup_logging(LOG_DEBUG); - -@@ -223,5 +396,10 @@ int main(int argc, char *argv[]) { - test_socket_address_is(); - test_socket_address_is_netlink(); - -+ test_in_addr_ifindex_to_string(); -+ test_in_addr_ifindex_from_string_auto(); -+ test_in_addr_ifindex_name_from_string_auto(); -+ test_in_addr_port_ifindex_name_from_string_auto(); -+ - return 0; - } -diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c -index b007dd6..1bb1866 100644 ---- a/src/test/test-socket-util.c -+++ b/src/test/test-socket-util.c -@@ -15,9 +15,7 @@ - #include "io-util.h" - #include "log.h" - #include "macro.h" --#include "missing_network.h" - #include "process-util.h" --#include "socket-netlink.h" - #include "socket-util.h" - #include "string-util.h" - #include "tests.h" -@@ -28,13 +26,13 @@ assert_cc(SUN_PATH_LEN == 108); - static void test_ifname_valid(void) { - log_info("/* %s */", __func__); - -- assert(ifname_valid("foo")); -- assert(ifname_valid("eth0")); -+ assert( ifname_valid("foo")); -+ assert( ifname_valid("eth0")); - - assert(!ifname_valid("0")); - assert(!ifname_valid("99")); -- assert(ifname_valid("a99")); -- assert(ifname_valid("99a")); -+ assert( ifname_valid("a99")); -+ assert( ifname_valid("99a")); - - assert(!ifname_valid(NULL)); - assert(!ifname_valid("")); -@@ -46,9 +44,13 @@ static void test_ifname_valid(void) { - assert(ifname_valid("foo.bar")); - assert(!ifname_valid("x:y")); - -- assert(ifname_valid("xxxxxxxxxxxxxxx")); -- assert(!ifname_valid("xxxxxxxxxxxxxxxx")); -- assert(ifname_valid_full("xxxxxxxxxxxxxxxx", true)); -+ assert( ifname_valid_full("xxxxxxxxxxxxxxx", 0)); -+ assert(!ifname_valid_full("xxxxxxxxxxxxxxxx", 0)); -+ assert( ifname_valid_full("xxxxxxxxxxxxxxxx", IFNAME_VALID_ALTERNATIVE)); -+ assert( ifname_valid_full("xxxxxxxxxxxxxxxx", IFNAME_VALID_ALTERNATIVE)); -+ assert(!ifname_valid_full("999", IFNAME_VALID_ALTERNATIVE)); -+ assert( ifname_valid_full("999", IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC)); -+ assert(!ifname_valid_full("0", IFNAME_VALID_ALTERNATIVE | IFNAME_VALID_NUMERIC)); - } - - static void test_socket_print_unix_one(const char *in, size_t len_in, const char *expected) { -@@ -84,256 +86,6 @@ static void test_socket_print_unix(void) { - test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000"); - } - --static void test_in_addr_is_null(void) { -- union in_addr_union i = {}; -- -- log_info("/* %s */", __func__); -- -- assert_se(in_addr_is_null(AF_INET, &i) == true); -- assert_se(in_addr_is_null(AF_INET6, &i) == true); -- -- i.in.s_addr = 0x1000000; -- assert_se(in_addr_is_null(AF_INET, &i) == false); -- assert_se(in_addr_is_null(AF_INET6, &i) == false); -- -- assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT); --} -- --static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) { -- union in_addr_union ua, ub; -- -- assert_se(in_addr_from_string(f, a, &ua) >= 0); -- assert_se(in_addr_from_string(f, b, &ub) >= 0); -- -- assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result); --} -- --static void test_in_addr_prefix_intersect(void) { -- log_info("/* %s */", __func__); -- -- test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0); -- test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1); -- test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1); -- -- test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1); -- test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0); -- -- test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1); -- test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1); -- test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1); -- test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0); -- -- test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", 128, 0); -- test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1); -- test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1); -- -- test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1); -- test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0); -- -- test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1); -- test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1); -- test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1); -- test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0); --} -- --static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) { -- union in_addr_union ubefore, uafter, t; -- -- assert_se(in_addr_from_string(f, before, &ubefore) >= 0); -- -- t = ubefore; -- assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after); -- -- if (after) { -- assert_se(in_addr_from_string(f, after, &uafter) >= 0); -- assert_se(in_addr_equal(f, &t, &uafter) > 0); -- } --} -- --static void test_in_addr_prefix_next(void) { -- log_info("/* %s */", __func__); -- -- test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0"); -- test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0"); -- test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0"); -- -- test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1"); -- test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL); -- test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL); -- -- test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001"); -- test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100"); -- test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002"); -- test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::"); -- test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::"); -- -- test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1"); -- -- test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL); -- test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL); --} -- --static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) { -- union in_addr_union ubefore, uafter, t; -- -- assert_se(in_addr_from_string(f, before, &ubefore) >= 0); -- -- t = ubefore; -- assert_se((in_addr_prefix_nth(f, &t, pl, nth) > 0) == !!after); -- -- if (after) { -- assert_se(in_addr_from_string(f, after, &uafter) >= 0); -- assert_se(in_addr_equal(f, &t, &uafter) > 0); -- } --} -- --static void test_in_addr_prefix_nth(void) { -- log_info("/* %s */", __func__); -- -- test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0"); -- test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 1, "192.168.1.0"); -- test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0"); -- test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128"); -- test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128"); -- test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 24, 0, "192.168.255.0"); -- test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 32, 1, NULL); -- test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 0, 1, NULL); -- -- test_in_addr_prefix_nth_one(AF_INET6, "4400::", 8, 1, "4500::"); -- test_in_addr_prefix_nth_one(AF_INET6, "4400::", 7, 1, "4600::"); -- test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 1, "4400:0:0:1::"); -- test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 2, "4400:0:0:2::"); -- test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 0xbad, "4400:0:0:0bad::"); -- test_in_addr_prefix_nth_one(AF_INET6, "4400:0:0:ffff::", 64, 1, "4400:0:1::"); -- test_in_addr_prefix_nth_one(AF_INET6, "4400::", 56, ((uint64_t)1<<48) -1, "44ff:ffff:ffff:ff00::"); -- test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 255, "ff00::"); -- test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL); -- test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL); -- test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL); --} -- --static void test_in_addr_to_string_one(int f, const char *addr) { -- union in_addr_union ua; -- _cleanup_free_ char *r = NULL; -- -- assert_se(in_addr_from_string(f, addr, &ua) >= 0); -- assert_se(in_addr_to_string(f, &ua, &r) >= 0); -- printf("test_in_addr_to_string_one: %s == %s\n", addr, r); -- assert_se(streq(addr, r)); --} -- --static void test_in_addr_to_string(void) { -- log_info("/* %s */", __func__); -- -- test_in_addr_to_string_one(AF_INET, "192.168.0.1"); -- test_in_addr_to_string_one(AF_INET, "10.11.12.13"); -- test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); -- test_in_addr_to_string_one(AF_INET6, "::1"); -- test_in_addr_to_string_one(AF_INET6, "fe80::"); --} -- --static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) { -- _cleanup_free_ char *r = NULL; -- union in_addr_union ua, uuaa; -- int ff, ifindex2; -- -- assert_se(in_addr_from_string(f, a, &ua) >= 0); -- assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0); -- printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r); -- assert_se(streq(b, r)); -- -- assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0); -- assert_se(ff == f); -- assert_se(in_addr_equal(f, &ua, &uuaa)); -- assert_se(ifindex2 == ifindex || ifindex2 == 0); --} -- --static void test_in_addr_ifindex_to_string(void) { -- log_info("/* %s */", __func__); -- -- test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1"); -- test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13"); -- test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); -- test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1"); -- test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12"); -- test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::"); -- test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12"); -- test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15"); -- test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1"); --} -- --static void test_in_addr_ifindex_from_string_auto(void) { -- int family, ifindex; -- union in_addr_union ua; -- -- log_info("/* %s */", __func__); -- /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */ -- -- assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0); -- assert_se(family == AF_INET6); -- assert_se(ifindex == 0); -- -- assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0); -- assert_se(family == AF_INET6); -- assert_se(ifindex == 19); -- -- assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0); -- assert_se(family == AF_INET6); -- assert_se(ifindex == LOOPBACK_IFINDEX); -- -- assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV); --} -- --static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) { -- int family, ifindex; -- union in_addr_union ua; -- _cleanup_free_ char *server_name = NULL; -- -- assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0); -- assert_se(streq_ptr(server_name, expected)); --} -- --static void test_in_addr_ifindex_name_from_string_auto(void) { -- log_info("/* %s */", __func__); -- -- test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL); -- test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com"); -- test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL); -- test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com"); --} -- --static void test_in_addr_port_ifindex_name_from_string_auto_one(const char *str, int family, uint16_t port, int ifindex, const char *server_name) { -- _cleanup_free_ char *name = NULL, *x = NULL; -- union in_addr_union a; -- uint16_t p; -- int f, i; -- -- assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, &name) >= 0); -- assert_se(family == f); -- assert_se(port == p); -- assert_se(ifindex == i); -- assert_se(streq_ptr(server_name, name)); -- assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, i, name, &x) >= 0); -- assert_se(streq(str, x)); --} -- --static void test_in_addr_port_ifindex_name_from_string_auto(void) { -- log_info("/* %s */", __func__); -- -- test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1", AF_INET, 0, 0, NULL); -- test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1#test.com", AF_INET, 0, 0, "test.com"); -- test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53", AF_INET, 53, 0, NULL); -- test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53#example.com", AF_INET, 53, 0, "example.com"); -- test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18", AF_INET6, 0, 0, NULL); -- test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18#hoge.com", AF_INET6, 0, 0, "hoge.com"); -- test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19", AF_INET6, 0, 19, NULL); -- test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53", AF_INET6, 53, 0, NULL); -- test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19#hoge.com", AF_INET6, 0, 19, "hoge.com"); -- test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53#hoge.com", AF_INET6, 53, 0, "hoge.com"); -- test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL); -- test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19#hoge.com", AF_INET6, 53, 19, "hoge.com"); --} -- - static void test_sockaddr_equal(void) { - union sockaddr_union a = { - .in.sin_family = AF_INET, -@@ -756,27 +508,11 @@ int main(int argc, char *argv[]) { - test_setup_logging(LOG_DEBUG); - - test_ifname_valid(); -- - test_socket_print_unix(); -- -- test_in_addr_is_null(); -- test_in_addr_prefix_intersect(); -- test_in_addr_prefix_next(); -- test_in_addr_prefix_nth(); -- test_in_addr_to_string(); -- test_in_addr_ifindex_to_string(); -- test_in_addr_ifindex_from_string_auto(); -- test_in_addr_ifindex_name_from_string_auto(); -- test_in_addr_port_ifindex_name_from_string_auto(); -- - test_sockaddr_equal(); -- - test_sockaddr_un_len(); -- - test_in_addr_is_multicast(); -- - test_getpeercred_getpeergroups(); -- - test_passfd_read(); - test_passfd_contents_read(); - test_receive_nopassfd(); -diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c -index 9d9dbd4..13a66df 100644 ---- a/src/test/test-stat-util.c -+++ b/src/test/test-stat-util.c -@@ -148,7 +148,7 @@ static void test_device_path_make_canonical(void) { - test_device_path_make_canonical_one("/dev/urandom"); - test_device_path_make_canonical_one("/dev/tty"); - -- if (is_device_node("/run/systemd/inaccessible/chr") > 0) { -+ if (is_device_node("/run/systemd/inaccessible/blk") > 0) { - test_device_path_make_canonical_one("/run/systemd/inaccessible/chr"); - test_device_path_make_canonical_one("/run/systemd/inaccessible/blk"); - } -diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c -index 13936f6..196c96a 100644 ---- a/src/test/test-string-util.c -+++ b/src/test/test-string-util.c -@@ -10,8 +10,9 @@ - #include "util.h" - - static void test_string_erase(void) { -- char *x; -+ log_info("/* %s */", __func__); - -+ char *x; - x = strdupa(""); - assert_se(streq(string_erase(x), "")); - -@@ -33,17 +34,17 @@ static void test_string_erase(void) { - } - - static void test_free_and_strndup_one(char **t, const char *src, size_t l, const char *expected, bool change) { -- int r; -- - log_debug("%s: \"%s\", \"%s\", %zd (expect \"%s\", %s)", - __func__, strnull(*t), strnull(src), l, strnull(expected), yes_no(change)); - -- r = free_and_strndup(t, src, l); -+ int r = free_and_strndup(t, src, l); - assert_se(streq_ptr(*t, expected)); - assert_se(r == change); /* check that change occurs only when necessary */ - } - - static void test_free_and_strndup(void) { -+ log_info("/* %s */", __func__); -+ - static const struct test_case { - const char *src; - size_t len; -@@ -91,6 +92,7 @@ static void test_free_and_strndup(void) { - } - - static void test_ascii_strcasecmp_n(void) { -+ log_info("/* %s */", __func__); - - assert_se(ascii_strcasecmp_n("", "", 0) == 0); - assert_se(ascii_strcasecmp_n("", "", 1) == 0); -@@ -118,6 +120,8 @@ static void test_ascii_strcasecmp_n(void) { - } - - static void test_ascii_strcasecmp_nn(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0); - assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0); - assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0); -@@ -137,6 +141,8 @@ static void test_ascii_strcasecmp_nn(void) { - static void test_cellescape(void) { - char buf[40]; - -+ log_info("/* %s */", __func__); -+ - assert_se(streq(cellescape(buf, 1, ""), "")); - assert_se(streq(cellescape(buf, 1, "1"), "")); - assert_se(streq(cellescape(buf, 1, "12"), "")); -@@ -216,19 +222,24 @@ static void test_cellescape(void) { - } - - static void test_streq_ptr(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(streq_ptr(NULL, NULL)); - assert_se(!streq_ptr("abc", "cdef")); - } - - static void test_strstrip(void) { -- char *r; -- char input[] = " hello, waldo. "; -+ log_info("/* %s */", __func__); - -- r = strstrip(input); -- assert_se(streq(r, "hello, waldo.")); -+ char *ret, input[] = " hello, waldo. "; -+ -+ ret = strstrip(input); -+ assert_se(streq(ret, "hello, waldo.")); - } - - static void test_strextend(void) { -+ log_info("/* %s */", __func__); -+ - _cleanup_free_ char *str = NULL; - - assert_se(strextend(&str, NULL)); -@@ -240,6 +251,8 @@ static void test_strextend(void) { - } - - static void test_strextend_with_separator(void) { -+ log_info("/* %s */", __func__); -+ - _cleanup_free_ char *str = NULL; - - assert_se(strextend_with_separator(&str, NULL, NULL)); -@@ -263,6 +276,8 @@ static void test_strextend_with_separator(void) { - } - - static void test_strrep(void) { -+ log_info("/* %s */", __func__); -+ - _cleanup_free_ char *one, *three, *zero; - one = strrep("waldo", 1); - three = strrep("waldo", 3); -@@ -288,11 +303,15 @@ static void test_string_has_cc(void) { - } - - static void test_ascii_strlower(void) { -+ log_info("/* %s */", __func__); -+ - char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK"; - assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk")); - } - - static void test_strshorten(void) { -+ log_info("/* %s */", __func__); -+ - char s[] = "foobar"; - - assert_se(strlen(strshorten(s, 6)) == 6); -@@ -302,6 +321,8 @@ static void test_strshorten(void) { - } - - static void test_strjoina(void) { -+ log_info("/* %s */", __func__); -+ - char *actual; - - actual = strjoina("", "foo", "bar"); -@@ -326,7 +347,41 @@ static void test_strjoina(void) { - assert_se(streq(actual, "foo")); - } - -+static void test_strjoin(void) { -+ char *actual; -+ -+ actual = strjoin("", "foo", "bar"); -+ assert_se(streq(actual, "foobar")); -+ mfree(actual); -+ -+ actual = strjoin("foo", "bar", "baz"); -+ assert_se(streq(actual, "foobarbaz")); -+ mfree(actual); -+ -+ actual = strjoin("foo", "", "bar", "baz"); -+ assert_se(streq(actual, "foobarbaz")); -+ mfree(actual); -+ -+ actual = strjoin("foo", NULL); -+ assert_se(streq(actual, "foo")); -+ mfree(actual); -+ -+ actual = strjoin(NULL, NULL); -+ assert_se(streq(actual, "")); -+ mfree(actual); -+ -+ actual = strjoin(NULL, "foo"); -+ assert_se(streq(actual, "")); -+ mfree(actual); -+ -+ actual = strjoin("foo", NULL, "bar"); -+ assert_se(streq(actual, "foo")); -+ mfree(actual); -+} -+ - static void test_strcmp_ptr(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(strcmp_ptr(NULL, NULL) == 0); - assert_se(strcmp_ptr("", NULL) > 0); - assert_se(strcmp_ptr("foo", NULL) > 0); -@@ -339,26 +394,36 @@ static void test_strcmp_ptr(void) { - } - - static void test_foreach_word(void) { -- const char *word, *state; -- size_t l; -- int i = 0; -- const char test[] = "test abc d\te f "; -+ log_info("/* %s */", __func__); -+ -+ const char *test = "test abc d\te f "; - const char * const expected[] = { - "test", - "abc", - "d", - "e", - "f", -- "", -- NULL - }; - -- FOREACH_WORD(word, l, test, state) -- assert_se(strneq(expected[i++], word, l)); -+ size_t i = 0; -+ int r; -+ for (const char *p = test;;) { -+ _cleanup_free_ char *word = NULL; -+ -+ r = extract_first_word(&p, &word, NULL, 0); -+ if (r == 0) { -+ assert_se(i == ELEMENTSOF(expected)); -+ break; -+ } -+ assert_se(r > 0); -+ -+ assert_se(streq(expected[i++], word)); -+ } - } - - static void check(const char *test, char** expected, bool trailing) { -- int i = 0, r; -+ size_t i = 0; -+ int r; - - printf("<<<%s>>>\n", test); - for (;;) { -@@ -380,6 +445,8 @@ static void check(const char *test, char** expected, bool trailing) { - } - - static void test_foreach_word_quoted(void) { -+ log_info("/* %s */", __func__); -+ - check("test a b c 'd' e '' '' hhh '' '' \"a b c\"", - STRV_MAKE("test", - "a", -@@ -405,6 +472,8 @@ static void test_foreach_word_quoted(void) { - } - - static void test_endswith(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(endswith("foobar", "bar")); - assert_se(endswith("foobar", "")); - assert_se(endswith("foobar", "foobar")); -@@ -415,6 +484,8 @@ static void test_endswith(void) { - } - - static void test_endswith_no_case(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(endswith_no_case("fooBAR", "bar")); - assert_se(endswith_no_case("foobar", "")); - assert_se(endswith_no_case("foobar", "FOOBAR")); -@@ -425,6 +496,8 @@ static void test_endswith_no_case(void) { - } - - static void test_delete_chars(void) { -+ log_info("/* %s */", __func__); -+ - char *s, input[] = " hello, waldo. abc"; - - s = delete_chars(input, WHITESPACE); -@@ -433,6 +506,7 @@ static void test_delete_chars(void) { - } - - static void test_delete_trailing_chars(void) { -+ log_info("/* %s */", __func__); - - char *s, - input1[] = " \n \r k \n \r ", -@@ -457,6 +531,8 @@ static void test_delete_trailing_chars(void) { - } - - static void test_delete_trailing_slashes(void) { -+ log_info("/* %s */", __func__); -+ - char s1[] = "foobar//", - s2[] = "foobar/", - s3[] = "foobar", -@@ -470,6 +546,8 @@ static void test_delete_trailing_slashes(void) { - } - - static void test_skip_leading_chars(void) { -+ log_info("/* %s */", __func__); -+ - char input1[] = " \n \r k \n \r ", - input2[] = "kkkkthiskkkiskkkaktestkkk", - input3[] = "abcdef"; -@@ -482,11 +560,15 @@ static void test_skip_leading_chars(void) { - } - - static void test_in_charset(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(in_charset("dddaaabbbcccc", "abcd")); - assert_se(!in_charset("dddaaabbbcccc", "abc f")); - } - - static void test_split_pair(void) { -+ log_info("/* %s */", __func__); -+ - _cleanup_free_ char *a = NULL, *b = NULL; - - assert_se(split_pair("", "", &a, &b) == -EINVAL); -@@ -509,6 +591,8 @@ static void test_split_pair(void) { - } - - static void test_first_word(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(first_word("Hello", "")); - assert_se(first_word("Hello", "Hello")); - assert_se(first_word("Hello world", "Hello")); -@@ -523,12 +607,16 @@ static void test_first_word(void) { - } - - static void test_strlen_ptr(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(strlen_ptr("foo") == 3); - assert_se(strlen_ptr("") == 0); - assert_se(strlen_ptr(NULL) == 0); - } - - static void test_memory_startswith(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(streq(memory_startswith("", 0, ""), "")); - assert_se(streq(memory_startswith("", 1, ""), "")); - assert_se(streq(memory_startswith("x", 2, ""), "x")); -@@ -541,6 +629,8 @@ static void test_memory_startswith(void) { - } - - static void test_memory_startswith_no_case(void) { -+ log_info("/* %s */", __func__); -+ - assert_se(streq(memory_startswith_no_case("", 0, ""), "")); - assert_se(streq(memory_startswith_no_case("", 1, ""), "")); - assert_se(streq(memory_startswith_no_case("x", 2, ""), "x")); -@@ -573,6 +663,8 @@ static void test_string_truncate_lines_one(const char *input, size_t n_lines, co - } - - static void test_string_truncate_lines(void) { -+ log_info("/* %s */", __func__); -+ - test_string_truncate_lines_one("", 0, "", false); - test_string_truncate_lines_one("", 1, "", false); - test_string_truncate_lines_one("", 2, "", false); -@@ -644,6 +736,8 @@ static void test_string_extract_lines_one(const char *input, size_t i, const cha - } - - static void test_string_extract_line(void) { -+ log_info("/* %s */", __func__); -+ - test_string_extract_lines_one("", 0, "", false); - test_string_extract_lines_one("", 1, "", false); - test_string_extract_lines_one("", 2, "", false); -@@ -710,6 +804,88 @@ static void test_string_extract_line(void) { - test_string_extract_lines_one("\n\n\nx\n", 3, "x", false); - } - -+static void test_string_contains_word_strv(void) { -+ log_info("/* %s */", __func__); -+ -+ const char *w; -+ -+ assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), NULL)); -+ -+ assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("a", "b"), &w)); -+ assert_se(streq(w, "a")); -+ -+ assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE("d"), &w)); -+ assert_se(w == NULL); -+ -+ assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", "a"), &w)); -+ assert_se(streq(w, "a")); -+ -+ assert_se(string_contains_word_strv("b a b cc", NULL, STRV_MAKE("b", "a", "b"), &w)); -+ assert_se(streq(w, "b")); -+ -+ assert_se(string_contains_word_strv("a b cc", NULL, STRV_MAKE("b", ""), &w)); -+ assert_se(streq(w, "b")); -+ -+ assert_se(!string_contains_word_strv("a b cc", NULL, STRV_MAKE(""), &w)); -+ assert_se(w == NULL); -+ -+ assert_se(string_contains_word_strv("a b cc", " ", STRV_MAKE(""), &w)); -+ assert_se(streq(w, "")); -+} -+ -+static void test_string_contains_word(void) { -+ log_info("/* %s */", __func__); -+ -+ assert_se( string_contains_word("a b cc", NULL, "a")); -+ assert_se( string_contains_word("a b cc", NULL, "b")); -+ assert_se(!string_contains_word("a b cc", NULL, "c")); -+ assert_se( string_contains_word("a b cc", NULL, "cc")); -+ assert_se(!string_contains_word("a b cc", NULL, "d")); -+ assert_se(!string_contains_word("a b cc", NULL, "a b")); -+ assert_se(!string_contains_word("a b cc", NULL, "a b c")); -+ assert_se(!string_contains_word("a b cc", NULL, "b c")); -+ assert_se(!string_contains_word("a b cc", NULL, "b cc")); -+ assert_se(!string_contains_word("a b cc", NULL, "a ")); -+ assert_se(!string_contains_word("a b cc", NULL, " b ")); -+ assert_se(!string_contains_word("a b cc", NULL, " cc")); -+ -+ assert_se( string_contains_word(" a b\t\tcc", NULL, "a")); -+ assert_se( string_contains_word(" a b\t\tcc", NULL, "b")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, "c")); -+ assert_se( string_contains_word(" a b\t\tcc", NULL, "cc")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, "d")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, "a b")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, "a b\t\tc")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, "b\t\tc")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, "b\t\tcc")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, "a ")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, " b ")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, " cc")); -+ -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, "")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, " ")); -+ assert_se(!string_contains_word(" a b\t\tcc", NULL, " ")); -+ assert_se( string_contains_word(" a b\t\tcc", " ", "")); -+ assert_se( string_contains_word(" a b\t\tcc", "\t", "")); -+ assert_se( string_contains_word(" a b\t\tcc", WHITESPACE, "")); -+ -+ assert_se( string_contains_word("a:b:cc", ":#", "a")); -+ assert_se( string_contains_word("a:b:cc", ":#", "b")); -+ assert_se(!string_contains_word("a:b:cc", ":#", "c")); -+ assert_se( string_contains_word("a:b:cc", ":#", "cc")); -+ assert_se(!string_contains_word("a:b:cc", ":#", "d")); -+ assert_se(!string_contains_word("a:b:cc", ":#", "a:b")); -+ assert_se(!string_contains_word("a:b:cc", ":#", "a:b:c")); -+ assert_se(!string_contains_word("a:b:cc", ":#", "b:c")); -+ assert_se(!string_contains_word("a#b#cc", ":#", "b:cc")); -+ assert_se( string_contains_word("a#b#cc", ":#", "b")); -+ assert_se( string_contains_word("a#b#cc", ":#", "cc")); -+ assert_se(!string_contains_word("a:b:cc", ":#", "a:")); -+ assert_se(!string_contains_word("a:b cc", ":#", "b")); -+ assert_se( string_contains_word("a:b cc", ":#", "b cc")); -+ assert_se(!string_contains_word("a:b:cc", ":#", ":cc")); -+} -+ - int main(int argc, char *argv[]) { - test_setup_logging(LOG_DEBUG); - -@@ -727,6 +903,7 @@ int main(int argc, char *argv[]) { - test_ascii_strlower(); - test_strshorten(); - test_strjoina(); -+ test_strjoin(); - test_strcmp_ptr(); - test_foreach_word(); - test_foreach_word_quoted(); -@@ -744,6 +921,8 @@ int main(int argc, char *argv[]) { - test_memory_startswith_no_case(); - test_string_truncate_lines(); - test_string_extract_line(); -+ test_string_contains_word_strv(); -+ test_string_contains_word(); - - return 0; - } -diff --git a/src/test/test-strv.c b/src/test/test-strv.c -index cba5441..558ffee 100644 ---- a/src/test/test-strv.c -+++ b/src/test/test-strv.c -@@ -100,6 +100,12 @@ static const char* const input_table_quoted[] = { - NULL, - }; - -+static const char* const input_table_quoted_joined[] = { -+ "one", -+ " two\t three " " four five", -+ NULL, -+}; -+ - static const char* const input_table_one[] = { - "one", - NULL, -@@ -232,7 +238,7 @@ static void test_strv_unquote(const char *quoted, char **list) { - - log_info("/* %s */", __func__); - -- r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); -+ r = strv_split_full(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); - assert_se(r == (int) strv_length(list)); - assert_se(s); - j = strv_join(s, " | "); -@@ -251,7 +257,7 @@ static void test_invalid_unquote(const char *quoted) { - - log_info("/* %s */", __func__); - -- r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); -+ r = strv_split_full(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); - assert_se(s == NULL); - assert_se(r == -EINVAL); - } -@@ -281,47 +287,39 @@ static void test_strv_split(void) { - - strv_free_erase(l); - -- l = strv_split_full(" one two\t three", NULL, 0); -- assert_se(l); -+ assert_se(strv_split_full(&l, " one two\t three", NULL, 0) == 3); - assert_se(strv_equal(l, (char**) input_table_multiple)); - - strv_free_erase(l); - -- l = strv_split_full(" 'one' \" two\t three \" ' four five'", NULL, SPLIT_QUOTES); -- assert_se(l); -+ assert_se(strv_split_full(&l, " 'one' \" two\t three \" ' four five'", NULL, EXTRACT_UNQUOTE) == 3); - assert_se(strv_equal(l, (char**) input_table_quoted)); - -- strv_free_erase(l); -+ l = strv_free_erase(l); - -- /* missing last quote ignores the last element. */ -- l = strv_split_full(" 'one' \" two\t three \" ' four five' ' ignored element ", NULL, SPLIT_QUOTES); -- assert_se(l); -- assert_se(strv_equal(l, (char**) input_table_quoted)); -- -- strv_free_erase(l); -+ /* missing last quote causes extraction to fail. */ -+ assert_se(strv_split_full(&l, " 'one' \" two\t three \" ' four five", NULL, EXTRACT_UNQUOTE) == -EINVAL); -+ assert_se(!l); - -- /* missing last quote, but the last element is _not_ ignored with SPLIT_RELAX. */ -- l = strv_split_full(" 'one' \" two\t three \" ' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX); -- assert_se(l); -+ /* missing last quote, but the last element is _not_ ignored with EXTRACT_RELAX. */ -+ assert_se(strv_split_full(&l, " 'one' \" two\t three \" ' four five", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 3); - assert_se(strv_equal(l, (char**) input_table_quoted)); - -- strv_free_erase(l); -+ l = strv_free_erase(l); - -- /* missing separator between */ -- l = strv_split_full(" 'one' \" two\t three \"' four five'", NULL, SPLIT_QUOTES | SPLIT_RELAX); -- assert_se(l); -- assert_se(strv_equal(l, (char**) input_table_quoted)); -+ /* missing separator between items */ -+ assert_se(strv_split_full(&l, " 'one' \" two\t three \"' four five'", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 2); -+ assert_se(strv_equal(l, (char**) input_table_quoted_joined)); - -- strv_free_erase(l); -+ l = strv_free_erase(l); - -- l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX); -- assert_se(l); -- assert_se(strv_equal(l, (char**) input_table_quoted)); -+ assert_se(strv_split_full(&l, " 'one' \" two\t three \"' four five", NULL, -+ EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_CUNESCAPE_RELAX) == 2); -+ assert_se(strv_equal(l, (char**) input_table_quoted_joined)); - -- strv_free_erase(l); -+ l = strv_free_erase(l); - -- l = strv_split_full("\\", NULL, SPLIT_QUOTES | SPLIT_RELAX); -- assert_se(l); -+ assert_se(strv_split_full(&l, "\\", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_CUNESCAPE_RELAX) == 1); - assert_se(strv_equal(l, STRV_MAKE("\\"))); - } - -@@ -333,71 +331,70 @@ static void test_strv_split_empty(void) { - l = strv_split("", WHITESPACE); - assert_se(l); - assert_se(strv_isempty(l)); -+ l = strv_free(l); - -- strv_free(l); -- l = strv_split("", NULL); -- assert_se(l); -+ assert_se(l = strv_split("", NULL)); - assert_se(strv_isempty(l)); -+ l = strv_free(l); - -- strv_free(l); -- l = strv_split_full("", NULL, 0); -+ assert_se(strv_split_full(&l, "", NULL, 0) == 0); - assert_se(l); - assert_se(strv_isempty(l)); -+ l = strv_free(l); - -- strv_free(l); -- l = strv_split_full("", NULL, SPLIT_QUOTES); -+ assert_se(strv_split_full(&l, "", NULL, EXTRACT_UNQUOTE) == 0); - assert_se(l); - assert_se(strv_isempty(l)); -+ l = strv_free(l); - -- strv_free(l); -- l = strv_split_full("", WHITESPACE, SPLIT_QUOTES); -+ assert_se(strv_split_full(&l, "", WHITESPACE, EXTRACT_UNQUOTE) == 0); - assert_se(l); - assert_se(strv_isempty(l)); -+ l = strv_free(l); - -- strv_free(l); -- l = strv_split_full("", WHITESPACE, SPLIT_QUOTES | SPLIT_RELAX); -+ assert_se(strv_split_full(&l, "", WHITESPACE, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 0); - assert_se(l); - assert_se(strv_isempty(l)); -- - strv_free(l); -+ - l = strv_split(" ", WHITESPACE); - assert_se(l); - assert_se(strv_isempty(l)); -- - strv_free(l); -+ - l = strv_split(" ", NULL); - assert_se(l); - assert_se(strv_isempty(l)); -+ l = strv_free(l); - -- strv_free(l); -- l = strv_split_full(" ", NULL, 0); -+ assert_se(strv_split_full(&l, " ", NULL, 0) == 0); - assert_se(l); - assert_se(strv_isempty(l)); -+ l = strv_free(l); - -- strv_free(l); -- l = strv_split_full(" ", WHITESPACE, SPLIT_QUOTES); -+ assert_se(strv_split_full(&l, " ", WHITESPACE, EXTRACT_UNQUOTE) == 0); - assert_se(l); - assert_se(strv_isempty(l)); -+ l = strv_free(l); - -- strv_free(l); -- l = strv_split_full(" ", NULL, SPLIT_QUOTES); -+ assert_se(strv_split_full(&l, " ", NULL, EXTRACT_UNQUOTE) == 0); - assert_se(l); - assert_se(strv_isempty(l)); -+ l = strv_free(l); - -- strv_free(l); -- l = strv_split_full(" ", NULL, SPLIT_QUOTES | SPLIT_RELAX); -+ assert_se(strv_split_full(&l, " ", NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX) == 0); - assert_se(l); - assert_se(strv_isempty(l)); - } - --static void test_strv_split_extract(void) { -+static void test_strv_split_full(void) { - _cleanup_strv_free_ char **l = NULL; - const char *str = ":foo\\:bar::waldo:"; - int r; - - log_info("/* %s */", __func__); - -- r = strv_split_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS); -+ r = strv_split_full(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS); - assert_se(r == (int) strv_length(l)); - assert_se(streq_ptr(l[0], "")); - assert_se(streq_ptr(l[1], "foo:bar")); -@@ -407,6 +404,35 @@ static void test_strv_split_extract(void) { - assert_se(streq_ptr(l[5], NULL)); - } - -+static void test_strv_split_colon_pairs(void) { -+ _cleanup_strv_free_ char **l = NULL; -+ const char *str = "one:two three four:five six seven:eight\\:nine ten\\:eleven\\\\", -+ *str_inval="one:two three:four:five"; -+ int r; -+ -+ log_info("/* %s */", __func__); -+ -+ r = strv_split_colon_pairs(&l, str); -+ assert_se(r == (int) strv_length(l)); -+ assert_se(r == 12); -+ assert_se(streq_ptr(l[0], "one")); -+ assert_se(streq_ptr(l[1], "two")); -+ assert_se(streq_ptr(l[2], "three")); -+ assert_se(streq_ptr(l[3], "")); -+ assert_se(streq_ptr(l[4], "four")); -+ assert_se(streq_ptr(l[5], "five")); -+ assert_se(streq_ptr(l[6], "six")); -+ assert_se(streq_ptr(l[7], "")); -+ assert_se(streq_ptr(l[8], "seven")); -+ assert_se(streq_ptr(l[9], "eight:nine")); -+ assert_se(streq_ptr(l[10], "ten:eleven\\")); -+ assert_se(streq_ptr(l[11], "")); -+ assert_se(streq_ptr(l[12], NULL)); -+ -+ r = strv_split_colon_pairs(&l, str_inval); -+ assert_se(r == -EINVAL); -+} -+ - static void test_strv_split_newlines(void) { - unsigned i = 0; - char **s; -@@ -997,7 +1023,8 @@ int main(int argc, char *argv[]) { - - test_strv_split(); - test_strv_split_empty(); -- test_strv_split_extract(); -+ test_strv_split_full(); -+ test_strv_split_colon_pairs(); - test_strv_split_newlines(); - test_strv_split_nulstr(); - test_strv_parse_nulstr(); -diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c -index 52e651f..0032571 100644 ---- a/src/test/test-terminal-util.c -+++ b/src/test/test-terminal-util.c -@@ -15,6 +15,12 @@ - #include "tmpfile-util.h" - #include "util.h" - -+#define LOREM_IPSUM "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor " \ -+ "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation " \ -+ "ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit " \ -+ "in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat " \ -+ "non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." -+ - static void test_default_term_for_tty(void) { - log_info("/* %s */", __func__); - -@@ -75,36 +81,76 @@ static void test_getttyname_malloc(void) { - assert_se(PATH_IN_SET(ttyname, "ptmx", "pts/ptmx")); - } - --static void test_one_color(const char *name, const char *color) { -- printf("<%s%s%s>\n", color, name, ansi_normal()); --} -+typedef struct { -+ const char *name; -+ const char* (*func)(void); -+} Color; -+ -+static const Color colors[] = { -+ { "normal", ansi_normal }, -+ { "highlight", ansi_highlight }, -+ { "black", ansi_black }, -+ { "red", ansi_red }, -+ { "green", ansi_green }, -+ { "yellow", ansi_yellow }, -+ { "blue", ansi_blue }, -+ { "magenta", ansi_magenta }, -+ { "cyan", ansi_cyan }, -+ { "white", ansi_white }, -+ { "grey", ansi_grey }, -+ -+ { "bright-black", ansi_bright_black }, -+ { "bright-red", ansi_bright_red }, -+ { "bright-green", ansi_bright_green }, -+ { "bright-yellow", ansi_bright_yellow }, -+ { "bright-blue", ansi_bright_blue }, -+ { "bright-magenta", ansi_bright_magenta }, -+ { "bright-cyan", ansi_bright_cyan }, -+ { "bright-white", ansi_bright_white }, -+ -+ { "highlight-black", ansi_highlight_black }, -+ { "highlight-red", ansi_highlight_red }, -+ { "highlight-green", ansi_highlight_green }, -+ { "highlight-yellow (original)", _ansi_highlight_yellow }, -+ { "highlight-yellow (replacement)", ansi_highlight_yellow }, -+ { "highlight-blue", ansi_highlight_blue }, -+ { "highlight-magenta", ansi_highlight_magenta }, -+ { "highlight-cyan", ansi_highlight_cyan }, -+ { "highlight-white", ansi_highlight_white }, -+ { "highlight-grey", ansi_highlight_grey }, -+ -+ { "underline", ansi_underline }, -+ { "highlight-underline", ansi_highlight_underline }, -+ { "highlight-red-underline", ansi_highlight_red_underline }, -+ { "highlight-green-underline", ansi_highlight_green_underline }, -+ { "highlight-yellow-underline", ansi_highlight_yellow_underline }, -+ { "highlight-blue-underline", ansi_highlight_blue_underline }, -+ { "highlight-magenta-underline", ansi_highlight_magenta_underline }, -+ { "highlight-grey-underline", ansi_highlight_grey_underline }, -+}; - - static void test_colors(void) { - log_info("/* %s */", __func__); - -- test_one_color("normal", ansi_normal()); -- test_one_color("highlight", ansi_highlight()); -- test_one_color("red", ansi_red()); -- test_one_color("green", ansi_green()); -- test_one_color("yellow", ansi_yellow()); -- test_one_color("blue", ansi_blue()); -- test_one_color("magenta", ansi_magenta()); -- test_one_color("grey", ansi_grey()); -- test_one_color("highlight-red", ansi_highlight_red()); -- test_one_color("highlight-green", ansi_highlight_green()); -- test_one_color("highlight-yellow", ansi_highlight_yellow()); -- test_one_color("highlight-blue", ansi_highlight_blue()); -- test_one_color("highlight-magenta", ansi_highlight_magenta()); -- test_one_color("highlight-grey", ansi_highlight_grey()); -- -- test_one_color("underline", ansi_underline()); -- test_one_color("highlight-underline", ansi_highlight_underline()); -- test_one_color("highlight-red-underline", ansi_highlight_red_underline()); -- test_one_color("highlight-green-underline", ansi_highlight_green_underline()); -- test_one_color("highlight-yellow-underline", ansi_highlight_yellow_underline()); -- test_one_color("highlight-blue-underline", ansi_highlight_blue_underline()); -- test_one_color("highlight-magenta-underline", ansi_highlight_magenta_underline()); -- test_one_color("highlight-grey-underline", ansi_highlight_grey_underline()); -+ for (size_t i = 0; i < ELEMENTSOF(colors); i++) -+ printf("<%s%s%s>\n", colors[i].func(), colors[i].name, ansi_normal()); -+} -+ -+static void test_text(void) { -+ log_info("/* %s */", __func__); -+ -+ for (size_t i = 0; !streq(colors[i].name, "underline"); i++) { -+ bool blwh = strstr(colors[i].name, "black") -+ || strstr(colors[i].name, "white"); -+ -+ printf("\n" -+ "Testing color %s%s\n%s%s%s\n", -+ colors[i].name, -+ blwh ? "" : ", this text should be readable", -+ colors[i].func(), -+ LOREM_IPSUM, -+ ansi_normal()); -+ } - } - - int main(int argc, char *argv[]) { -@@ -114,6 +160,7 @@ int main(int argc, char *argv[]) { - test_read_one_char(); - test_getttyname_malloc(); - test_colors(); -+ test_text(); - - return 0; - } -diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c -index 8826956..6424295 100644 ---- a/src/test/test-time-util.c -+++ b/src/test/test-time-util.c -@@ -333,17 +333,17 @@ static void test_format_timestamp(void) { - assert_se(parse_timestamp(buf, &y) >= 0); - assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC); - -- assert_se(format_timestamp_utc(buf, sizeof(buf), x)); -+ assert_se(format_timestamp_style(buf, sizeof(buf), x, TIMESTAMP_UTC)); - log_info("%s", buf); - assert_se(parse_timestamp(buf, &y) >= 0); - assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC); - -- assert_se(format_timestamp_us(buf, sizeof(buf), x)); -+ assert_se(format_timestamp_style(buf, sizeof(buf), x, TIMESTAMP_US)); - log_info("%s", buf); - assert_se(parse_timestamp(buf, &y) >= 0); - assert_se(x == y); - -- assert_se(format_timestamp_us_utc(buf, sizeof(buf), x)); -+ assert_se(format_timestamp_style(buf, sizeof(buf), x, TIMESTAMP_US_UTC)); - log_info("%s", buf); - assert_se(parse_timestamp(buf, &y) >= 0); - assert_se(x == y); -@@ -364,7 +364,7 @@ static void test_format_timestamp_utc_one(usec_t val, const char *result) { - char buf[FORMAT_TIMESTAMP_MAX]; - const char *t; - -- t = format_timestamp_utc(buf, sizeof(buf), val); -+ t = format_timestamp_style(buf, sizeof(buf), val, TIMESTAMP_UTC); - assert_se(streq_ptr(t, result)); - } - -diff --git a/src/test/test-udev.c b/src/test/test-udev.c -index c0b215d..006fdb6 100644 ---- a/src/test/test-udev.c -+++ b/src/test/test-udev.c -@@ -17,6 +17,7 @@ - #include "log.h" - #include "main-func.h" - #include "mkdir.h" -+#include "mount-util.h" - #include "namespace-util.h" - #include "selinux-util.h" - #include "signal-util.h" -@@ -43,12 +44,12 @@ static int fake_filesystems(void) { - if (r < 0) - return log_error_errno(r, "Failed to detach mount namespace: %m"); - -- for (size_t i = 0; i < ELEMENTSOF(fakefss); i++) -- if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) { -- log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error); -- if (!fakefss[i].ignore_mount_error) -- return -errno; -- } -+ for (size_t i = 0; i < ELEMENTSOF(fakefss); i++) { -+ r = mount_verbose(fakefss[i].ignore_mount_error ? LOG_NOTICE : LOG_ERR, -+ fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL); -+ if (r < 0 && !fakefss[i].ignore_mount_error) -+ return r; -+ } - - return 0; - } -@@ -62,20 +63,24 @@ static int run(int argc, char *argv[]) { - - test_setup_logging(LOG_INFO); - -- if (!IN_SET(argc, 2, 3)) { -- log_error("This program needs one or two arguments, %d given", argc - 1); -- return -EINVAL; -- } -+ if (!IN_SET(argc, 2, 3)) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "This program needs one or two arguments, %d given", argc - 1); - - r = fake_filesystems(); - if (r < 0) - return r; - -+ /* Let's make sure the test runs with selinux assumed disabled. */ -+#if HAVE_SELINUX -+ fini_selinuxmnt(); -+#endif -+ mac_selinux_retest(); -+ - if (argc == 2) { -- if (!streq(argv[1], "check")) { -- log_error("Unknown argument: %s", argv[1]); -- return -EINVAL; -- } -+ if (!streq(argv[1], "check")) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "Unknown argument: %s", argv[1]); - - return 0; - } -@@ -91,7 +96,8 @@ static int run(int argc, char *argv[]) { - - assert_se(udev_rules_load(&rules, RESOLVE_NAME_EARLY) == 0); - -- const char *syspath = strjoina("/sys", devpath); -+ const char *syspath; -+ syspath = strjoina("/sys", devpath); - r = device_new_from_synthetic_event(&dev, syspath, action); - if (r < 0) - return log_debug_errno(r, "Failed to open device '%s'", devpath); -diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c -index 6021164..d1f85a7 100644 ---- a/src/test/test-unit-file.c -+++ b/src/test/test-unit-file.c -@@ -30,7 +30,6 @@ static void test_unit_file_build_name_map(char **ids) { - _cleanup_(lookup_paths_free) LookupPaths lp = {}; - _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; - _cleanup_hashmap_free_ Hashmap *unit_names = NULL; -- Iterator i; - const char *k, *dst; - char **v; - usec_t mtime = 0; -@@ -40,10 +39,10 @@ static void test_unit_file_build_name_map(char **ids) { - - assert_se(unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL) == 1); - -- HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) -+ HASHMAP_FOREACH_KEY(dst, k, unit_ids) - log_info("ids: %s → %s", k, dst); - -- HASHMAP_FOREACH_KEY(v, k, unit_names, i) { -+ HASHMAP_FOREACH_KEY(v, k, unit_names) { - _cleanup_free_ char *j = strv_join(v, ", "); - log_info("aliases: %s ← %s", k, j); - } -@@ -59,7 +58,6 @@ static void test_unit_file_build_name_map(char **ids) { - char **id; - STRV_FOREACH(id, ids) { - const char *fragment, *name; -- Iterator it; - _cleanup_set_free_free_ Set *names = NULL; - log_info("*** %s ***", *id); - r = unit_file_find_fragment(unit_ids, -@@ -70,7 +68,7 @@ static void test_unit_file_build_name_map(char **ids) { - assert(r == 0); - log_info("fragment: %s", fragment); - log_info("names:"); -- SET_FOREACH(name, names, it) -+ SET_FOREACH(name, names) - log_info(" %s", name); - } - } -diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c -index c9bff94..306d08a 100644 ---- a/src/test/test-user-util.c -+++ b/src/test/test-user-util.c -@@ -452,6 +452,25 @@ static void test_parse_uid_range(void) { - assert_se(parse_uid_range(" 01", &a, &b) == -EINVAL && a == 4 && b == 5); - } - -+static void test_mangle_gecos_one(const char *input, const char *expected) { -+ _cleanup_free_ char *p = NULL; -+ -+ assert_se(p = mangle_gecos(input)); -+ assert_se(streq(p, expected)); -+ assert_se(valid_gecos(p)); -+} -+ -+static void test_mangle_gecos(void) { -+ test_mangle_gecos_one("", ""); -+ test_mangle_gecos_one("root", "root"); -+ test_mangle_gecos_one("wuff\nwuff", "wuff wuff"); -+ test_mangle_gecos_one("wuff:wuff", "wuff wuff"); -+ test_mangle_gecos_one("wuff\r\n:wuff", "wuff wuff"); -+ test_mangle_gecos_one("\n--wüff-wäff-wöff::", " --wüff-wäff-wöff "); -+ test_mangle_gecos_one("\xc3\x28", " ("); -+ test_mangle_gecos_one("\xe2\x28\xa1", " ( "); -+} -+ - int main(int argc, char *argv[]) { - test_uid_to_name_one(0, "root"); - test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME); -@@ -482,6 +501,7 @@ int main(int argc, char *argv[]) { - test_valid_user_group_name_or_numeric_relaxed(); - test_valid_user_group_name_or_numeric(); - test_valid_gecos(); -+ test_mangle_gecos(); - test_valid_home(); - - test_make_salt(); -diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c -index 8937f56..66003ac 100644 ---- a/src/test/test-utf8.c -+++ b/src/test/test-utf8.c -@@ -18,6 +18,25 @@ static void test_utf8_is_printable(void) { - assert_se(utf8_is_printable("\t", 1)); - } - -+static void test_utf8_n_is_valid(void) { -+ log_info("/* %s */", __func__); -+ -+ assert_se( utf8_is_valid_n("ascii is valid unicode", 21)); -+ assert_se( utf8_is_valid_n("ascii is valid unicode", 22)); -+ assert_se(!utf8_is_valid_n("ascii is valid unicode", 23)); -+ assert_se( utf8_is_valid_n("\342\204\242", 0)); -+ assert_se(!utf8_is_valid_n("\342\204\242", 1)); -+ assert_se(!utf8_is_valid_n("\342\204\242", 2)); -+ assert_se( utf8_is_valid_n("\342\204\242", 3)); -+ assert_se(!utf8_is_valid_n("\342\204\242", 4)); -+ assert_se( utf8_is_valid_n("", 0)); -+ assert_se( utf8_is_valid_n("", 1)); -+ assert_se( utf8_is_valid_n("", 2)); -+ assert_se( utf8_is_valid_n("", 3)); -+ assert_se( utf8_is_valid_n("", 4)); -+ assert_se(!utf8_is_valid_n("", 5)); -+} -+ - static void test_utf8_is_valid(void) { - log_info("/* %s */", __func__); - -@@ -216,6 +235,7 @@ static void test_utf8_to_utf16(void) { - } - - int main(int argc, char *argv[]) { -+ test_utf8_n_is_valid(); - test_utf8_is_valid(); - test_utf8_is_printable(); - test_ascii_is_valid(); -diff --git a/src/time-wait-sync/time-wait-sync.c b/src/time-wait-sync/time-wait-sync.c -index e880f9e..9607244 100644 ---- a/src/time-wait-sync/time-wait-sync.c -+++ b/src/time-wait-sync/time-wait-sync.c -@@ -155,7 +155,7 @@ static int clock_state_update( - if (tx.status & STA_NANO) - tx.time.tv_usec /= 1000; - t = timeval_load(&tx.time); -- ts = format_timestamp_us_utc(buf, sizeof(buf), t); -+ ts = format_timestamp_style(buf, sizeof(buf), t, TIMESTAMP_US_UTC); - if (!ts) - strcpy(buf, "unrepresentable"); - log_info("adjtime state %d status %x time %s", sp->adjtime_state, tx.status, ts); -diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c -index 7afc37d..0131bbe 100644 ---- a/src/timedate/timedatectl.c -+++ b/src/timedate/timedatectl.c -@@ -1005,7 +1005,7 @@ static int parse_argv(int argc, char *argv[]) { - return log_oom(); - - /* If the user asked for a particular -- * property, show it to him, even if it is -+ * property, show it to them, even if it is - * empty. */ - arg_all = true; - break; -diff --git a/src/timesync/timesyncd-conf.c b/src/timesync/timesyncd-conf.c -index 532d6ea..d7ec94e 100644 ---- a/src/timesync/timesyncd-conf.c -+++ b/src/timesync/timesyncd-conf.c -@@ -89,7 +89,8 @@ int config_parse_servers( - else { - r = manager_parse_server_string(m, ltype, rvalue); - if (r < 0) { -- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse NTP server string '%s'. Ignoring.", rvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, r, -+ "Failed to parse NTP server string '%s', ignoring: %m", rvalue); - return 0; - } - } -diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c -index 5570408..0fab37d 100644 ---- a/src/timesync/timesyncd-manager.c -+++ b/src/timesync/timesyncd-manager.c -@@ -180,18 +180,18 @@ static int manager_arm_timer(Manager *m, usec_t next) { - } - - if (m->event_timer) { -- r = sd_event_source_set_time(m->event_timer, now(clock_boottime_or_monotonic()) + next); -+ r = sd_event_source_set_time_relative(m->event_timer, next); - if (r < 0) - return r; - - return sd_event_source_set_enabled(m->event_timer, SD_EVENT_ONESHOT); - } - -- return sd_event_add_time( -+ return sd_event_add_time_relative( - m->event, - &m->event_timer, - clock_boottime_or_monotonic(), -- now(clock_boottime_or_monotonic()) + next, 0, -+ next, 0, - manager_timer, m); - } - -@@ -647,7 +647,8 @@ static int manager_listen_setup(Manager *m) { - if (r < 0) - return r; - -- (void) setsockopt_int(m->server_socket, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); -+ if (addr.sa.sa_family == AF_INET) -+ (void) setsockopt_int(m->server_socket, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); - - return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m); - } -@@ -786,7 +787,7 @@ int manager_connect(Manager *m) { - if (!ratelimit_below(&m->ratelimit)) { - log_debug("Delaying attempts to contact servers."); - -- r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + RETRY_USEC, 0, manager_retry_connect, m); -+ r = sd_event_add_time_relative(m->event, &m->event_retry, clock_boottime_or_monotonic(), RETRY_USEC, 0, manager_retry_connect, m); - if (r < 0) - return log_error_errno(r, "Failed to create retry timer: %m"); - -@@ -840,7 +841,7 @@ int manager_connect(Manager *m) { - - if (restart && !m->exhausted_servers && m->poll_interval_usec) { - log_debug("Waiting after exhausting servers."); -- r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + m->poll_interval_usec, 0, manager_retry_connect, m); -+ r = sd_event_add_time_relative(m->event, &m->event_retry, clock_boottime_or_monotonic(), m->poll_interval_usec, 0, manager_retry_connect, m); - if (r < 0) - return log_error_errno(r, "Failed to create retry timer: %m"); - -diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c -index 2404e36..b9b3700 100644 ---- a/src/tmpfiles/tmpfiles.c -+++ b/src/tmpfiles/tmpfiles.c -@@ -26,6 +26,7 @@ - #include "copy.h" - #include "def.h" - #include "dirent-util.h" -+#include "dissect-image.h" - #include "escape.h" - #include "fd-util.h" - #include "fileio.h" -@@ -37,7 +38,10 @@ - #include "log.h" - #include "macro.h" - #include "main-func.h" -+#include "missing_stat.h" -+#include "missing_syscall.h" - #include "mkdir.h" -+#include "mount-util.h" - #include "mountpoint-util.h" - #include "offline-passwd.h" - #include "pager.h" -@@ -164,6 +168,7 @@ static PagerFlags arg_pager_flags = 0; - static char **arg_include_prefixes = NULL; - static char **arg_exclude_prefixes = NULL; - static char *arg_root = NULL; -+static char *arg_image = NULL; - static char *arg_replace = NULL; - - #define MAX_DEPTH 256 -@@ -177,6 +182,7 @@ STATIC_DESTRUCTOR_REGISTER(unix_sockets, set_free_freep); - STATIC_DESTRUCTOR_REGISTER(arg_include_prefixes, freep); - STATIC_DESTRUCTOR_REGISTER(arg_exclude_prefixes, freep); - STATIC_DESTRUCTOR_REGISTER(arg_root, freep); -+STATIC_DESTRUCTOR_REGISTER(arg_image, freep); - - static int specifier_machine_id_safe(char specifier, const void *data, const void *userdata, char **ret); - static int specifier_directory(char specifier, const void *data, const void *userdata, char **ret); -@@ -369,9 +375,8 @@ static bool takes_ownership(ItemType t) { - - static struct Item* find_glob(OrderedHashmap *h, const char *match) { - ItemArray *j; -- Iterator i; - -- ORDERED_HASHMAP_FOREACH(j, h, i) { -+ ORDERED_HASHMAP_FOREACH(j, h) { - size_t n; - - for (n = 0; n < j->n_items; n++) { -@@ -486,60 +491,105 @@ static DIR* opendir_nomod(const char *path) { - return xopendirat_nomod(AT_FDCWD, path); - } - -+static inline nsec_t load_statx_timestamp_nsec(const struct statx_timestamp *ts) { -+ assert(ts); -+ -+ if (ts->tv_sec < 0) -+ return NSEC_INFINITY; -+ -+ if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC) -+ return NSEC_INFINITY; -+ -+ return ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec; -+} -+ - static int dir_cleanup( - Item *i, - const char *p, - DIR *d, -- const struct stat *ds, -- usec_t cutoff, -- dev_t rootdev, -+ nsec_t self_atime_nsec, -+ nsec_t self_mtime_nsec, -+ nsec_t cutoff_nsec, -+ dev_t rootdev_major, -+ dev_t rootdev_minor, - bool mountpoint, - int maxdepth, - bool keep_this_level) { - -- struct dirent *dent; - bool deleted = false; -+ struct dirent *dent; - int r = 0; - - FOREACH_DIRENT_ALL(dent, d, break) { -- struct stat s; -- usec_t age; - _cleanup_free_ char *sub_path = NULL; -+ nsec_t atime_nsec, mtime_nsec, ctime_nsec, btime_nsec; - - if (dot_or_dot_dot(dent->d_name)) - continue; - -- if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) { -- if (errno == ENOENT) -- continue; -- -+ /* If statx() is supported, use it. It's preferable over fstatat() since it tells us -+ * explicitly where we are looking at a mount point, for free as side information. Determining -+ * the same information without statx() is hard, see the complexity of path_is_mount_point(), -+ * and also much slower as it requires a number of syscalls instead of just one. Hence, when -+ * we have modern statx() we use it instead of fstat() and do proper mount point checks, -+ * while on older kernels's well do traditional st_dev based detection of mount points. -+ * -+ * Using statx() for detecting mount points also has the benfit that we handle weird file -+ * systems such as overlayfs better where each file is originating from a different -+ * st_dev. */ -+ -+ STRUCT_STATX_DEFINE(sx); -+ -+ r = statx_fallback( -+ dirfd(d), dent->d_name, -+ AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, -+ STATX_TYPE|STATX_MODE|STATX_UID|STATX_ATIME|STATX_MTIME|STATX_CTIME|STATX_BTIME, -+ &sx); -+ if (r == -ENOENT) -+ continue; -+ if (r < 0) { - /* FUSE, NFS mounts, SELinux might return EACCES */ - r = log_full_errno(errno == EACCES ? LOG_DEBUG : LOG_ERR, errno, -- "stat(%s/%s) failed: %m", p, dent->d_name); -+ "statx(%s/%s) failed: %m", p, dent->d_name); - continue; - } - -- /* Stay on the same filesystem */ -- if (s.st_dev != rootdev) { -- log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name); -- continue; -- } -- -- /* Try to detect bind mounts of the same filesystem instance; they -- * do not differ in device major/minors. This type of query is not -- * supported on all kernels or filesystem types though. */ -- if (S_ISDIR(s.st_mode)) { -- int q; -- -- q = fd_is_mount_point(dirfd(d), dent->d_name, 0); -- if (q < 0) -- log_debug_errno(q, "Failed to determine whether \"%s/%s\" is a mount point, ignoring: %m", p, dent->d_name); -- else if (q > 0) { -- log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.", p, dent->d_name); -+ if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) { -+ /* Yay, we have the mount point API, use it */ -+ if (FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT)) { -+ log_debug("Ignoring \"%s/%s\": different mount points.", p, dent->d_name); -+ continue; -+ } -+ } else { -+ /* So we might have statx() but the STATX_ATTR_MOUNT_ROOT flag is not supported, fall -+ * back to traditional stx_dev checking. */ -+ if (sx.stx_dev_major != rootdev_major || -+ sx.stx_dev_minor != rootdev_minor) { -+ log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name); - continue; - } -+ -+ /* Try to detect bind mounts of the same filesystem instance; they do not differ in device -+ * major/minors. This type of query is not supported on all kernels or filesystem types -+ * though. */ -+ if (S_ISDIR(sx.stx_mode)) { -+ int q; -+ -+ q = fd_is_mount_point(dirfd(d), dent->d_name, 0); -+ if (q < 0) -+ log_debug_errno(q, "Failed to determine whether \"%s/%s\" is a mount point, ignoring: %m", p, dent->d_name); -+ else if (q > 0) { -+ log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.", p, dent->d_name); -+ continue; -+ } -+ } - } - -+ atime_nsec = FLAGS_SET(sx.stx_mask, STATX_ATIME) ? load_statx_timestamp_nsec(&sx.stx_atime) : 0; -+ mtime_nsec = FLAGS_SET(sx.stx_mask, STATX_MTIME) ? load_statx_timestamp_nsec(&sx.stx_mtime) : 0; -+ ctime_nsec = FLAGS_SET(sx.stx_mask, STATX_CTIME) ? load_statx_timestamp_nsec(&sx.stx_ctime) : 0; -+ btime_nsec = FLAGS_SET(sx.stx_mask, STATX_BTIME) ? load_statx_timestamp_nsec(&sx.stx_btime) : 0; -+ - sub_path = path_join(p, dent->d_name); - if (!sub_path) { - r = log_oom(); -@@ -557,12 +607,12 @@ static int dir_cleanup( - continue; - } - -- if (S_ISDIR(s.st_mode)) { -+ if (S_ISDIR(sx.stx_mode)) { - _cleanup_closedir_ DIR *sub_dir = NULL; - - if (mountpoint && - streq(dent->d_name, "lost+found") && -- s.st_uid == 0) { -+ sx.stx_uid == 0) { - log_debug("Ignoring directory \"%s\".", sub_path); - continue; - } -@@ -585,7 +635,11 @@ static int dir_cleanup( - continue; - } - -- q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false); -+ q = dir_cleanup(i, -+ sub_path, sub_dir, -+ atime_nsec, mtime_nsec, cutoff_nsec, -+ rootdev_major, rootdev_minor, -+ false, maxdepth-1, false); - if (q < 0) - r = q; - } -@@ -601,22 +655,28 @@ static int dir_cleanup( - } - - /* Ignore ctime, we change it when deleting */ -- age = timespec_load(&s.st_mtim); -- if (age >= cutoff) { -+ if (mtime_nsec != NSEC_INFINITY && mtime_nsec >= cutoff_nsec) { - char a[FORMAT_TIMESTAMP_MAX]; - /* Follows spelling in stat(1). */ - log_debug("Directory \"%s\": modify time %s is too new.", - sub_path, -- format_timestamp_us(a, sizeof(a), age)); -+ format_timestamp_style(a, sizeof(a), mtime_nsec / NSEC_PER_USEC, TIMESTAMP_US)); - continue; - } - -- age = timespec_load(&s.st_atim); -- if (age >= cutoff) { -+ if (atime_nsec != NSEC_INFINITY && atime_nsec >= cutoff_nsec) { - char a[FORMAT_TIMESTAMP_MAX]; - log_debug("Directory \"%s\": access time %s is too new.", - sub_path, -- format_timestamp_us(a, sizeof(a), age)); -+ format_timestamp_style(a, sizeof(a), atime_nsec / NSEC_PER_USEC, TIMESTAMP_US)); -+ continue; -+ } -+ -+ if (btime_nsec != NSEC_INFINITY && btime_nsec >= cutoff_nsec) { -+ char a[FORMAT_TIMESTAMP_MAX]; -+ log_debug("Directory \"%s\": birth time %s is too new.", -+ sub_path, -+ format_timestamp_style(a, sizeof(a), btime_nsec / NSEC_PER_USEC, TIMESTAMP_US)); - continue; - } - -@@ -628,14 +688,14 @@ static int dir_cleanup( - } else { - /* Skip files for which the sticky bit is set. These are semantics we define, and are - * unknown elsewhere. See XDG_RUNTIME_DIR specification for details. */ -- if (s.st_mode & S_ISVTX) { -+ if (sx.stx_mode & S_ISVTX) { - log_debug("Skipping \"%s\": sticky bit set.", sub_path); - continue; - } - - if (mountpoint && -- S_ISREG(s.st_mode) && -- s.st_uid == 0 && -+ S_ISREG(sx.stx_mode) && -+ sx.stx_uid == 0 && - STR_IN_SET(dent->d_name, - ".journal", - "aquota.user", -@@ -645,13 +705,13 @@ static int dir_cleanup( - } - - /* Ignore sockets that are listed in /proc/net/unix */ -- if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) { -+ if (S_ISSOCK(sx.stx_mode) && unix_socket_alive(sub_path)) { - log_debug("Skipping \"%s\": live socket.", sub_path); - continue; - } - - /* Ignore device nodes */ -- if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) { -+ if (S_ISCHR(sx.stx_mode) || S_ISBLK(sx.stx_mode)) { - log_debug("Skipping \"%s\": a device.", sub_path); - continue; - } -@@ -662,31 +722,36 @@ static int dir_cleanup( - continue; - } - -- age = timespec_load(&s.st_mtim); -- if (age >= cutoff) { -+ if (mtime_nsec != NSEC_INFINITY && mtime_nsec >= cutoff_nsec) { - char a[FORMAT_TIMESTAMP_MAX]; - /* Follows spelling in stat(1). */ - log_debug("File \"%s\": modify time %s is too new.", - sub_path, -- format_timestamp_us(a, sizeof(a), age)); -+ format_timestamp_style(a, sizeof(a), mtime_nsec / NSEC_PER_USEC, TIMESTAMP_US)); - continue; - } - -- age = timespec_load(&s.st_atim); -- if (age >= cutoff) { -+ if (atime_nsec != NSEC_INFINITY && atime_nsec >= cutoff_nsec) { - char a[FORMAT_TIMESTAMP_MAX]; - log_debug("File \"%s\": access time %s is too new.", - sub_path, -- format_timestamp_us(a, sizeof(a), age)); -+ format_timestamp_style(a, sizeof(a), atime_nsec / NSEC_PER_USEC, TIMESTAMP_US)); - continue; - } - -- age = timespec_load(&s.st_ctim); -- if (age >= cutoff) { -+ if (ctime_nsec != NSEC_INFINITY && ctime_nsec >= cutoff_nsec) { - char a[FORMAT_TIMESTAMP_MAX]; - log_debug("File \"%s\": change time %s is too new.", - sub_path, -- format_timestamp_us(a, sizeof(a), age)); -+ format_timestamp_style(a, sizeof(a), ctime_nsec / NSEC_PER_USEC, TIMESTAMP_US)); -+ continue; -+ } -+ -+ if (btime_nsec != NSEC_INFINITY && btime_nsec >= cutoff_nsec) { -+ char a[FORMAT_TIMESTAMP_MAX]; -+ log_debug("File \"%s\": birth time %s is too new.", -+ sub_path, -+ format_timestamp_style(a, sizeof(a), btime_nsec / NSEC_PER_USEC, TIMESTAMP_US)); - continue; - } - -@@ -701,21 +766,19 @@ static int dir_cleanup( - - finish: - if (deleted) { -- char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX]; -- usec_t age1, age2; -- -- age1 = timespec_load(&ds->st_atim); -- age2 = timespec_load(&ds->st_mtim); -+ char a[FORMAT_TIMESTAMP_MAX], m[FORMAT_TIMESTAMP_MAX]; -+ struct timespec ts[2]; - - log_debug("Restoring access and modification time on \"%s\": %s, %s", - p, -- format_timestamp_us(a, sizeof(a), age1), -- format_timestamp_us(b, sizeof(b), age2)); -+ format_timestamp_style(a, sizeof(a), self_atime_nsec / NSEC_PER_USEC, TIMESTAMP_US), -+ format_timestamp_style(m, sizeof(m), self_mtime_nsec / NSEC_PER_USEC, TIMESTAMP_US)); -+ -+ timespec_store_nsec(ts + 0, self_atime_nsec); -+ timespec_store_nsec(ts + 1, self_mtime_nsec); - - /* Restore original directory timestamps */ -- if (futimens(dirfd(d), (struct timespec[]) { -- ds->st_atim, -- ds->st_mtim }) < 0) -+ if (futimens(dirfd(d), ts) < 0) - log_warning_errno(errno, "Failed to revert timestamps of '%s', ignoring: %m", p); - } - -@@ -773,6 +836,7 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st - struct stat stbuf; - mode_t new_mode; - bool do_chown; -+ int r; - - assert(i); - assert(fd); -@@ -818,8 +882,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st - log_debug("\"%s\" matches temporary mode %o already.", path, m); - else { - log_debug("Temporarily changing \"%s\" to mode %o.", path, m); -- if (fchmod_opath(fd, m) < 0) -- return log_error_errno(errno, "fchmod() of %s failed: %m", path); -+ r = fchmod_opath(fd, m); -+ if (r < 0) -+ return log_error_errno(r, "fchmod() of %s failed: %m", path); - } - } - } -@@ -850,8 +915,9 @@ static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st - log_debug("\"%s\" matches mode %o already.", path, new_mode); - else { - log_debug("Changing \"%s\" to mode %o.", path, new_mode); -- if (fchmod_opath(fd, new_mode) < 0) -- return log_error_errno(errno, "fchmod() of %s failed: %m", path); -+ r = fchmod_opath(fd, new_mode); -+ if (r < 0) -+ return log_error_errno(r, "fchmod() of %s failed: %m", path); - } - } - } -@@ -1477,7 +1543,7 @@ static int copy_files(Item *i) { - dfd, bn, - i->uid_set ? i->uid : UID_INVALID, - i->gid_set ? i->gid : GID_INVALID, -- COPY_REFLINK | COPY_MERGE_EMPTY | COPY_MAC_CREATE); -+ COPY_REFLINK | COPY_MERGE_EMPTY | COPY_MAC_CREATE | COPY_HARDLINKS); - if (r < 0) { - struct stat a, b; - -@@ -2182,11 +2248,11 @@ static int remove_item(Item *i) { - } - - static int clean_item_instance(Item *i, const char* instance) { -+ char timestamp[FORMAT_TIMESTAMP_MAX]; - _cleanup_closedir_ DIR *d = NULL; -- struct stat s, ps; -- bool mountpoint; -+ STRUCT_STATX_DEFINE(sx); -+ int mountpoint, r; - usec_t cutoff, n; -- char timestamp[FORMAT_TIMESTAMP_MAX]; - - assert(i); - -@@ -2209,24 +2275,34 @@ static int clean_item_instance(Item *i, const char* instance) { - return log_error_errno(errno, "Failed to open directory %s: %m", instance); - } - -- if (fstat(dirfd(d), &s) < 0) -- return log_error_errno(errno, "stat(%s) failed: %m", i->path); -+ r = statx_fallback(dirfd(d), "", AT_EMPTY_PATH, STATX_MODE|STATX_INO|STATX_ATIME|STATX_MTIME, &sx); -+ if (r < 0) -+ return log_error_errno(r, "statx(%s) failed: %m", instance); - -- if (!S_ISDIR(s.st_mode)) -- return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), -- "%s is not a directory.", i->path); -+ if (FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) -+ mountpoint = FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT); -+ else { -+ struct stat ps; - -- if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) -- return log_error_errno(errno, "stat(%s/..) failed: %m", i->path); -+ if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) -+ return log_error_errno(errno, "stat(%s/..) failed: %m", i->path); - -- mountpoint = s.st_dev != ps.st_dev || s.st_ino == ps.st_ino; -+ mountpoint = -+ sx.stx_dev_major != major(ps.st_dev) || -+ sx.stx_dev_minor != minor(ps.st_dev) || -+ sx.stx_ino != ps.st_ino; -+ } - - log_debug("Cleanup threshold for %s \"%s\" is %s", - mountpoint ? "mount point" : "directory", - instance, -- format_timestamp_us(timestamp, sizeof(timestamp), cutoff)); -+ format_timestamp_style(timestamp, sizeof(timestamp), cutoff, TIMESTAMP_US)); - -- return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint, -+ return dir_cleanup(i, instance, d, -+ load_statx_timestamp_nsec(&sx.stx_atime), -+ load_statx_timestamp_nsec(&sx.stx_mtime), -+ cutoff * NSEC_PER_USEC, -+ sx.stx_dev_major, sx.stx_dev_minor, mountpoint, - MAX_DEPTH, i->keep_first_level); - } - -@@ -2298,10 +2374,9 @@ static int process_item_array(ItemArray *array, OperationMask operation) { - - /* Clean up all children first */ - if ((operation & (OPERATION_REMOVE|OPERATION_CLEAN)) && !set_isempty(array->children)) { -- Iterator i; - ItemArray *c; - -- SET_FOREACH(c, array->children, i) { -+ SET_FOREACH(c, array->children) { - int k; - - k = process_item_array(c, operation & (OPERATION_REMOVE|OPERATION_CLEAN)); -@@ -2884,6 +2959,27 @@ static int cat_config(char **config_dirs, char **args) { - return cat_files(NULL, files, 0); - } - -+static int exclude_default_prefixes(void) { -+ int r; -+ -+ /* Provide an easy way to exclude virtual/memory file systems from what we do here. Useful in -+ * combination with --root= where we probably don't want to apply stuff to these dirs as they are -+ * likely over-mounted if the root directory is actually used, and it wouldbe less than ideal to have -+ * all kinds of files created/adjusted underneath these mount points. */ -+ -+ r = strv_extend_strv( -+ &arg_exclude_prefixes, -+ STRV_MAKE("/dev", -+ "/proc", -+ "/run", -+ "/sys"), -+ true); -+ if (r < 0) -+ return log_oom(); -+ -+ return 0; -+} -+ - static int help(void) { - _cleanup_free_ char *link = NULL; - int r; -@@ -2904,7 +3000,9 @@ static int help(void) { - " --boot Execute actions only safe at boot\n" - " --prefix=PATH Only apply rules with the specified prefix\n" - " --exclude-prefix=PATH Ignore rules with the specified prefix\n" -+ " -E Ignore rules prefixed with /dev, /proc, /run, /sys\n" - " --root=PATH Operate on an alternate filesystem root\n" -+ " --image=PATH Operate on disk image as filesystem root\n" - " --replace=PATH Treat arguments as replacement for PATH\n" - " --no-pager Do not pipe output into a pager\n" - "\nSee the %s for details.\n" -@@ -2928,6 +3026,7 @@ static int parse_argv(int argc, char *argv[]) { - ARG_PREFIX, - ARG_EXCLUDE_PREFIX, - ARG_ROOT, -+ ARG_IMAGE, - ARG_REPLACE, - ARG_NO_PAGER, - }; -@@ -2944,6 +3043,7 @@ static int parse_argv(int argc, char *argv[]) { - { "prefix", required_argument, NULL, ARG_PREFIX }, - { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX }, - { "root", required_argument, NULL, ARG_ROOT }, -+ { "image", required_argument, NULL, ARG_IMAGE }, - { "replace", required_argument, NULL, ARG_REPLACE }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - {} -@@ -2954,7 +3054,7 @@ static int parse_argv(int argc, char *argv[]) { - assert(argc >= 0); - assert(argv); - -- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) -+ while ((c = getopt_long(argc, argv, "hE", options, NULL)) >= 0) - - switch (c) { - -@@ -3004,6 +3104,21 @@ static int parse_argv(int argc, char *argv[]) { - return r; - break; - -+ case ARG_IMAGE: -+ r = parse_path_argument_and_warn(optarg, /* suppress_root= */ false, &arg_image); -+ if (r < 0) -+ return r; -+ -+ /* Imply -E here since it makes little sense to create files persistently in the /run mointpoint of a disk image */ -+ _fallthrough_; -+ -+ case 'E': -+ r = exclude_default_prefixes(); -+ if (r < 0) -+ return r; -+ -+ break; -+ - case ARG_REPLACE: - if (!path_is_absolute(optarg) || - !endswith(optarg, ".conf")) -@@ -3036,13 +3151,19 @@ static int parse_argv(int argc, char *argv[]) { - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "When --replace= is given, some configuration items must be specified"); - -+ if (arg_root && arg_user) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), -+ "Combination of --user and --root= is not supported."); -+ -+ if (arg_image && arg_root) -+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported."); -+ - return 1; - } - - static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) { - _cleanup_(hashmap_freep) Hashmap *uid_cache = NULL, *gid_cache = NULL; - _cleanup_fclose_ FILE *_f = NULL; -- Iterator iterator; - unsigned v = 0; - FILE *f; - Item *i; -@@ -3098,14 +3219,13 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe - } - - /* we have to determine age parameter for each entry of type X */ -- ORDERED_HASHMAP_FOREACH(i, globs, iterator) { -- Iterator iter; -+ ORDERED_HASHMAP_FOREACH(i, globs) { - Item *j, *candidate_item = NULL; - - if (i->type != IGNORE_DIRECTORY_PATH) - continue; - -- ORDERED_HASHMAP_FOREACH(j, items, iter) { -+ ORDERED_HASHMAP_FOREACH(j, items) { - if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) - continue; - -@@ -3211,9 +3331,11 @@ DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_array_hash_ops, char, string_ - ItemArray, item_array_free); - - static int run(int argc, char *argv[]) { -+ _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; -+ _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL; -+ _cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL; - _cleanup_strv_free_ char **config_dirs = NULL; - bool invalid_config = false; -- Iterator iterator; - ItemArray *a; - enum { - PHASE_REMOVE_AND_CLEAN, -@@ -3243,10 +3365,20 @@ static int run(int argc, char *argv[]) { - - if (DEBUG_LOGGING) { - _cleanup_free_ char *t = NULL; -+ char **i; -+ -+ STRV_FOREACH(i, config_dirs) { -+ _cleanup_free_ char *j = NULL; - -- t = strv_join(config_dirs, "\n\t"); -- if (t) -- log_debug("Looking for configuration files in (higher priority first):\n\t%s", t); -+ j = path_join(arg_root, *i); -+ if (!j) -+ return log_oom(); -+ -+ if (!strextend(&t, "\n\t", j, NULL)) -+ return log_oom(); -+ } -+ -+ log_debug("Looking for configuration files in (higher priority first):%s", t); - } - - if (arg_cat_config) { -@@ -3261,6 +3393,23 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return r; - -+ if (arg_image) { -+ assert(!arg_root); -+ -+ r = mount_image_privately_interactively( -+ arg_image, -+ DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK, -+ &unlink_dir, -+ &loop_device, -+ &decrypted_image); -+ if (r < 0) -+ return r; -+ -+ arg_root = strdup(unlink_dir); -+ if (!arg_root) -+ return log_oom(); -+ } -+ - items = ordered_hashmap_new(&item_array_hash_ops); - globs = ordered_hashmap_new(&item_array_hash_ops); - if (!items || !globs) -@@ -3280,12 +3429,12 @@ static int run(int argc, char *argv[]) { - return r; - - /* Let's now link up all child/parent relationships */ -- ORDERED_HASHMAP_FOREACH(a, items, iterator) { -+ ORDERED_HASHMAP_FOREACH(a, items) { - r = link_parent(a); - if (r < 0) - return r; - } -- ORDERED_HASHMAP_FOREACH(a, globs, iterator) { -+ ORDERED_HASHMAP_FOREACH(a, globs) { - r = link_parent(a); - if (r < 0) - return r; -@@ -3307,21 +3456,21 @@ static int run(int argc, char *argv[]) { - continue; - - /* The non-globbing ones usually create things, hence we apply them first */ -- ORDERED_HASHMAP_FOREACH(a, items, iterator) { -+ ORDERED_HASHMAP_FOREACH(a, items) { - k = process_item_array(a, op); - if (k < 0 && r >= 0) - r = k; - } - - /* The globbing ones usually alter things, hence we apply them second. */ -- ORDERED_HASHMAP_FOREACH(a, globs, iterator) { -+ ORDERED_HASHMAP_FOREACH(a, globs) { - k = process_item_array(a, op); - if (k < 0 && r >= 0) - r = k; - } - } - -- if (ERRNO_IS_RESOURCE(-r)) -+ if (ERRNO_IS_RESOURCE(r)) - return r; - if (invalid_config) - return EX_DATAERR; -diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c -index 4371da4..932f6e1 100644 ---- a/src/tty-ask-password-agent/tty-ask-password-agent.c -+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c -@@ -47,7 +47,7 @@ static enum { - ACTION_LIST, - ACTION_QUERY, - ACTION_WATCH, -- ACTION_WALL -+ ACTION_WALL, - } arg_action = ACTION_QUERY; - - static bool arg_plymouth = false; -@@ -143,8 +143,7 @@ static int agent_ask_password_tty( - const char *flag_file, - char ***ret) { - -- int tty_fd = -1; -- int r; -+ int tty_fd = -1, r; - - if (arg_console) { - const char *con = arg_device ?: "/dev/console"; -@@ -166,7 +165,7 @@ static int agent_ask_password_tty( - release_terminal(); - } - -- return 0; -+ return r; - } - - static int process_one_password_file(const char *filename) { -@@ -210,7 +209,7 @@ static int process_one_password_file(const char *filename) { - - switch (arg_action) { - case ACTION_LIST: -- printf("'%s' (PID %u)\n", message, pid); -+ printf("'%s' (PID %u)\n", strna(message), pid); - return 0; - - case ACTION_WALL: { -@@ -219,7 +218,7 @@ static int process_one_password_file(const char *filename) { - if (asprintf(&wall, - "Password entry required for \'%s\' (PID %u).\r\n" - "Please enter password with the systemd-tty-ask-password-agent tool.", -- message, -+ strna(message), - pid) < 0) - return log_oom(); - -@@ -233,7 +232,7 @@ static int process_one_password_file(const char *filename) { - - if (access(socket_name, W_OK) < 0) { - if (arg_action == ACTION_QUERY) -- log_info("Not querying '%s' (PID %u), lacking privileges.", message, pid); -+ log_info("Not querying '%s' (PID %u), lacking privileges.", strna(message), pid); - - return 0; - } -@@ -246,7 +245,6 @@ static int process_one_password_file(const char *filename) { - r = ask_password_plymouth(message, not_after, flags, filename, &passwords); - else - r = agent_ask_password_tty(message, not_after, flags, filename, &passwords); -- - if (r < 0) { - /* If the query went away, that's OK */ - if (IN_SET(r, -ETIME, -ENOENT)) -@@ -262,8 +260,7 @@ static int process_one_password_file(const char *filename) { - if (r < 0) - return log_error_errno(r, "Failed to send: %m"); - break; -- } -- } -+ }} - - return 0; - } -@@ -586,7 +583,6 @@ static void terminate_agents(Set *pids) { - struct timespec ts; - siginfo_t status = {}; - sigset_t set; -- Iterator i; - void *p; - int r, signum; - -@@ -594,7 +590,7 @@ static void terminate_agents(Set *pids) { - * Request termination of the remaining processes as those - * are not required anymore. - */ -- SET_FOREACH(p, pids, i) -+ SET_FOREACH(p, pids) - (void) kill(PTR_TO_PID(p), SIGTERM); - - /* -@@ -628,7 +624,7 @@ static void terminate_agents(Set *pids) { - /* - * Kill hanging processes. - */ -- SET_FOREACH(p, pids, i) { -+ SET_FOREACH(p, pids) { - log_warning("Failed to terminate child %d, killing it", PTR_TO_PID(p)); - (void) kill(PTR_TO_PID(p), SIGKILL); - } -@@ -713,7 +709,7 @@ static int run(int argc, char *argv[]) { - (void) release_terminal(); - } - -- return process_and_watch_password_files(arg_action != ACTION_QUERY); -+ return process_and_watch_password_files(!IN_SET(arg_action, ACTION_QUERY, ACTION_LIST)); - } - - DEFINE_MAIN_FUNCTION(run); -diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf -index 60a9d21..20f5d7e 100644 ---- a/src/udev/net/link-config-gperf.gperf -+++ b/src/udev/net/link-config-gperf.gperf -@@ -7,6 +7,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") - #include "ethtool-util.h" - #include "link-config.h" - #include "network-internal.h" -+#include "socket-util.h" - %} - struct ConfigPerfItem; - %null_strings -@@ -36,7 +37,7 @@ Link.MACAddressPolicy, config_parse_mac_address_policy, 0, - Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac) - Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy) - Link.Name, config_parse_ifname, 0, offsetof(link_config, name) --Link.AlternativeName, config_parse_ifnames, 1, offsetof(link_config, alternative_names) -+Link.AlternativeName, config_parse_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(link_config, alternative_names) - Link.AlternativeNamesPolicy, config_parse_alternative_names_policy, 0, offsetof(link_config, alternative_names_policy) - Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias) - Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu) -diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c -index 72ef0c5..03fd429 100644 ---- a/src/udev/net/link-config.c -+++ b/src/udev/net/link-config.c -@@ -320,7 +320,8 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr - case NET_ADDR_PERM: - break; - default: -- return log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type); -+ log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type); -+ return 0; - } - - if (want_random == (addr_type == NET_ADDR_RANDOM)) -diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c -index bb82e8a..eb980cb 100644 ---- a/src/udev/udev-builtin-keyboard.c -+++ b/src/udev/udev-builtin-keyboard.c -@@ -87,7 +87,7 @@ static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode - return 0; - } - --static char* parse_token(const char *current, int32_t *val_out) { -+static const char* parse_token(const char *current, int32_t *val_out) { - char *next; - int32_t val; - -@@ -109,7 +109,7 @@ static char* parse_token(const char *current, int32_t *val_out) { - - static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *value) { - struct input_absinfo absinfo; -- char *next; -+ const char *next; - int r; - - r = ioctl(fd, EVIOCGABS(evcode), &absinfo); -@@ -122,7 +122,7 @@ static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *val - next = parse_token(next, &absinfo.fuzz); - next = parse_token(next, &absinfo.flat); - if (!next) -- return log_device_error(dev, "Failed to parse EV_ABS override '%s'", value); -+ return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse EV_ABS override '%s'", value); - - log_device_debug(dev, "keyboard: %x overridden with %"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32, - evcode, absinfo.minimum, absinfo.maximum, absinfo.resolution, absinfo.fuzz, absinfo.flat); -diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c -index b3c0ec8..f070c1d 100644 ---- a/src/udev/udev-builtin-net_id.c -+++ b/src/udev/udev-builtin-net_id.c -@@ -186,7 +186,7 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) { - /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to - * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We - * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network -- * interface a system might have. Ideally the kernel would already filter his crap for us, but it -+ * interface a system might have. Ideally the kernel would already filter this crap for us, but it - * doesn't currently. */ - if (idx > ONBOARD_INDEX_MAX) - return -ENOENT; -diff --git a/src/udev/udev-builtin-uaccess.c b/src/udev/udev-builtin-uaccess.c -index 63401a5..d552316 100644 ---- a/src/udev/udev-builtin-uaccess.c -+++ b/src/udev/udev-builtin-uaccess.c -@@ -50,7 +50,7 @@ static int builtin_uaccess(sd_device *dev, int argc, char *argv[], bool test) { - - r = devnode_acl(path, true, false, 0, true, uid); - if (r < 0) { -- log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m"); -+ log_device_full_errno(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m"); - goto finish; - } - -@@ -64,7 +64,7 @@ finish: - /* Better be safe than sorry and reset ACL */ - k = devnode_acl(path, true, false, 0, false, 0); - if (k < 0) { -- log_device_full(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m"); -+ log_device_full_errno(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m"); - if (r >= 0) - r = k; - } -diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c -index c12af28..758b5ed 100644 ---- a/src/udev/udev-builtin-usb_id.c -+++ b/src/udev/udev-builtin-usb_id.c -@@ -372,7 +372,7 @@ fallback: - if (r < 0) - return log_device_debug_errno(dev_usb, r, "Failed to get idProduct attribute: %m"); - -- /* fallback to USB vendor & device */ -+ /* fall back to USB vendor & device */ - if (vendor_str[0] == '\0') { - const char *usb_vendor; - -diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c -index b41fbfc..b13c1bf 100644 ---- a/src/udev/udev-builtin.c -+++ b/src/udev/udev-builtin.c -@@ -109,6 +109,7 @@ UdevBuiltinCommand udev_builtin_lookup(const char *command) { - - int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command, bool test) { - _cleanup_strv_free_ char **argv = NULL; -+ int r; - - assert(dev); - assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX); -@@ -117,9 +118,9 @@ int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command - if (!builtins[cmd]) - return -EOPNOTSUPP; - -- argv = strv_split_full(command, NULL, SPLIT_QUOTES | SPLIT_RELAX); -- if (!argv) -- return -ENOMEM; -+ r = strv_split_full(&argv, command, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_RETAIN_ESCAPE); -+ if (r < 0) -+ return r; - - /* we need '0' here to reset the internal state */ - optind = 0; -diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c -index 1e51f22..dafe3da 100644 ---- a/src/udev/udev-ctrl.c -+++ b/src/udev/udev-ctrl.c -@@ -392,9 +392,10 @@ int udev_ctrl_wait(struct udev_ctrl *uctrl, usec_t timeout) { - (void) sd_event_source_set_description(source_io, "udev-ctrl-wait-io"); - - if (timeout != USEC_INFINITY) { -- r = sd_event_add_time(uctrl->event, &source_timeout, clock_boottime_or_monotonic(), -- usec_add(now(clock_boottime_or_monotonic()), timeout), -- 0, NULL, INT_TO_PTR(-ETIMEDOUT)); -+ r = sd_event_add_time_relative( -+ uctrl->event, &source_timeout, clock_boottime_or_monotonic(), -+ timeout, -+ 0, NULL, INT_TO_PTR(-ETIMEDOUT)); - if (r < 0) - return r; - -diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c -index e1c2baf..7c78b4c 100644 ---- a/src/udev/udev-event.c -+++ b/src/udev/udev-event.c -@@ -633,7 +633,7 @@ static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userd - if (si->si_status == 0) - log_device_debug(spawn->device, "Process '%s' succeeded.", spawn->cmd); - else -- log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, 0, -+ log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, - "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status); - ret = si->si_status; - break; -@@ -747,9 +747,9 @@ int udev_event_spawn(UdevEvent *event, - return log_device_error_errno(event->dev, errno, - "Failed to create pipe for command '%s': %m", cmd); - -- argv = strv_split_full(cmd, NULL, SPLIT_QUOTES|SPLIT_RELAX); -- if (!argv) -- return log_oom(); -+ r = strv_split_full(&argv, cmd, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX | EXTRACT_RETAIN_ESCAPE); -+ if (r < 0) -+ return log_device_error_errno(event->dev, r, "Failed to split command: %m"); - - if (isempty(argv[0])) - return log_device_error_errno(event->dev, SYNTHETIC_ERRNO(EINVAL), -@@ -958,6 +958,24 @@ static int udev_event_on_move(UdevEvent *event) { - return 0; - } - -+static int copy_all_tags(sd_device *d, sd_device *s) { -+ const char *tag; -+ int r; -+ -+ assert(d); -+ -+ if (!s) -+ return 0; -+ -+ for (tag = sd_device_get_tag_first(s); tag; tag = sd_device_get_tag_next(s)) { -+ r = device_add_tag(d, tag, false); -+ if (r < 0) -+ return r; -+ } -+ -+ return 0; -+} -+ - int udev_event_execute_rules(UdevEvent *event, - usec_t timeout_usec, - int timeout_signal, -@@ -990,6 +1008,10 @@ int udev_event_execute_rules(UdevEvent *event, - if (r < 0) - return log_device_debug_errno(dev, r, "Failed to clone sd_device object: %m"); - -+ r = copy_all_tags(dev, event->dev_db_clone); -+ if (r < 0) -+ log_device_warning_errno(dev, r, "Failed to copy all tags from old database entry, ignoring: %m"); -+ - if (sd_device_get_devnum(dev, NULL) >= 0) - /* Disable watch during event processing. */ - (void) udev_watch_end(event->dev_db_clone); -@@ -1034,10 +1056,9 @@ int udev_event_execute_rules(UdevEvent *event, - void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec, int timeout_signal) { - const char *command; - void *val; -- Iterator i; - int r; - -- ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list, i) { -+ ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list) { - UdevBuiltinCommand builtin_cmd = PTR_TO_UDEV_BUILTIN_CMD(val); - - if (builtin_cmd != _UDEV_BUILTIN_INVALID) { -diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c -index 31a3403..bc259dd 100644 ---- a/src/udev/udev-node.c -+++ b/src/udev/udev-node.c -@@ -314,7 +314,6 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, - if (apply_mode || apply_uid || apply_gid || apply_mac) { - bool selinux = false, smack = false; - const char *name, *label; -- Iterator i; - - if (apply_mode || apply_uid || apply_gid) { - log_device_debug(dev, "Setting permissions %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o", -@@ -325,13 +324,13 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, - - r = chmod_and_chown(devnode, mode, uid, gid); - if (r < 0) -- log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, -- "Failed to set owner/mode of %s to uid=" UID_FMT -- ", gid=" GID_FMT ", mode=%#o: %m", -- devnode, -- uid_is_valid(uid) ? uid : stats.st_uid, -- gid_is_valid(gid) ? gid : stats.st_gid, -- mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); -+ log_device_full_errno(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, -+ "Failed to set owner/mode of %s to uid=" UID_FMT -+ ", gid=" GID_FMT ", mode=%#o: %m", -+ devnode, -+ uid_is_valid(uid) ? uid : stats.st_uid, -+ gid_is_valid(gid) ? gid : stats.st_gid, -+ mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); - } else - log_device_debug(dev, "Preserve permissions of %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o", - devnode, -@@ -340,7 +339,7 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, - mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); - - /* apply SECLABEL{$module}=$label */ -- ORDERED_HASHMAP_FOREACH_KEY(label, name, seclabel_list, i) { -+ ORDERED_HASHMAP_FOREACH_KEY(label, name, seclabel_list) { - int q; - - if (streq(name, "selinux")) { -@@ -348,8 +347,8 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, - - q = mac_selinux_apply(devnode, label); - if (q < 0) -- log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, -- "SECLABEL: failed to set SELinux label '%s': %m", label); -+ log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, -+ "SECLABEL: failed to set SELinux label '%s': %m", label); - else - log_device_debug(dev, "SECLABEL: set SELinux label '%s'", label); - -@@ -358,8 +357,8 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, - - q = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label); - if (q < 0) -- log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, -- "SECLABEL: failed to set SMACK label '%s': %m", label); -+ log_device_full_errno(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, -+ "SECLABEL: failed to set SMACK label '%s': %m", label); - else - log_device_debug(dev, "SECLABEL: set SMACK label '%s'", label); - -diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c -index c36f032..437429a 100644 ---- a/src/udev/udev-rules.c -+++ b/src/udev/udev-rules.c -@@ -182,43 +182,46 @@ struct UdevRules { - - /*** Logging helpers ***/ - --#define log_rule_full(device, rules, level, error, fmt, ...) \ -+#define log_rule_full_errno(device, rules, level, error, fmt, ...) \ - ({ \ - UdevRules *_r = (rules); \ - UdevRuleFile *_f = _r ? _r->current_file : NULL; \ - UdevRuleLine *_l = _f ? _f->current_line : NULL; \ - const char *_n = _f ? _f->filename : NULL; \ - \ -- log_device_full(device, level, error, "%s:%u " fmt, \ -- strna(_n), _l ? _l->line_number : 0, \ -- ##__VA_ARGS__); \ -+ log_device_full_errno(device, level, error, "%s:%u " fmt, \ -+ strna(_n), _l ? _l->line_number : 0, \ -+ ##__VA_ARGS__); \ - }) - --#define log_rule_debug(device, rules, ...) log_rule_full(device, rules, LOG_DEBUG, 0, ##__VA_ARGS__) --#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, 0, ##__VA_ARGS__) --#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, 0, ##__VA_ARGS__) --#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, 0, ##__VA_ARGS__) --#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, 0, ##__VA_ARGS__) -+#define log_rule_full(device, rules, level, ...) (void) log_rule_full_errno(device, rules, level, 0, __VA_ARGS__) - --#define log_rule_debug_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_DEBUG, error, ##__VA_ARGS__) --#define log_rule_info_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_INFO, error, ##__VA_ARGS__) --#define log_rule_notice_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_NOTICE, error, ##__VA_ARGS__) --#define log_rule_warning_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_WARNING, error, ##__VA_ARGS__) --#define log_rule_error_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_ERR, error, ##__VA_ARGS__) -+#define log_rule_debug(device, rules, ...) log_rule_full_errno(device, rules, LOG_DEBUG, 0, __VA_ARGS__) -+#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, __VA_ARGS__) -+#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, __VA_ARGS__) -+#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, __VA_ARGS__) -+#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, __VA_ARGS__) - --#define log_token_full(rules, ...) log_rule_full(NULL, rules, ##__VA_ARGS__) -+#define log_rule_debug_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_DEBUG, error, __VA_ARGS__) -+#define log_rule_info_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_INFO, error, __VA_ARGS__) -+#define log_rule_notice_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_NOTICE, error, __VA_ARGS__) -+#define log_rule_warning_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_WARNING, error, __VA_ARGS__) -+#define log_rule_error_errno(device, rules, error, ...) log_rule_full_errno(device, rules, LOG_ERR, error, __VA_ARGS__) - --#define log_token_debug(rules, ...) log_token_full(rules, LOG_DEBUG, 0, ##__VA_ARGS__) --#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, 0, ##__VA_ARGS__) --#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, 0, ##__VA_ARGS__) --#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, 0, ##__VA_ARGS__) --#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, 0, ##__VA_ARGS__) -+#define log_token_full_errno(rules, level, error, ...) log_rule_full_errno(NULL, rules, level, error, __VA_ARGS__) -+#define log_token_full(rules, level, ...) (void) log_token_full_errno(rules, level, 0, __VA_ARGS__) - --#define log_token_debug_errno(rules, error, ...) log_token_full(rules, LOG_DEBUG, error, ##__VA_ARGS__) --#define log_token_info_errno(rules, error, ...) log_token_full(rules, LOG_INFO, error, ##__VA_ARGS__) --#define log_token_notice_errno(rules, error, ...) log_token_full(rules, LOG_NOTICE, error, ##__VA_ARGS__) --#define log_token_warning_errno(rules, error, ...) log_token_full(rules, LOG_WARNING, error, ##__VA_ARGS__) --#define log_token_error_errno(rules, error, ...) log_token_full(rules, LOG_ERR, error, ##__VA_ARGS__) -+#define log_token_debug(rules, ...) log_token_full_errno(rules, LOG_DEBUG, 0, __VA_ARGS__) -+#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, __VA_ARGS__) -+#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, __VA_ARGS__) -+#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, __VA_ARGS__) -+#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, __VA_ARGS__) -+ -+#define log_token_debug_errno(rules, error, ...) log_token_full_errno(rules, LOG_DEBUG, error, __VA_ARGS__) -+#define log_token_info_errno(rules, error, ...) log_token_full_errno(rules, LOG_INFO, error, __VA_ARGS__) -+#define log_token_notice_errno(rules, error, ...) log_token_full_errno(rules, LOG_NOTICE, error, __VA_ARGS__) -+#define log_token_warning_errno(rules, error, ...) log_token_full_errno(rules, LOG_WARNING, error, __VA_ARGS__) -+#define log_token_error_errno(rules, error, ...) log_token_full_errno(rules, LOG_ERR, error, __VA_ARGS__) - - #define _log_token_invalid(rules, key, type) \ - log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), \ -@@ -2017,7 +2020,7 @@ static int udev_rule_apply_token_to_event( - if (token->op == OP_REMOVE) - device_remove_tag(dev, buf); - else { -- r = device_add_tag(dev, buf); -+ r = device_add_tag(dev, buf, true); - if (r < 0) - return log_rule_error_errno(dev, rules, r, "Failed to add tag '%s': %m", buf); - } -@@ -2038,7 +2041,7 @@ static int udev_rule_apply_token_to_event( - } - if (sd_device_get_devnum(dev, NULL) >= 0 && - (sd_device_get_devname(dev, &val) < 0 || -- !streq_ptr(buf, startswith(val, "/dev/")))) { -+ !streq_ptr(buf, path_startswith(val, "/dev/")))) { - log_rule_error(dev, rules, - "Kernel device nodes cannot be renamed, ignoring NAME=\"%s\"; please fix it.", - token->value); -diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c -index 96a25dd..d87a435 100644 ---- a/src/udev/udev-watch.c -+++ b/src/udev/udev-watch.c -@@ -97,10 +97,8 @@ int udev_watch_begin(sd_device *dev) { - log_device_debug(dev, "Adding watch on '%s'", devnode); - wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE); - if (wd < 0) -- return log_device_full(dev, -- errno == ENOENT ? LOG_DEBUG : LOG_ERR, -- errno, -- "Failed to add device '%s' to watch: %m", devnode); -+ return log_device_full_errno(dev, errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, -+ "Failed to add device '%s' to watch: %m", devnode); - - device_set_watch_handle(dev, wd); - -diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c -index 8cd8ed1..52f27ed 100644 ---- a/src/udev/udevadm-monitor.c -+++ b/src/udev/udevadm-monitor.c -@@ -62,7 +62,6 @@ static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, - static int setup_monitor(MonitorNetlinkGroup sender, sd_event *event, sd_device_monitor **ret) { - _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; - const char *subsystem, *devtype, *tag; -- Iterator i; - int r; - - r = device_monitor_new_full(&monitor, sender, -1); -@@ -75,14 +74,14 @@ static int setup_monitor(MonitorNetlinkGroup sender, sd_event *event, sd_device_ - if (r < 0) - return log_error_errno(r, "Failed to attach event: %m"); - -- HASHMAP_FOREACH_KEY(devtype, subsystem, arg_subsystem_filter, i) { -+ HASHMAP_FOREACH_KEY(devtype, subsystem, arg_subsystem_filter) { - r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, subsystem, devtype); - if (r < 0) - return log_error_errno(r, "Failed to apply subsystem filter '%s%s%s': %m", - subsystem, devtype ? "/" : "", strempty(devtype)); - } - -- SET_FOREACH(tag, arg_tag_filter, i) { -+ SET_FOREACH(tag, arg_tag_filter) { - r = sd_device_monitor_filter_add_match_tag(monitor, tag); - if (r < 0) - return log_error_errno(r, "Failed to apply tag filter '%s': %m", tag); -diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c -index 5b9b654..0d84b31 100644 ---- a/src/udev/udevadm-test.c -+++ b/src/udev/udevadm-test.c -@@ -17,6 +17,7 @@ - #include "device-private.h" - #include "device-util.h" - #include "libudev-util.h" -+#include "path-util.h" - #include "string-util.h" - #include "strxcpyx.h" - #include "udev-builtin.h" -@@ -90,7 +91,7 @@ static int parse_argv(int argc, char *argv[]) { - "syspath parameter missing."); - - /* add /sys if needed */ -- if (!startswith(argv[optind], "/sys")) -+ if (!path_startswith(argv[optind], "/sys")) - strscpyl(arg_syspath, sizeof(arg_syspath), "/sys", argv[optind], NULL); - else - strscpy(arg_syspath, sizeof(arg_syspath), argv[optind]); -@@ -104,7 +105,6 @@ int test_main(int argc, char *argv[], void *userdata) { - _cleanup_(sd_device_unrefp) sd_device *dev = NULL; - const char *cmd, *key, *value; - sigset_t mask, sigmask_orig; -- Iterator i; - void *val; - int r; - -@@ -148,7 +148,7 @@ int test_main(int argc, char *argv[], void *userdata) { - FOREACH_DEVICE_PROPERTY(dev, key, value) - printf("%s=%s\n", key, value); - -- ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) { -+ ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list) { - char program[UTIL_PATH_SIZE]; - - (void) udev_event_apply_format(event, cmd, program, sizeof(program), false); -diff --git a/src/udev/udevd.c b/src/udev/udevd.c -index f3236de..22dad2a 100644 ---- a/src/udev/udevd.c -+++ b/src/udev/udevd.c -@@ -251,7 +251,6 @@ static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *use - - static void worker_attach_event(struct worker *worker, struct event *event) { - sd_event *e; -- uint64_t usec; - - assert(worker); - assert(worker->manager); -@@ -266,13 +265,13 @@ static void worker_attach_event(struct worker *worker, struct event *event) { - - e = worker->manager->event; - -- assert_se(sd_event_now(e, CLOCK_MONOTONIC, &usec) >= 0); -+ (void) sd_event_add_time_relative(e, &event->timeout_warning_event, CLOCK_MONOTONIC, -+ udev_warn_timeout(arg_event_timeout_usec), USEC_PER_SEC, -+ on_event_timeout_warning, event); - -- (void) sd_event_add_time(e, &event->timeout_warning_event, CLOCK_MONOTONIC, -- usec + udev_warn_timeout(arg_event_timeout_usec), USEC_PER_SEC, on_event_timeout_warning, event); -- -- (void) sd_event_add_time(e, &event->timeout_event, CLOCK_MONOTONIC, -- usec + arg_event_timeout_usec, USEC_PER_SEC, on_event_timeout, event); -+ (void) sd_event_add_time_relative(e, &event->timeout_event, CLOCK_MONOTONIC, -+ arg_event_timeout_usec, USEC_PER_SEC, -+ on_event_timeout, event); - } - - static void manager_clear_for_worker(Manager *manager) { -@@ -613,7 +612,6 @@ static int worker_spawn(Manager *manager, struct event *event) { - static void event_run(Manager *manager, struct event *event) { - static bool log_children_max_reached = true; - struct worker *worker; -- Iterator i; - int r; - - assert(manager); -@@ -627,7 +625,7 @@ static void event_run(Manager *manager, struct event *event) { - event->seqnum, r >= 0 ? device_action_to_string(action) : ""); - } - -- HASHMAP_FOREACH(worker, manager->workers, i) { -+ HASHMAP_FOREACH(worker, manager->workers) { - if (worker->state != WORKER_IDLE) - continue; - -@@ -657,6 +655,10 @@ static void event_run(Manager *manager, struct event *event) { - /* Re-enable the debug message for the next batch of events */ - log_children_max_reached = true; - -+ /* fork with up-to-date SELinux label database, so the child inherits the up-to-date db -+ and, until the next SELinux policy changes, we safe further reloads in future children */ -+ mac_selinux_maybe_reload(); -+ - /* start new worker and pass initial device */ - worker_spawn(manager, event); - } -@@ -721,11 +723,10 @@ static int event_queue_insert(Manager *manager, sd_device *dev) { - - static void manager_kill_workers(Manager *manager) { - struct worker *worker; -- Iterator i; - - assert(manager); - -- HASHMAP_FOREACH(worker, manager->workers, i) { -+ HASHMAP_FOREACH(worker, manager->workers) { - if (worker->state == WORKER_KILLED) - continue; - -@@ -1685,8 +1686,11 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg - /* Bump receiver buffer, but only if we are not called via socket activation, as in that - * case systemd sets the receive buffer size for us, and the value in the .socket unit - * should take full effect. */ -- if (fd_uevent < 0) -- (void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024); -+ if (fd_uevent < 0) { -+ r = sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024); -+ if (r < 0) -+ log_warning_errno(r, "Failed to set receive buffer size for device monitor, ignoring: %m"); -+ } - - r = device_monitor_enable_receiving(manager->monitor); - if (r < 0) -diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c -index c001802..e9d589e 100644 ---- a/src/update-done/update-done.c -+++ b/src/update-done/update-done.c -@@ -31,7 +31,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) { - - r = write_string_file_atomic_label_ts(path, message, ts); - if (r == -EROFS) -- return log_debug("Cannot create \"%s\", file system is read-only.", path); -+ return log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path); - if (r < 0) - return log_error_errno(r, "Failed to write \"%s\": %m", path); - return 0; -diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c -index 47354d5..4ab90a6 100644 ---- a/src/update-utmp/update-utmp.c -+++ b/src/update-utmp/update-utmp.c -@@ -187,8 +187,10 @@ static int on_runlevel(Context *c) { - runlevel = get_current_runlevel(c); - if (runlevel < 0) - return runlevel; -- if (runlevel == 0) -- return log_warning("Failed to get new runlevel, utmp update skipped."); -+ if (runlevel == 0) { -+ log_warning("Failed to get new runlevel, utmp update skipped."); -+ return 0; -+ } - - if (previous == runlevel) - return 0; -diff --git a/src/userdb/userdbctl.c b/src/userdb/userdbctl.c -index c973ee9..0c135fa 100644 ---- a/src/userdb/userdbctl.c -+++ b/src/userdb/userdbctl.c -@@ -8,7 +8,6 @@ - #include "fd-util.h" - #include "format-table.h" - #include "format-util.h" --#include "group-record-show.h" - #include "main-func.h" - #include "pager.h" - #include "parse-util.h" -@@ -232,6 +231,7 @@ static int show_group(GroupRecord *gr, Table *table) { - TABLE_STRING, gr->group_name, - TABLE_STRING, user_disposition_to_string(group_record_disposition(gr)), - TABLE_GID, gr->gid, -+ TABLE_STRING, gr->description, - TABLE_INT, (int) group_record_disposition(gr)); - if (r < 0) - return table_log_add_error(r); -@@ -255,13 +255,14 @@ static int display_group(int argc, char *argv[], void *userdata) { - arg_output = argc > 1 ? OUTPUT_FRIENDLY : OUTPUT_TABLE; - - if (arg_output == OUTPUT_TABLE) { -- table = table_new("name", "disposition", "gid", "disposition-numeric"); -+ table = table_new("name", "disposition", "gid", "description", "disposition-numeric"); - if (!table) - return log_oom(); - - (void) table_set_align_percent(table, table_get_cell(table, 0, 2), 100); -+ (void) table_set_empty_string(table, "-"); - (void) table_set_sort(table, (size_t) 3, (size_t) 2, (size_t) -1); -- (void) table_set_display(table, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) -1); -+ (void) table_set_display(table, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) -1); - } - - if (argc > 1) { -@@ -685,7 +686,8 @@ static int parse_argv(int argc, char *argv[]) { - else if (streq(optarg, "help")) { - puts("classic\n" - "friendly\n" -- "json"); -+ "json\n" -+ "table"); - return 0; - } else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid --output= mode: %s", optarg); -diff --git a/src/userdb/userdbd.c b/src/userdb/userdbd.c -index dbc285e..e456104 100644 ---- a/src/userdb/userdbd.c -+++ b/src/userdb/userdbd.c -@@ -11,7 +11,7 @@ - - /* This service offers two Varlink services, both implementing io.systemd.UserDatabase: - * -- * → io.systemd.NameServiceSwitch: this is a compatibility interface for glibc NSS: it response to -+ * → io.systemd.NameServiceSwitch: this is a compatibility interface for glibc NSS: it responds to - * name lookups by checking the classic NSS interfaces and responding that. - * - * → io.systemd.Multiplexer: this multiplexes lookup requests to all Varlink services that have a -diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c -index d720209..a68011b 100644 ---- a/src/userdb/userwork.c -+++ b/src/userdb/userwork.c -@@ -7,7 +7,6 @@ - - #include "env-util.h" - #include "fd-util.h" --#include "group-record-nss.h" - #include "group-record.h" - #include "io-util.h" - #include "main-func.h" -diff --git a/src/veritysetup/veritysetup.c b/src/veritysetup/veritysetup.c -index e475402..8294951 100644 ---- a/src/veritysetup/veritysetup.c -+++ b/src/veritysetup/veritysetup.c -@@ -5,7 +5,7 @@ - #include - - #include "alloc-util.h" --#include "crypt-util.h" -+#include "cryptsetup-util.h" - #include "fileio.h" - #include "hexdecoct.h" - #include "log.h" -@@ -73,7 +73,7 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return log_error_errno(r, "Failed to open verity device %s: %m", argv[4]); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - status = crypt_status(cd, argv[2]); - if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) { -@@ -124,7 +124,7 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return log_error_errno(r, "crypt_init_by_name() failed: %m"); - -- crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); -+ cryptsetup_enable_logging(cd); - - r = crypt_deactivate(cd, argv[2]); - if (r < 0) -diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c -index e55864d..6a08464 100644 ---- a/src/volatile-root/volatile-root.c -+++ b/src/volatile-root/volatile-root.c -@@ -175,7 +175,7 @@ static int run(int argc, char *argv[]) { - r = get_block_device_harder(path, &devt); - if (r < 0) - return log_error_errno(r, "Failed to determine device major/minor of %s: %m", path); -- else if (r > 0) { -+ else if (r > 0) { /* backed by block device */ - _cleanup_free_ char *dn = NULL; - - r = device_path_make_major_minor(S_IFBLK, devt, &dn); -diff --git a/src/xdg-autostart-generator/xdg-autostart-generator.c b/src/xdg-autostart-generator/xdg-autostart-generator.c -index 53366a3..6cec28e 100644 ---- a/src/xdg-autostart-generator/xdg-autostart-generator.c -+++ b/src/xdg-autostart-generator/xdg-autostart-generator.c -@@ -94,7 +94,6 @@ static int enumerate_xdg_autostart(Hashmap *all_services) { - static int run(const char *dest, const char *dest_early, const char *dest_late) { - _cleanup_(hashmap_freep) Hashmap *all_services = NULL; - XdgAutostartService *service; -- Iterator j; - int r; - - assert_se(dest_late); -@@ -107,7 +106,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) - if (r < 0) - return r; - -- HASHMAP_FOREACH(service, all_services, j) -+ HASHMAP_FOREACH(service, all_services) - (void) xdg_autostart_service_generate_unit(service, dest_late); - - return 0; -diff --git a/src/xdg-autostart-generator/xdg-autostart-service.c b/src/xdg-autostart-generator/xdg-autostart-service.c -index 4a30f9e..c6f39f2 100644 ---- a/src/xdg-autostart-generator/xdg-autostart-service.c -+++ b/src/xdg-autostart-generator/xdg-autostart-service.c -@@ -166,7 +166,7 @@ static int xdg_config_parse_string( - - /* XDG does not allow duplicate definitions. */ - if (*out) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Key %s was defined multiple times, ignoring.", lvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Key %s was defined multiple times, ignoring.", lvalue); - return 0; - } - -@@ -238,7 +238,7 @@ static int xdg_config_parse_strv( - - /* XDG does not allow duplicate definitions. */ - if (*ret_sv) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Key %s was already defined, ignoring.", lvalue); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Key %s was already defined, ignoring.", lvalue); - return 0; - } - -@@ -256,7 +256,7 @@ static int xdg_config_parse_strv( - /* Move forward, and ensure it is a valid escape. */ - end++; - if (!strchr("sntr\\;", *end)) { -- log_syntax(unit, LOG_ERR, filename, line, 0, "Undefined escape sequence \\%c.", *end); -+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Undefined escape sequence \\%c.", *end); - return 0; - } - continue; -@@ -385,9 +385,9 @@ int xdg_autostart_format_exec_start( - * NOTE: Technically, XDG only specifies " as quotes, while this also - * accepts '. - */ -- exec_split = strv_split_full(exec, WHITESPACE, SPLIT_QUOTES | SPLIT_RELAX); -- if (!exec_split) -- return -ENOMEM; -+ r = strv_split_full(&exec_split, exec, NULL, EXTRACT_UNQUOTE | EXTRACT_RELAX); -+ if (r < 0) -+ return r; - - if (strv_isempty(exec_split)) - return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Exec line is empty"); -diff --git a/test/README.testsuite b/test/README.testsuite -index 7204fdb..34c7ab3 100644 ---- a/test/README.testsuite -+++ b/test/README.testsuite -@@ -104,19 +104,19 @@ Ubuntu CI - New PR submitted to the project are run through regression tests, and one set - of those is the 'autopkgtest' runs for several different architectures, called - 'Ubuntu CI'. Part of that testing is to run all these tests. Sometimes these --tests are temporarily blacklisted from running in the 'autopkgtest' tests while -+tests are temporarily deny-listed from running in the 'autopkgtest' tests while - debugging a flaky test; that is done by creating a file in the test directory --named 'blacklist-ubuntu-ci', for example to prevent the TEST-01-BASIC test from -+named 'deny-list-ubuntu-ci', for example to prevent the TEST-01-BASIC test from - running in the 'autopkgtest' runs, create the file --'TEST-01-BASIC/blacklist-ubuntu-ci'. -+'TEST-01-BASIC/deny-list-ubuntu-ci'. - --The tests may be disabled only for specific archs, by creating a blacklist file -+The tests may be disabled only for specific archs, by creating a deny-list file - with the arch name at the end, e.g. --'TEST-01-BASIC/blacklist-ubuntu-ci-arm64' to disable the TEST-01-BASIC test -+'TEST-01-BASIC/deny-list-ubuntu-ci-arm64' to disable the TEST-01-BASIC test - only on test runs for the 'arm64' architecture. - - Note the arch naming is not from 'uname -m', it is Debian arch names: - https://wiki.debian.org/ArchitectureSpecificsMemo - --For PRs that fix a currently blacklisted test, the PR should include removal --of the blacklist file. -+For PRs that fix a currently deny-listed test, the PR should include removal -+of the deny-list file. -diff --git a/test/TEST-21-SYSUSERS/test.sh b/test/TEST-21-SYSUSERS/test.sh -index 2992bea..3b37f7e 100755 ---- a/test/TEST-21-SYSUSERS/test.sh -+++ b/test/TEST-21-SYSUSERS/test.sh -@@ -22,8 +22,9 @@ preprocess() { - # see meson.build how to extract this. gcc -E was used before to - # get this value from config.h, however the autopkgtest fails with - # it -- SYSTEM_UID_MAX=$(awk 'BEGIN { uid=999 } /^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }' /etc/login.defs) -- SYSTEM_GID_MAX=$(awk 'BEGIN { gid=999 } /^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }' /etc/login.defs) -+ [[ -e /etc/login.defs ]] && login_defs_file="/etc/login.defs" || login_defs_file="/usr/etc/login.defs" -+ SYSTEM_UID_MAX=$(awk 'BEGIN { uid=999 } /^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }' $login_defs_file) -+ SYSTEM_GID_MAX=$(awk 'BEGIN { gid=999 } /^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }' $login_defs_file) - - # we can't rely on config.h to get the nologin path, as autopkgtest - # uses pre-compiled binaries, so extract it from the systemd-sysusers -diff --git a/test/TEST-24-UNIT-TESTS/blacklist-ubuntu-ci-ppc64el b/test/TEST-24-UNIT-TESTS/deny-list-ubuntu-ci-ppc64el -similarity index 100% -rename from test/TEST-24-UNIT-TESTS/blacklist-ubuntu-ci-ppc64el -rename to test/TEST-24-UNIT-TESTS/deny-list-ubuntu-ci-ppc64el -diff --git a/test/TEST-25-IMPORT/blacklist-ubuntu-ci b/test/TEST-25-IMPORT/deny-list-ubuntu-ci -similarity index 100% -rename from test/TEST-25-IMPORT/blacklist-ubuntu-ci -rename to test/TEST-25-IMPORT/deny-list-ubuntu-ci -diff --git a/test/TEST-30-ONCLOCKCHANGE/blacklist-ubuntu-ci-i386 b/test/TEST-30-ONCLOCKCHANGE/deny-list-ubuntu-ci-i386 -similarity index 100% -rename from test/TEST-30-ONCLOCKCHANGE/blacklist-ubuntu-ci-i386 -rename to test/TEST-30-ONCLOCKCHANGE/deny-list-ubuntu-ci-i386 -diff --git a/test/TEST-36-NUMAPOLICY/blacklist-ubuntu-ci-s390x b/test/TEST-36-NUMAPOLICY/deny-list-ubuntu-ci-s390x -similarity index 100% -rename from test/TEST-36-NUMAPOLICY/blacklist-ubuntu-ci-s390x -rename to test/TEST-36-NUMAPOLICY/deny-list-ubuntu-ci-s390x -diff --git a/test/TEST-40-EXEC-COMMAND-EX/blacklist-ubuntu-ci-arm64 b/test/TEST-40-EXEC-COMMAND-EX/deny-list-ubuntu-ci-arm64 -similarity index 100% -rename from test/TEST-40-EXEC-COMMAND-EX/blacklist-ubuntu-ci-arm64 -rename to test/TEST-40-EXEC-COMMAND-EX/deny-list-ubuntu-ci-arm64 -diff --git a/test/TEST-50-DISSECT/test.sh b/test/TEST-50-DISSECT/test.sh -index 3882658..f274b73 100755 ---- a/test/TEST-50-DISSECT/test.sh -+++ b/test/TEST-50-DISSECT/test.sh -@@ -28,19 +28,19 @@ test_create_image() { - instmods dm_verity =md - install_dmevent - generate_module_dependencies -- inst_binary sfdisk - inst_binary losetup - - BASICTOOLS=( - bash - cat -+ mount - ) - oldinitdir=$initdir - export initdir=$TESTDIR/minimal - mkdir -p $initdir - setup_basic_dirs - install_basic_tools -- inst /usr/lib/os-release -+ cp $os_release $initdir/usr/lib/os-release - ln -s ../usr/lib/os-release $initdir/etc/os-release - echo MARKER=1 >> $initdir/usr/lib/os-release - mksquashfs $initdir $oldinitdir/usr/share/minimal.raw -diff --git a/test/TEST-54-CREDS/Makefile b/test/TEST-54-CREDS/Makefile -new file mode 120000 -index 0000000..e9f93b1 ---- /dev/null -+++ b/test/TEST-54-CREDS/Makefile -@@ -0,0 +1 @@ -+../TEST-01-BASIC/Makefile -\ No newline at end of file -diff --git a/test/TEST-54-CREDS/test.sh b/test/TEST-54-CREDS/test.sh -new file mode 100755 -index 0000000..5feb15e ---- /dev/null -+++ b/test/TEST-54-CREDS/test.sh -@@ -0,0 +1,7 @@ -+#!/usr/bin/env bash -+set -e -+TEST_DESCRIPTION="test credentials" -+ -+. $TEST_BASE_DIR/test-functions -+ -+do_test "$@" 54 -diff --git a/test/TEST-55-UDEV-TAGS/Makefile b/test/TEST-55-UDEV-TAGS/Makefile -new file mode 120000 -index 0000000..e9f93b1 ---- /dev/null -+++ b/test/TEST-55-UDEV-TAGS/Makefile -@@ -0,0 +1 @@ -+../TEST-01-BASIC/Makefile -\ No newline at end of file -diff --git a/test/TEST-55-UDEV-TAGS/test.sh b/test/TEST-55-UDEV-TAGS/test.sh -new file mode 100755 -index 0000000..325d70f ---- /dev/null -+++ b/test/TEST-55-UDEV-TAGS/test.sh -@@ -0,0 +1,8 @@ -+#!/usr/bin/env bash -+set -e -+TEST_DESCRIPTION="UDEV tags management" -+TEST_NO_NSPAWN=1 -+ -+. $TEST_BASE_DIR/test-functions -+ -+do_test "$@" 55 -diff --git a/test/create-busybox-container b/test/create-busybox-container -index 08fb5d4..5ded429 100755 ---- a/test/create-busybox-container -+++ b/test/create-busybox-container -@@ -9,6 +9,17 @@ mkdir -p "$root" - mkdir "$root/bin" - cp $(type -P busybox) "$root/bin" - -+os_release=$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release) -+ID_LIKE=$(awk -F= '$1=="ID_LIKE" { print $2 ;}' $os_release) -+if [[ "$ID_LIKE" = *"suse"* ]]; then -+ mkdir -p "$root/lib" -+ mkdir -p "$root/lib64" -+ for lib in $(find /lib*/ld*); do -+ [[ -d $root/$(dirname $lib) ]] || mkdir -p $root/$(dirname $lib) -+ cp $lib $root/$lib -+ done -+fi -+ - mkdir -p "$root/usr/lib" - touch "$root/usr/lib/os-release" - -diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network -index 5d80470..054b630 100644 ---- a/test/fuzz/fuzz-network-parser/directives.network -+++ b/test/fuzz/fuzz-network-parser/directives.network -@@ -54,6 +54,9 @@ MACAddress= - Destination= - VNI= - AssociatedWith= -+[BridgeMDB] -+MulticastGroupAddress= -+VLANId= - [DHCP] - UseDomains= - UseRoutes= -diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service -index dbff9ab..21a04cf 100644 ---- a/test/fuzz/fuzz-unit-file/directives.service -+++ b/test/fuzz/fuzz-unit-file/directives.service -@@ -385,6 +385,7 @@ DNSLifetimeSec= - DNSSEC= - DNSSECNegativeTrustAnchors= - DNSStubListener= -+DNSStubListenerExtra= - DUIDRawData= - DUIDType= - DefaultLeaseTimeSec= -@@ -782,6 +783,8 @@ KEYMAP= - KEYMAP_TOGGLE= - KeepFree= - KeyringMode= -+ProtectProc= -+ProcSubset= - KillExcludeUsers= - KillOnlyUsers= - KillSignal= -diff --git a/test/fuzz/fuzz-unit-file/systemd-machined.service b/test/fuzz/fuzz-unit-file/systemd-machined.service -index 70b627c..79ee986 100644 ---- a/test/fuzz/fuzz-unit-file/systemd-machined.service -+++ b/test/fuzz/fuzz-unit-file/systemd-machined.service -@@ -15,9 +15,6 @@ Documentation=https://www.freedesktop.org/wiki/Software/systemd/machined - Wants=machine.slice - After=machine.slice - RequiresMountsFor=/var/lib/machines --ConditionNull=true --ConditionNull= --ConditionNull=|!false - OnFailureIsolate=false - FailureActionExitStatus=222 - FailureActionExitStatus= -diff --git a/test/networkd-test.py b/test/networkd-test.py -index b225694..4116995 100755 ---- a/test/networkd-test.py -+++ b/test/networkd-test.py -@@ -223,7 +223,8 @@ Gateway=192.168.250.1''') - subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) - - def tearDown(self): -- subprocess.check_call(['systemctl', 'stop', 'systemd-networkd']) -+ subprocess.check_call(['systemctl', 'stop', 'systemd-networkd.socket']) -+ subprocess.check_call(['systemctl', 'stop', 'systemd-networkd.service']) - subprocess.check_call(['ip', 'link', 'del', 'mybridge']) - subprocess.check_call(['ip', 'link', 'del', 'port1']) - subprocess.check_call(['ip', 'link', 'del', 'port2']) -@@ -309,7 +310,8 @@ class ClientTestBase(NetworkdTestingUtilities): - - def tearDown(self): - self.shutdown_iface() -- subprocess.call(['systemctl', 'stop', 'systemd-networkd']) -+ subprocess.call(['systemctl', 'stop', 'systemd-networkd.socket']) -+ subprocess.call(['systemctl', 'stop', 'systemd-networkd.service']) - subprocess.call(['ip', 'link', 'del', 'dummy0'], - stderr=subprocess.DEVNULL) - -@@ -917,40 +919,7 @@ Domains= one two three four five six seven eight nine ten''') - if ' one' in contents: - break - time.sleep(0.1) -- self.assertRegex(contents, 'search .*one two three four') -- self.assertNotIn('seven\n', contents) -- self.assertIn('# Too many search domains configured, remaining ones ignored.\n', contents) -- -- def test_search_domains_too_long(self): -- -- # we don't use this interface for this test -- self.if_router = None -- -- name_prefix = 'a' * 60 -- -- self.write_network('test.netdev', '''\ --[NetDev] --Name=dummy0 --Kind=dummy --MACAddress=12:34:56:78:9a:bc''') -- self.write_network('test.network', '''\ --[Match] --Name=dummy0 --[Network] --Address=192.168.42.100/24 --DNS=192.168.42.1 --Domains={p}0 {p}1 {p}2 {p}3 {p}4'''.format(p=name_prefix)) -- -- self.start_unit('systemd-networkd') -- -- for timeout in range(50): -- with open(RESOLV_CONF) as f: -- contents = f.read() -- if ' one' in contents: -- break -- time.sleep(0.1) -- self.assertRegex(contents, 'search .*{p}0 {p}1 {p}2'.format(p=name_prefix)) -- self.assertIn('# Total length of all search domains is too long, remaining ones ignored.', contents) -+ self.assertRegex(contents, 'search .*one two three four five six seven eight nine ten') - - def test_dropin(self): - # we don't use this interface for this test -@@ -1020,7 +989,8 @@ class MatchClientTest(unittest.TestCase, NetworkdTestingUtilities): - - def tearDown(self): - """Stop networkd.""" -- subprocess.call(['systemctl', 'stop', 'systemd-networkd']) -+ subprocess.call(['systemctl', 'stop', 'systemd-networkd.socket']) -+ subprocess.call(['systemctl', 'stop', 'systemd-networkd.service']) - - def test_basic_matching(self): - """Verify the Name= line works throughout this class.""" -@@ -1070,7 +1040,8 @@ class UnmanagedClientTest(unittest.TestCase, NetworkdTestingUtilities): - - def tearDown(self): - """Stop networkd.""" -- subprocess.call(['systemctl', 'stop', 'systemd-networkd']) -+ subprocess.call(['systemctl', 'stop', 'systemd-networkd.socket']) -+ subprocess.call(['systemctl', 'stop', 'systemd-networkd.service']) - - def create_iface(self): - """Create temporary veth pairs for interface matching.""" -diff --git a/test/test-execute/exec-dynamicuser-statedir.service b/test/test-execute/exec-dynamicuser-statedir.service -index ca40934..6103193 100644 ---- a/test/test-execute/exec-dynamicuser-statedir.service -+++ b/test/test-execute/exec-dynamicuser-statedir.service -@@ -10,10 +10,10 @@ ExecStart=test -f /var/lib/waldo/yay - ExecStart=test -f /var/lib/quux/pief/yayyay - ExecStart=test -f /var/lib/private/waldo/yay - ExecStart=test -f /var/lib/private/quux/pief/yayyay --ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/waldo:%S/quux/pief"' -+ExecStart=sh -x -c 'test "$$STATE_DIRECTORY" = "%S/waldo:%S/quux/pief"' - - # Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates --ExecStart=sh -x -c 'test $$(find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf -o -path /dev/.lxc \) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo' -+ExecStart=sh -x -c 'test $$(find / \\( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf -o -path /dev/.lxc \\) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d "\\\\n") = /var/lib/private/quux/pief/var/lib/private/waldo' - - Type=oneshot - DynamicUser=yes -diff --git a/test/test-execute/exec-systemcallfilter-override-error-action.service b/test/test-execute/exec-systemcallfilter-override-error-action.service -new file mode 100644 -index 0000000..3569b45 ---- /dev/null -+++ b/test/test-execute/exec-systemcallfilter-override-error-action.service -@@ -0,0 +1,8 @@ -+[Unit] -+Description=Test for SystemCallFilter with specific kill action overriding default errno action -+ -+[Service] -+ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)' -+Type=oneshot -+SystemCallFilter=~uname:kill -+SystemCallErrorNumber=EILSEQ -diff --git a/test/test-execute/exec-systemcallfilter-override-error-action2.service b/test/test-execute/exec-systemcallfilter-override-error-action2.service -new file mode 100644 -index 0000000..04bfd6b ---- /dev/null -+++ b/test/test-execute/exec-systemcallfilter-override-error-action2.service -@@ -0,0 +1,8 @@ -+[Unit] -+Description=Test for SystemCallFilter with specific errno action overriding default kill action -+ -+[Service] -+ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)' -+Type=oneshot -+SystemCallFilter=~uname:EILSEQ -+SystemCallErrorNumber=kill -diff --git a/test/test-functions b/test/test-functions -index 863cc18..9893864 100644 ---- a/test/test-functions -+++ b/test/test-functions -@@ -4,9 +4,10 @@ - PATH=/sbin:/bin:/usr/sbin:/usr/bin - export PATH - --LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && echo yes || :) --LOOKS_LIKE_ARCH=$(source /etc/os-release && [[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && echo yes || :) --LOOKS_LIKE_SUSE=$(source /etc/os-release && [[ " $ID_LIKE " = *" suse "* ]] && echo yes || :) -+os_release=$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release) -+LOOKS_LIKE_DEBIAN=$(source $os_release && [[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && echo yes || :) -+LOOKS_LIKE_ARCH=$(source $os_release && [[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && echo yes || :) -+LOOKS_LIKE_SUSE=$(source $os_release && [[ " $ID_LIKE " = *" suse "* ]] && echo yes || :) - KERNEL_VER=${KERNEL_VER-$(uname -r)} - KERNEL_MODS="/lib/modules/$KERNEL_VER/" - QEMU_TIMEOUT="${QEMU_TIMEOUT:-infinity}" -@@ -639,7 +640,8 @@ install_dmevent() { - } - - install_systemd() { -- # install compiled files -+ ddebug "Install compiled systemd" -+ - local _ninja_bin=$(type -P ninja || type -P ninja-build) - if [[ -z "$_ninja_bin" ]]; then - dfatal "ninja was not found" -@@ -648,9 +650,6 @@ install_systemd() { - (set -x; DESTDIR=$initdir "$_ninja_bin" -C $BUILD_DIR install) - # remove unneeded documentation - rm -fr $initdir/usr/share/{man,doc} -- # we strip binaries since debug symbols increase binaries size a lot -- # and it could fill the available space -- strip_binaries - - [[ "$LOOKS_LIKE_SUSE" ]] && setup_suse - -@@ -674,7 +673,7 @@ get_ldpath() { - install_missing_libraries() { - # install possible missing libraries - for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do -- LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i)" inst_libs $i -+ LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i):$(get_ldpath $i)/src/udev" inst_libs $i - done - } - -@@ -940,7 +939,7 @@ install_config_files() { - inst /etc/shells - inst_any /etc/nsswitch.conf /usr/etc/nsswitch.conf - inst /etc/pam.conf || : -- inst /etc/os-release -+ inst_any /etc/os-release /usr/lib/os-release - inst /etc/localtime - # we want an empty environment - > $initdir/etc/environment -diff --git a/test/test-network/conf/25-address-static.network b/test/test-network/conf/25-address-static.network -index e9780f2..f8119d1 100644 ---- a/test/test-network/conf/25-address-static.network -+++ b/test/test-network/conf/25-address-static.network -@@ -51,3 +51,261 @@ Peer=2001:db8:0:f103::10/128 - - [Address] - Address=::/64 -+ -+# test for ENOBUFS issue #17012 -+[Network] -+Address=10.3.3.1/16 -+Address=10.3.3.2/16 -+Address=10.3.3.3/16 -+Address=10.3.3.4/16 -+Address=10.3.3.5/16 -+Address=10.3.3.6/16 -+Address=10.3.3.7/16 -+Address=10.3.3.8/16 -+Address=10.3.3.9/16 -+Address=10.3.3.10/16 -+Address=10.3.3.11/16 -+Address=10.3.3.12/16 -+Address=10.3.3.13/16 -+Address=10.3.3.14/16 -+Address=10.3.3.15/16 -+Address=10.3.3.16/16 -+Address=10.3.3.17/16 -+Address=10.3.3.18/16 -+Address=10.3.3.19/16 -+Address=10.3.3.20/16 -+Address=10.3.3.21/16 -+Address=10.3.3.22/16 -+Address=10.3.3.23/16 -+Address=10.3.3.24/16 -+Address=10.3.3.25/16 -+Address=10.3.3.26/16 -+Address=10.3.3.27/16 -+Address=10.3.3.28/16 -+Address=10.3.3.29/16 -+Address=10.3.3.30/16 -+Address=10.3.3.31/16 -+Address=10.3.3.32/16 -+Address=10.3.3.33/16 -+Address=10.3.3.34/16 -+Address=10.3.3.35/16 -+Address=10.3.3.36/16 -+Address=10.3.3.37/16 -+Address=10.3.3.38/16 -+Address=10.3.3.39/16 -+Address=10.3.3.40/16 -+Address=10.3.3.41/16 -+Address=10.3.3.42/16 -+Address=10.3.3.43/16 -+Address=10.3.3.44/16 -+Address=10.3.3.45/16 -+Address=10.3.3.46/16 -+Address=10.3.3.47/16 -+Address=10.3.3.48/16 -+Address=10.3.3.49/16 -+Address=10.3.3.50/16 -+Address=10.3.3.51/16 -+Address=10.3.3.52/16 -+Address=10.3.3.53/16 -+Address=10.3.3.54/16 -+Address=10.3.3.55/16 -+Address=10.3.3.56/16 -+Address=10.3.3.57/16 -+Address=10.3.3.58/16 -+Address=10.3.3.59/16 -+Address=10.3.3.60/16 -+Address=10.3.3.61/16 -+Address=10.3.3.62/16 -+Address=10.3.3.63/16 -+Address=10.3.3.64/16 -+Address=10.3.3.65/16 -+Address=10.3.3.66/16 -+Address=10.3.3.67/16 -+Address=10.3.3.68/16 -+Address=10.3.3.69/16 -+Address=10.3.3.70/16 -+Address=10.3.3.71/16 -+Address=10.3.3.72/16 -+Address=10.3.3.73/16 -+Address=10.3.3.74/16 -+Address=10.3.3.75/16 -+Address=10.3.3.76/16 -+Address=10.3.3.77/16 -+Address=10.3.3.78/16 -+Address=10.3.3.79/16 -+Address=10.3.3.80/16 -+Address=10.3.3.81/16 -+Address=10.3.3.82/16 -+Address=10.3.3.83/16 -+Address=10.3.3.84/16 -+Address=10.3.3.85/16 -+Address=10.3.3.86/16 -+Address=10.3.3.87/16 -+Address=10.3.3.88/16 -+Address=10.3.3.89/16 -+Address=10.3.3.90/16 -+Address=10.3.3.91/16 -+Address=10.3.3.92/16 -+Address=10.3.3.93/16 -+Address=10.3.3.94/16 -+Address=10.3.3.95/16 -+Address=10.3.3.96/16 -+Address=10.3.3.97/16 -+Address=10.3.3.98/16 -+Address=10.3.3.99/16 -+Address=10.3.3.100/16 -+Address=10.3.3.101/16 -+Address=10.3.3.101/16 -+Address=10.3.3.102/16 -+Address=10.3.3.103/16 -+Address=10.3.3.104/16 -+Address=10.3.3.105/16 -+Address=10.3.3.106/16 -+Address=10.3.3.107/16 -+Address=10.3.3.108/16 -+Address=10.3.3.109/16 -+Address=10.3.3.110/16 -+Address=10.3.3.111/16 -+Address=10.3.3.112/16 -+Address=10.3.3.113/16 -+Address=10.3.3.114/16 -+Address=10.3.3.115/16 -+Address=10.3.3.116/16 -+Address=10.3.3.117/16 -+Address=10.3.3.118/16 -+Address=10.3.3.119/16 -+Address=10.3.3.120/16 -+Address=10.3.3.121/16 -+Address=10.3.3.122/16 -+Address=10.3.3.123/16 -+Address=10.3.3.124/16 -+Address=10.3.3.125/16 -+Address=10.3.3.126/16 -+Address=10.3.3.127/16 -+Address=10.3.3.128/16 -+Address=10.3.3.129/16 -+Address=10.3.3.130/16 -+Address=10.3.3.131/16 -+Address=10.3.3.132/16 -+Address=10.3.3.133/16 -+Address=10.3.3.134/16 -+Address=10.3.3.135/16 -+Address=10.3.3.136/16 -+Address=10.3.3.137/16 -+Address=10.3.3.138/16 -+Address=10.3.3.139/16 -+Address=10.3.3.140/16 -+Address=10.3.3.141/16 -+Address=10.3.3.142/16 -+Address=10.3.3.143/16 -+Address=10.3.3.144/16 -+Address=10.3.3.145/16 -+Address=10.3.3.146/16 -+Address=10.3.3.147/16 -+Address=10.3.3.148/16 -+Address=10.3.3.149/16 -+Address=10.3.3.150/16 -+Address=10.3.3.151/16 -+Address=10.3.3.152/16 -+Address=10.3.3.153/16 -+Address=10.3.3.154/16 -+Address=10.3.3.155/16 -+Address=10.3.3.156/16 -+Address=10.3.3.157/16 -+Address=10.3.3.158/16 -+Address=10.3.3.159/16 -+Address=10.3.3.160/16 -+Address=10.3.3.161/16 -+Address=10.3.3.162/16 -+Address=10.3.3.163/16 -+Address=10.3.3.164/16 -+Address=10.3.3.165/16 -+Address=10.3.3.166/16 -+Address=10.3.3.167/16 -+Address=10.3.3.168/16 -+Address=10.3.3.169/16 -+Address=10.3.3.170/16 -+Address=10.3.3.171/16 -+Address=10.3.3.172/16 -+Address=10.3.3.173/16 -+Address=10.3.3.174/16 -+Address=10.3.3.175/16 -+Address=10.3.3.176/16 -+Address=10.3.3.177/16 -+Address=10.3.3.178/16 -+Address=10.3.3.179/16 -+Address=10.3.3.180/16 -+Address=10.3.3.181/16 -+Address=10.3.3.182/16 -+Address=10.3.3.183/16 -+Address=10.3.3.184/16 -+Address=10.3.3.185/16 -+Address=10.3.3.186/16 -+Address=10.3.3.187/16 -+Address=10.3.3.188/16 -+Address=10.3.3.189/16 -+Address=10.3.3.190/16 -+Address=10.3.3.191/16 -+Address=10.3.3.192/16 -+Address=10.3.3.193/16 -+Address=10.3.3.194/16 -+Address=10.3.3.195/16 -+Address=10.3.3.196/16 -+Address=10.3.3.197/16 -+Address=10.3.3.198/16 -+Address=10.3.3.199/16 -+Address=10.3.3.200/16 -+Address=10.3.3.201/16 -+Address=10.3.3.202/16 -+Address=10.3.3.203/16 -+Address=10.3.3.204/16 -+Address=10.3.3.205/16 -+Address=10.3.3.206/16 -+Address=10.3.3.207/16 -+Address=10.3.3.208/16 -+Address=10.3.3.209/16 -+Address=10.3.3.210/16 -+Address=10.3.3.211/16 -+Address=10.3.3.212/16 -+Address=10.3.3.213/16 -+Address=10.3.3.214/16 -+Address=10.3.3.215/16 -+Address=10.3.3.216/16 -+Address=10.3.3.217/16 -+Address=10.3.3.218/16 -+Address=10.3.3.219/16 -+Address=10.3.3.220/16 -+Address=10.3.3.221/16 -+Address=10.3.3.222/16 -+Address=10.3.3.223/16 -+Address=10.3.3.224/16 -+Address=10.3.3.225/16 -+Address=10.3.3.226/16 -+Address=10.3.3.227/16 -+Address=10.3.3.228/16 -+Address=10.3.3.229/16 -+Address=10.3.3.230/16 -+Address=10.3.3.231/16 -+Address=10.3.3.232/16 -+Address=10.3.3.233/16 -+Address=10.3.3.234/16 -+Address=10.3.3.235/16 -+Address=10.3.3.236/16 -+Address=10.3.3.237/16 -+Address=10.3.3.238/16 -+Address=10.3.3.239/16 -+Address=10.3.3.240/16 -+Address=10.3.3.241/16 -+Address=10.3.3.242/16 -+Address=10.3.3.243/16 -+Address=10.3.3.244/16 -+Address=10.3.3.245/16 -+Address=10.3.3.246/16 -+Address=10.3.3.247/16 -+Address=10.3.3.248/16 -+Address=10.3.3.249/16 -+Address=10.3.3.250/16 -+Address=10.3.3.251/16 -+Address=10.3.3.252/16 -+Address=10.3.3.253/16 -+Address=10.3.3.254/16 -diff --git a/test/test-network/conf/ipv6-prefix-veth-token-static-explicit.network b/test/test-network/conf/ipv6-prefix-veth-token-prefixstable-without-address.network -similarity index 61% -rename from test/test-network/conf/ipv6-prefix-veth-token-static-explicit.network -rename to test/test-network/conf/ipv6-prefix-veth-token-prefixstable-without-address.network -index 237f9aa..5fe68a2 100644 ---- a/test/test-network/conf/ipv6-prefix-veth-token-static-explicit.network -+++ b/test/test-network/conf/ipv6-prefix-veth-token-prefixstable-without-address.network -@@ -3,4 +3,4 @@ Name=veth99 - - [Network] - IPv6AcceptRA=true --IPv6Token=static:::1a:2b:3c:4d -+IPv6Token=prefixstable -diff --git a/test/test-network/conf/ipv6-prefix-veth-token-static-multiple.network b/test/test-network/conf/ipv6-prefix-veth-token-static-multiple.network -deleted file mode 100644 -index 18fecb8..0000000 ---- a/test/test-network/conf/ipv6-prefix-veth-token-static-multiple.network -+++ /dev/null -@@ -1,9 +0,0 @@ --[Match] --Name=veth99 -- --[Network] --IPv6AcceptRA=true --IPv6Token=::1a:2b:3c:4d --IPv6Token=::1a:2b:3c:4d --IPv6Token=::1a:2b:3c:4d --IPv6Token=::fa:de:ca:fe -diff --git a/test/test-network/conf/ipv6-prefix-veth-token-static.network b/test/test-network/conf/ipv6-prefix-veth-token-static.network -index 1e43bd4..5c5fdc9 100644 ---- a/test/test-network/conf/ipv6-prefix-veth-token-static.network -+++ b/test/test-network/conf/ipv6-prefix-veth-token-static.network -@@ -4,3 +4,7 @@ Name=veth99 - [Network] - IPv6AcceptRA=true - IPv6Token=::1a:2b:3c:4d -+IPv6Token=static:::fa:de:ca:fe -+IPv6Token=::1a:2b:3c:4d -+IPv6Token=static:::1a:2b:3c:4d -+IPv6Token=::fa:de:ca:fe -diff --git a/test/test-network/conf/ipv6-prefix.network b/test/test-network/conf/ipv6-prefix.network -index 215cc90..9de0e31 100644 ---- a/test/test-network/conf/ipv6-prefix.network -+++ b/test/test-network/conf/ipv6-prefix.network -@@ -12,3 +12,8 @@ DNSLifetimeSec=1min - Prefix=2002:da8:1:0::/64 - PreferredLifetimeSec=1000s - ValidLifetimeSec=2100s -+ -+[IPv6Prefix] -+Prefix=2002:da8:2:0::/64 -+PreferredLifetimeSec=1000s -+ValidLifetimeSec=2100s -diff --git a/test/test-network/conf/routing-policy-rule-reconfigure.network b/test/test-network/conf/routing-policy-rule-reconfigure.network -new file mode 100644 -index 0000000..ca38b78 ---- /dev/null -+++ b/test/test-network/conf/routing-policy-rule-reconfigure.network -@@ -0,0 +1,33 @@ -+[Match] -+Name=test1 -+ -+[Network] -+IPv6AcceptRA=no -+ -+# fwmark -+[RoutingPolicyRule] -+Table=1011 -+Family=ipv4 -+Priority=10111 -+FirewallMark=1011 -+ -+# oif -+[RoutingPolicyRule] -+Table=1011 -+Family=ipv4 -+Priority=10112 -+OutgoingInterface=test1 -+ -+# iif -+[RoutingPolicyRule] -+Table=1011 -+Family=ipv4 -+Priority=10113 -+IncomingInterface=test1 -+ -+# source -+[RoutingPolicyRule] -+Table=1011 -+Family=ipv4 -+Priority=10114 -+From=192.168.8.254 -diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py -index 0ca1fb3..6660ce0 100755 ---- a/test/test-network/systemd-networkd-tests.py -+++ b/test/test-network/systemd-networkd-tests.py -@@ -328,7 +328,7 @@ def tearDownModule(): - - shutil.rmtree(networkd_ci_path) - -- for u in ['systemd-networkd.service', 'systemd-resolved.service']: -+ for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service']: - check_output(f'systemctl stop {u}') - - shutil.rmtree('/run/systemd/system/systemd-networkd.service.d') -@@ -464,7 +464,8 @@ def remove_networkd_state_files(): - def stop_networkd(show_logs=True, remove_state_files=True): - if show_logs: - invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value') -- check_output('systemctl stop systemd-networkd') -+ check_output('systemctl stop systemd-networkd.socket') -+ check_output('systemctl stop systemd-networkd.service') - if show_logs: - print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id)) - if remove_state_files: -@@ -1734,9 +1735,11 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): - '25-vrf.network', - '26-link-local-addressing-ipv6.network', - 'routing-policy-rule-dummy98.network', -- 'routing-policy-rule-test1.network'] -+ 'routing-policy-rule-test1.network', -+ 'routing-policy-rule-reconfigure.network', -+ ] - -- routing_policy_rule_tables = ['7', '8', '9'] -+ routing_policy_rule_tables = ['7', '8', '9', '1011'] - routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']] - - def setUp(self): -@@ -1764,6 +1767,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): - self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98') - self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98') - -+ # test for ENOBUFS issue #17012 -+ for i in range(1,254): -+ self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255') -+ - # invalid sections - self.assertNotRegex(output, '10.10.0.1/16') - self.assertNotRegex(output, '10.10.0.2/16') -@@ -1789,6 +1796,14 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): - self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global') - self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global') - -+ restart_networkd() -+ self.wait_online(['dummy98:routable']) -+ -+ # test for ENOBUFS issue #17012 -+ output = check_output('ip -4 address show dev dummy98') -+ for i in range(1,254): -+ self.assertRegex(output, f'inet 10.3.3.{i}/16 brd 10.3.255.255') -+ - def test_address_preferred_lifetime_zero_ipv6(self): - copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev') - start_networkd(5) -@@ -1969,13 +1984,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): - self.assertRegex(output, 'iif test1') - self.assertRegex(output, 'lookup 8') - -- output = check_output('ip -6 rule list iif test1 priority 101') -- print(output) -- self.assertRegex(output, '101:') -- self.assertRegex(output, 'from all') -- self.assertRegex(output, 'iif test1') -- self.assertRegex(output, 'lookup 9') -- - def test_routing_policy_rule_issue_11280(self): - copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev', - 'routing-policy-rule-dummy98.network', '12-dummy.netdev') -@@ -1996,6 +2004,39 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): - - stop_networkd(remove_state_files=False) - -+ def test_routing_policy_rule_reconfigure(self): -+ copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure.network', '11-dummy.netdev') -+ start_networkd() -+ self.wait_online(['test1:degraded']) -+ -+ output = check_output('ip rule list table 1011') -+ print(output) -+ self.assertRegex(output, '10111: from all fwmark 0x3f3 lookup 1011') -+ self.assertRegex(output, '10112: from all oif test1 lookup 1011') -+ self.assertRegex(output, '10113: from all iif test1 lookup 1011') -+ self.assertRegex(output, '10114: from 192.168.8.254 lookup 1011') -+ -+ run('ip rule delete priority 10111') -+ run('ip rule delete priority 10112') -+ run('ip rule delete priority 10113') -+ run('ip rule delete priority 10114') -+ run('ip rule delete priority 10115') -+ -+ output = check_output('ip rule list table 1011') -+ print(output) -+ self.assertEqual(output, '') -+ -+ run(*networkctl_cmd, 'reconfigure', 'test1', env=env) -+ -+ self.wait_online(['test1:degraded']) -+ -+ output = check_output('ip rule list table 1011') -+ print(output) -+ self.assertRegex(output, '10111: from all fwmark 0x3f3 lookup 1011') -+ self.assertRegex(output, '10112: from all oif test1 lookup 1011') -+ self.assertRegex(output, '10113: from all iif test1 lookup 1011') -+ self.assertRegex(output, '10114: from 192.168.8.254 lookup 1011') -+ - @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable() - def test_routing_policy_rule_port_range(self): - copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev') -@@ -2428,7 +2469,8 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): - self.assertRegex(output, 'Search Domains: one') - - def test_keep_configuration_static(self): -- check_output('systemctl stop systemd-networkd') -+ check_output('systemctl stop systemd-networkd.socket') -+ check_output('systemctl stop systemd-networkd.service') - - check_output('ip link add name dummy98 type dummy') - check_output('ip address add 10.1.2.3/16 dev dummy98') -@@ -3067,9 +3109,8 @@ class NetworkdRATests(unittest.TestCase, Utilities): - 'ipv6-prefix.network', - 'ipv6-prefix-veth.network', - 'ipv6-prefix-veth-token-static.network', -- 'ipv6-prefix-veth-token-static-explicit.network', -- 'ipv6-prefix-veth-token-static-multiple.network', -- 'ipv6-prefix-veth-token-prefixstable.network'] -+ 'ipv6-prefix-veth-token-prefixstable.network', -+ 'ipv6-prefix-veth-token-prefixstable-without-address.network'] - - def setUp(self): - remove_links(self.links) -@@ -3102,34 +3143,29 @@ class NetworkdRATests(unittest.TestCase, Utilities): - output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) - print(output) - self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d') -+ self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe') -+ self.assertRegex(output, '2002:da8:2:0:1a:2b:3c:4d') -+ self.assertRegex(output, '2002:da8:2:0:fa:de:ca:fe') - -- def test_ipv6_token_static_explicit(self): -- copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-explicit.network') -- start_networkd() -- self.wait_online(['veth99:routable', 'veth-peer:degraded']) -- -- output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) -- print(output) -- self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d') -- -- def test_ipv6_token_static_multiple(self): -- copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-multiple.network') -+ def test_ipv6_token_prefixstable(self): -+ copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network') - start_networkd() - self.wait_online(['veth99:routable', 'veth-peer:degraded']) - - output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) - print(output) -- self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d') -- self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe') -+ self.assertRegex(output, '2002:da8:1:0') -+ self.assertRegex(output, '2002:da8:2:0.*78:9abc') # EUI - -- def test_ipv6_token_prefixstable(self): -- copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network') -+ def test_ipv6_token_prefixstable_without_address(self): -+ copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable-without-address.network') - start_networkd() - self.wait_online(['veth99:routable', 'veth-peer:degraded']) - - output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env) - print(output) - self.assertRegex(output, '2002:da8:1:0') -+ self.assertRegex(output, '2002:da8:2:0') - - class NetworkdDHCPServerTests(unittest.TestCase, Utilities): - links = ['veth99'] -@@ -3591,7 +3627,8 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): - print(output) - self.assertRegex(output, r'192.168.5.*') - -- check_output('systemctl stop systemd-networkd') -+ check_output('systemctl stop systemd-networkd.socket') -+ check_output('systemctl stop systemd-networkd.service') - - print('The lease address should be kept after networkd stopped') - output = check_output('ip address show dev veth99 scope global') -@@ -3626,7 +3663,8 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities): - self.assertRegex(output, r'192.168.5.*') - - stop_dnsmasq(dnsmasq_pid_file) -- check_output('systemctl stop systemd-networkd') -+ check_output('systemctl stop systemd-networkd.socket') -+ check_output('systemctl stop systemd-networkd.service') - - output = check_output('ip address show dev veth99 scope global') - print(output) -diff --git a/test/testsuite-52.units/testsuite-52.service b/test/testsuite-52.units/testsuite-52.service -old mode 100755 -new mode 100644 -diff --git a/test/udev-test.pl b/test/udev-test.pl -index 2480e41..1ab6828 100755 ---- a/test/udev-test.pl -+++ b/test/udev-test.pl -@@ -629,9 +629,9 @@ EOF - desc => "textual user/group id", - devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", - exp_name => "node", -- exp_perms => "root:mail:0660", -+ exp_perms => "root:audio:0660", - rules => </tmp/bind -- systemd-nspawn --register=no -D "$_root" --bind=/tmp/bind /bin/sh -c 'test -e /tmp/bind' -+ systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --bind=/tmp/bind /bin/sh -c 'test -e /tmp/bind' - } - - function check_norbind { -@@ -49,15 +55,15 @@ function check_norbind { - mount -t tmpfs tmpfs /tmp/binddir/subdir - echo -n "inner" > /tmp/binddir/subdir/file - /usr/lib/systemd/tests/testdata/create-busybox-container "$_root" -- systemd-nspawn --register=no -D "$_root" --bind=/tmp/binddir:/mnt:norbind /bin/sh -c 'CONTENT=$(cat /mnt/subdir/file); if [[ $CONTENT != "outer" ]]; then echo "*** unexpected content: $CONTENT"; return 1; fi' -+ systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --bind=/tmp/binddir:/mnt:norbind /bin/sh -c 'CONTENT=$(cat /mnt/subdir/file); if [[ $CONTENT != "outer" ]]; then echo "*** unexpected content: $CONTENT"; return 1; fi' - } - - function check_notification_socket { - # https://github.com/systemd/systemd/issues/4944 -- local _cmd='echo a | $(busybox which nc) -U -u -w 1 /run/systemd/nspawn/notify' -+ local _cmd='echo a | $(busybox which nc) -U -u -w 1 /run/host/notify' - # /testsuite-13.nc-container is prepared by test.sh -- systemd-nspawn --register=no -D /testsuite-13.nc-container /bin/sh -x -c "$_cmd" -- systemd-nspawn --register=no -D /testsuite-13.nc-container -U /bin/sh -x -c "$_cmd" -+ systemd-nspawn $SUSE_OPTS--register=no -D /testsuite-13.nc-container /bin/sh -x -c "$_cmd" -+ systemd-nspawn $SUSE_OPTS--register=no -D /testsuite-13.nc-container -U /bin/sh -x -c "$_cmd" - } - - function check_os_release { -@@ -79,7 +85,7 @@ if echo test >> /run/host/os-release; then exit 1; fi - echo MARKER=1 >> /etc/os-release - fi - -- systemd-nspawn --register=no -D /testsuite-13.nc-container --bind="${_os_release_source}":/tmp/os-release /bin/sh -x -e -c "$_cmd" -+ systemd-nspawn $SUSE_OPTS--register=no -D /testsuite-13.nc-container --bind="${_os_release_source}":/tmp/os-release /bin/sh -x -e -c "$_cmd" - - if grep -q MARKER /etc/os-release; then - rm /etc/os-release -@@ -100,16 +106,16 @@ function run { - local _root="/var/lib/machines/testsuite-13.unified-$1-cgns-$2-api-vfs-writable-$3" - rm -rf "$_root" - /usr/lib/systemd/tests/testdata/create-busybox-container "$_root" -- SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" -b -- SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" --private-network -b -+ SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" -b -+ SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --private-network -b - -- if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" -U -b; then -+ if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" -U -b; then - [[ "$is_user_ns_supported" = "yes" && "$3" = "network" ]] && return 1 - else - [[ "$is_user_ns_supported" = "no" && "$3" = "network" ]] && return 1 - fi - -- if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" --private-network -U -b; then -+ if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" --private-network -U -b; then - [[ "$is_user_ns_supported" = "yes" && "$3" = "yes" ]] && return 1 - else - [[ "$is_user_ns_supported" = "no" && "$3" = "yes" ]] && return 1 -@@ -118,43 +124,43 @@ function run { - local _netns_opt="--network-namespace-path=/proc/self/ns/net" - - # --network-namespace-path and network-related options cannot be used together -- if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-interface=lo -b; then -+ if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-interface=lo -b; then - return 1 - fi - -- if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-macvlan=lo -b; then -+ if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-macvlan=lo -b; then - return 1 - fi - -- if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-ipvlan=lo -b; then -+ if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-ipvlan=lo -b; then - return 1 - fi - -- if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-veth -b; then -+ if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-veth -b; then - return 1 - fi - -- if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-veth-extra=lo -b; then -+ if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-veth-extra=lo -b; then - return 1 - fi - -- if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-bridge=lo -b; then -+ if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-bridge=lo -b; then - return 1 - fi - -- if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-zone=zone -b; then -+ if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --network-zone=zone -b; then - return 1 - fi - - # allow combination of --network-namespace-path and --private-network -- if ! SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --private-network -b; then -+ if ! SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" --private-network -b; then - return 1 - fi - - # test --network-namespace-path works with a network namespace created by "ip netns" - ip netns add nspawn_test - _netns_opt="--network-namespace-path=/run/netns/nspawn_test" -- SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" /bin/ip a | grep -v -E '^1: lo.*UP' -+ SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn $SUSE_OPTS--register=no -D "$_root" "$_netns_opt" /bin/ip a | grep -v -E '^1: lo.*UP' - local r=$? - ip netns del nspawn_test - -diff --git a/test/units/testsuite-50.sh b/test/units/testsuite-50.sh -index 81e48e0..d6e1a35 100755 ---- a/test/units/testsuite-50.sh -+++ b/test/units/testsuite-50.sh -@@ -28,25 +28,27 @@ cp /usr/share/minimal.* "${image_dir}/" - image="${image_dir}/minimal" - roothash="$(cat ${image}.roothash)" - --/usr/lib/systemd/systemd-dissect ${image}.raw | grep -q -F "Found read-only 'root' partition of type squashfs with verity" --/usr/lib/systemd/systemd-dissect ${image}.raw | grep -q -F "MARKER=1" --/usr/lib/systemd/systemd-dissect ${image}.raw | grep -q -F -f /usr/lib/os-release -+os_release=$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release) -+ -+systemd-dissect --json=short ${image}.raw | grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"fstype":"squashfs","architecture":null,"verity":"external"' -+systemd-dissect ${image}.raw | grep -q -F "MARKER=1" -+systemd-dissect ${image}.raw | grep -q -F -f $os_release - - mv ${image}.verity ${image}.fooverity - mv ${image}.roothash ${image}.foohash --/usr/lib/systemd/systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F "Found read-only 'root' partition of type squashfs with verity" --/usr/lib/systemd/systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F "MARKER=1" --/usr/lib/systemd/systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F -f /usr/lib/os-release -+systemd-dissect --json=short ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"fstype":"squashfs","architecture":null,"verity":"external"' -+systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F "MARKER=1" -+systemd-dissect ${image}.raw --root-hash=${roothash} --verity-data=${image}.fooverity | grep -q -F -f $os_release - mv ${image}.fooverity ${image}.verity - mv ${image}.foohash ${image}.roothash - - mkdir -p ${image_dir}/mount ${image_dir}/mount2 --/usr/lib/systemd/systemd-dissect --mount ${image}.raw ${image_dir}/mount --cat ${image_dir}/mount/usr/lib/os-release | grep -q -F -f /usr/lib/os-release --cat ${image_dir}/mount/etc/os-release | grep -q -F -f /usr/lib/os-release -+systemd-dissect --mount ${image}.raw ${image_dir}/mount -+cat ${image_dir}/mount/usr/lib/os-release | grep -q -F -f $os_release -+cat ${image_dir}/mount/etc/os-release | grep -q -F -f $os_release - cat ${image_dir}/mount/usr/lib/os-release | grep -q -F "MARKER=1" - # Verity volume should be shared (opened only once) --/usr/lib/systemd/systemd-dissect --mount ${image}.raw ${image_dir}/mount2 -+systemd-dissect --mount ${image}.raw ${image_dir}/mount2 - verity_count=$(ls -1 /dev/mapper/ | grep -c verity) - # In theory we should check that count is exactly one. In practice, libdevmapper - # randomly and unpredictably fails with an unhelpful EINVAL when a device is open -@@ -111,19 +113,87 @@ dd if=${image}.raw of=${loop}p1 - dd if=${image}.verity of=${loop}p2 - losetup -d ${loop} - --/usr/lib/systemd/systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q "Found read-only 'root' partition (UUID $(head -c 32 ${image}.roothash)) of type squashfs for .* with verity on partition #1" --/usr/lib/systemd/systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q "Found read-only 'root-verity' partition (UUID $(tail -c 32 ${image}.roothash)) of type DM_verity_hash for .* on partition #2" --/usr/lib/systemd/systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F "MARKER=1" --/usr/lib/systemd/systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F -f /usr/lib/os-release -+# Derive partition UUIDs from root hash, in UUID syntax -+ROOT_UUID=$(systemd-id128 -u show $(head -c 32 ${image}.roothash) -u | tail -n 1 | cut -b 6-) -+VERITY_UUID=$(systemd-id128 -u show $(tail -c 32 ${image}.roothash) -u | tail -n 1 | cut -b 6-) -+ -+systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root","partition_uuid":"'$ROOT_UUID'","fstype":"squashfs","architecture":"x86-64","verity":"yes","node":' -+systemd-dissect --json=short --root-hash ${roothash} ${image}.gpt | grep -q '{"rw":"ro","designator":"root-verity","partition_uuid":"'$VERITY_UUID'","fstype":"DM_verity_hash","architecture":"x86-64","verity":null,"node":' -+systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F "MARKER=1" -+systemd-dissect --root-hash ${roothash} ${image}.gpt | grep -q -F -f $os_release - --/usr/lib/systemd/systemd-dissect --root-hash ${roothash} --mount ${image}.gpt ${image_dir}/mount --cat ${image_dir}/mount/usr/lib/os-release | grep -q -F -f /usr/lib/os-release --cat ${image_dir}/mount/etc/os-release | grep -q -F -f /usr/lib/os-release -+systemd-dissect --root-hash ${roothash} --mount ${image}.gpt ${image_dir}/mount -+cat ${image_dir}/mount/usr/lib/os-release | grep -q -F -f $os_release -+cat ${image_dir}/mount/etc/os-release | grep -q -F -f $os_release - cat ${image_dir}/mount/usr/lib/os-release | grep -q -F "MARKER=1" - umount ${image_dir}/mount - - systemd-run -t --property RootImage=${image}.gpt --property RootHash=${roothash} /usr/bin/cat /usr/lib/os-release | grep -q -F "MARKER=1" - -+systemd-run -t --property RootImage=${image}.raw --property RootImageOptions="root:nosuid,dev home:ro,dev ro,noatime" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "nosuid" -+systemd-run -t --property RootImage=${image}.gpt --property RootImageOptions="root:ro,noatime root:ro,dev" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "noatime" -+ -+mkdir -p mkdir -p ${image_dir}/result -+cat > /run/systemd/system/testservice-50a.service < /run/result/a" -+BindPaths=${image_dir}/result:/run/result -+TemporaryFileSystem=/run -+MountAPIVFS=yes -+RootImage=${image}.raw -+RootImageOptions=root:ro,noatime home:ro,dev relatime,dev -+RootImageOptions=nosuid,dev -+EOF -+systemctl start testservice-50a.service -+grep -F "squashfs" ${image_dir}/result/a | grep -q -F "noatime" -+grep -F "squashfs" ${image_dir}/result/a | grep -q -F -v "nosuid" -+ -+cat > /run/systemd/system/testservice-50b.service < /run/result/b" -+BindPaths=${image_dir}/result:/run/result -+TemporaryFileSystem=/run -+MountAPIVFS=yes -+RootImage=${image}.gpt -+RootImageOptions=root:ro,noatime,nosuid home:ro,dev nosuid,dev -+RootImageOptions=home:ro,dev nosuid,dev,%%foo -+EOF -+systemctl start testservice-50b.service -+grep -F "squashfs" ${image_dir}/result/b | grep -q -F "noatime" -+ -+# Check that specifier escape is applied %%foo -> %foo -+busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1/unit/testservice_2d50b_2eservice org.freedesktop.systemd1.Service RootImageOptions | grep -F "nosuid,dev,%foo" -+ -+# Now do some checks with MountImages, both by itself, with options and in combination with RootImage, and as single FS or GPT image -+systemd-run -t --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1" -+systemd-run -t --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1" -+systemd-run -t --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2:nosuid,dev" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "nosuid" -+systemd-run -t --property MountImages="${image}.gpt:/run/img1:root:nosuid ${image}.raw:/run/img2:home:suid" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "nosuid" -+systemd-run -t --property MountImages="${image}.raw:/run/img2\:3" /usr/bin/cat /run/img2:3/usr/lib/os-release | grep -q -F "MARKER=1" -+systemd-run -t --property MountImages="${image}.raw:/run/img2\:3:nosuid" --property MountAPIVFS=yes mount | grep -F "squashfs" | grep -q -F "nosuid" -+systemd-run -t --property TemporaryFileSystem=/run --property RootImage=${image}.raw --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /usr/lib/os-release | grep -q -F "MARKER=1" -+systemd-run -t --property TemporaryFileSystem=/run --property RootImage=${image}.raw --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1" -+systemd-run -t --property TemporaryFileSystem=/run --property RootImage=${image}.gpt --property RootHash=${roothash} --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1" -+cat >/run/systemd/system/testservice-50c.service < /run/result/c" -+ExecStart=bash -c "cat /run/img2:3/usr/lib/os-release >> /run/result/c" -+ExecStart=bash -c "mount >> /run/result/c" -+BindPaths=${image_dir}/result:/run/result -+Type=oneshot -+EOF -+systemctl start testservice-50c.service -+grep -q -F "MARKER=1" ${image_dir}/result/c -+grep -F "squashfs" ${image_dir}/result/c | grep -q -F "noatime" -+grep -F "squashfs" ${image_dir}/result/c | grep -q -F -v "nosuid" -+ - echo OK > /testok - - exit 0 -diff --git a/test/units/testsuite-54.service b/test/units/testsuite-54.service -new file mode 100644 -index 0000000..862dd1c ---- /dev/null -+++ b/test/units/testsuite-54.service -@@ -0,0 +1,7 @@ -+[Unit] -+Description=TESTSUITE-54-CREDS -+ -+[Service] -+ExecStartPre=rm -f /failed /testok -+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh -+Type=oneshot -diff --git a/test/units/testsuite-54.sh b/test/units/testsuite-54.sh -new file mode 100755 -index 0000000..aabc56f ---- /dev/null -+++ b/test/units/testsuite-54.sh -@@ -0,0 +1,31 @@ -+#!/usr/bin/env bash -+set -ex -+ -+systemd-analyze log-level debug -+ -+# Verify that the creds are properly loaded and we can read them from the service's unpriv user -+systemd-run -p LoadCredential=passwd:/etc/passwd \ -+ -p LoadCredential=shadow:/etc/shadow \ -+ -p SetCredential=dog:wuff \ -+ -p DynamicUser=1 \ -+ --wait \ -+ --pipe \ -+ cat '${CREDENTIALS_DIRECTORY}/passwd' '${CREDENTIALS_DIRECTORY}/shadow' '${CREDENTIALS_DIRECTORY}/dog' > /tmp/ts54-concat -+( cat /etc/passwd /etc/shadow && echo -n wuff ) | cmp /tmp/ts54-concat -+rm /tmp/ts54-concat -+ -+# Verify that the creds are immutable -+! systemd-run -p LoadCredential=passwd:/etc/passwd \ -+ -p DynamicUser=1 \ -+ --wait \ -+ touch '${CREDENTIALS_DIRECTORY}/passwd' -+! systemd-run -p LoadCredential=passwd:/etc/passwd \ -+ -p DynamicUser=1 \ -+ --wait \ -+ rm '${CREDENTIALS_DIRECTORY}/passwd' -+ -+systemd-analyze log-level info -+ -+echo OK > /testok -+ -+exit 0 -diff --git a/test/units/testsuite-55.service b/test/units/testsuite-55.service -new file mode 100644 -index 0000000..2127a4d ---- /dev/null -+++ b/test/units/testsuite-55.service -@@ -0,0 +1,7 @@ -+[Unit] -+Description=TESTSUITE-55-UDEV-TAGS -+ -+[Service] -+ExecStartPre=rm -f /failed /testok -+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh -+Type=oneshot -diff --git a/test/units/testsuite-55.sh b/test/units/testsuite-55.sh -new file mode 100755 -index 0000000..ffceefb ---- /dev/null -+++ b/test/units/testsuite-55.sh -@@ -0,0 +1,66 @@ -+#!/bin/bash -+set -ex -+set -o pipefail -+ -+mkdir -p /run/udev/rules.d/ -+ -+! test -f /run/udev/tags/added/c1:3 && -+ ! test -f /run/udev/tags/changed/c1:3 && -+ udevadm info /dev/null | grep -q -v 'E: TAGS=.*:added:.*' && -+ udevadm info /dev/null | grep -q -v 'E: CURRENT_TAGS=.*:added:.*' && -+ udevadm info /dev/null | grep -q -v 'E: TAGS=.*:changed:.*' && -+ udevadm info /dev/null | grep -q -v 'E: CURRENT_TAGS=.*:changed:.*' -+ -+cat > /run/udev/rules.d/50-testsuite.rules < /testok -+ -+exit 0 -diff --git a/tools/make-man-index.py b/tools/make-man-index.py -index 4d206ca..37c708d 100755 ---- a/tools/make-man-index.py -+++ b/tools/make-man-index.py -@@ -55,7 +55,8 @@ def make_index(pages): - check_id(p, t) - section = t.find('./refmeta/manvolnum').text - refname = t.find('./refnamediv/refname').text -- purpose = ' '.join(t.find('./refnamediv/refpurpose').text.split()) -+ purpose_text = ' '.join(t.find('./refnamediv/refpurpose').itertext()) -+ purpose = ' '.join(purpose_text.split()) - for f in t.findall('./refnamediv/refname'): - infos = (f.text, section, purpose, refname) - index[f.text[0].upper()].append(infos) -diff --git a/tools/syscall-names-update.sh b/tools/syscall-names-update.sh -new file mode 100755 -index 0000000..c884b93 ---- /dev/null -+++ b/tools/syscall-names-update.sh -@@ -0,0 +1,6 @@ -+#!/bin/sh -+set -eu -+ -+cd "$1" -+ -+curl -L -o syscall-names.text 'https://raw.githubusercontent.com/hrw/syscalls-table/master/syscall-names.text' -diff --git a/tools/update-dbus-docs.py b/tools/update-dbus-docs.py -index f95faaa..3500d9c 100755 ---- a/tools/update-dbus-docs.py -+++ b/tools/update-dbus-docs.py -@@ -1,6 +1,7 @@ - #!/usr/bin/env python3 - # SPDX-License-Identifier: LGPL-2.1+ - -+import argparse - import collections - import sys - import os -@@ -14,8 +15,6 @@ PARSER = etree.XMLParser(no_network=True, - strip_cdata=False, - resolve_entities=False) - --PRINT_ERRORS = True -- - class NoCommand(Exception): - pass - -@@ -37,7 +36,7 @@ def print_method(declarations, elem, *, prefix, file, is_signal=False): - argname = arg.get('name') - - if argname is None: -- if PRINT_ERRORS: -+ if opts.print_errors: - print(f'method {name}: argument {num+1} has no name', file=sys.stderr) - argname = 'UNNAMED' - -@@ -120,9 +119,11 @@ def document_has_elem_with_text(document, elem, item_repr): - else: - return False - --def check_documented(document, declarations): -+def check_documented(document, declarations, stats): - missing = [] - for klass, items in declarations.items(): -+ stats['total'] += len(items) -+ - for item in items: - if klass == 'method': - elem = 'function' -@@ -137,10 +138,12 @@ def check_documented(document, declarations): - assert False, (klass, item) - - if not document_has_elem_with_text(document, elem, item_repr): -- if PRINT_ERRORS: -+ if opts.print_errors: - print(f'{klass} {item} is not documented :(') - missing.append((klass, item)) - -+ stats['missing'] += len(missing) -+ - return missing - - def xml_to_text(destination, xml, *, only_interface=None): -@@ -165,7 +168,7 @@ def xml_to_text(destination, xml, *, only_interface=None): - - return file.getvalue(), declarations, interfaces - --def subst_output(document, programlisting): -+def subst_output(document, programlisting, stats): - executable = programlisting.get('executable', None) - if executable is None: - # Not our thing -@@ -174,7 +177,7 @@ def subst_output(document, programlisting): - node = programlisting.get('node') - interface = programlisting.get('interface') - -- argv = [f'{build_dir}/{executable}', f'--bus-introspect={interface}'] -+ argv = [f'{opts.build_dir}/{executable}', f'--bus-introspect={interface}'] - print(f'COMMAND: {shlex.join(argv)}') - - try: -@@ -189,7 +192,7 @@ def subst_output(document, programlisting): - programlisting.text = '\n' + new_text + ' ' - - if declarations: -- missing = check_documented(document, declarations) -+ missing = check_documented(document, declarations, stats) - parent = programlisting.getparent() - - # delete old comments -@@ -253,9 +256,11 @@ def process(page): - if xml.tag != 'refentry': - return - -+ stats = collections.Counter() -+ - pls = xml.findall('.//programlisting') - for pl in pls: -- subst_output(xml, pl) -+ subst_output(xml, pl, stats) - - out_text = etree.tostring(xml, encoding='unicode') - # massage format to avoid some lxml whitespace handling idiosyncrasies -@@ -264,20 +269,44 @@ def process(page): - out_text[out_text.find(' -Date: Thu, 20 Aug 2020 12:59:23 +0200 -Subject: [PATCH] sd-bus: fix error handling on readv() - -let's make sure we collect the right error code from errno, otherwise -we'll see EPERM (i.e. error 1) for all errors readv() returns (since it -returns -1 on error), including EAGAIN. - -This is definitely backport material. - -A fix-up for 3691bcf3c5eebdcca5b4f1c51c745441c57a6cd1. - -Fixes: #16699 ---- - src/libsystemd/sd-bus/bus-socket.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c -index fc7e8e844ab..de36a1f278a 100644 ---- a/src/libsystemd/sd-bus/bus-socket.c -+++ b/src/libsystemd/sd-bus/bus-socket.c -@@ -544,9 +544,11 @@ static int bus_socket_read_auth(sd_bus *b) { - - iov = IOVEC_MAKE((uint8_t *)b->rbuffer + b->rbuffer_size, n - b->rbuffer_size); - -- if (b->prefer_readv) -+ if (b->prefer_readv) { - k = readv(b->input_fd, &iov, 1); -- else { -+ if (k < 0) -+ k = -errno; -+ } else { - mh = (struct msghdr) { - .msg_iov = &iov, - .msg_iovlen = 1, -@@ -1187,9 +1189,11 @@ int bus_socket_read_message(sd_bus *bus) { - - iov = IOVEC_MAKE((uint8_t *)bus->rbuffer + bus->rbuffer_size, need - bus->rbuffer_size); - -- if (bus->prefer_readv) -+ if (bus->prefer_readv) { - k = readv(bus->input_fd, &iov, 1); -- else { -+ if (k < 0) -+ k = -errno; -+ } else { - mh = (struct msghdr) { - .msg_iov = &iov, - .msg_iovlen = 1, diff --git a/systemd.spec b/systemd.spec index a5f03973..a53a7056 100644 --- a/systemd.spec +++ b/systemd.spec @@ -1528,6 +1528,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Fri 30 Apr 2021 hexiaowen - 248-3 +- delete unused rebase-patch + * Fri 30 Apr 2021 hexiaowen - 248-2 - delete unused patches -- Gitee