nixpkgs/pkgs/os-specific/linux/systemd/0019-core-handle-lookup-paths-being-symlinks.patch
2022-03-05 21:27:44 +01:00

81 lines
3.7 KiB
Diff

From 169fc6f270ff3e3903a7a31550c964152f9751ec Mon Sep 17 00:00:00 2001
From: Andreas Rammhold <andreas@rammhold.de>
Date: Wed, 18 Aug 2021 19:10:08 +0200
Subject: [PATCH 19/19] core: handle lookup paths being symlinks
With a recent change paths leaving the statically known lookup paths
would be treated differently then those that remained within those. That
was done (AFAIK) to consistently handle alias names. Unfortunately that
means that on some distributions, especially those where /etc/ consists
mostly of symlinks, would trigger that new detection for every single
unit in /etc/systemd/system. The reason for that is that the units
directory itself is already a symlink.
---
src/basic/unit-file.c | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/src/basic/unit-file.c b/src/basic/unit-file.c
index 30c632dfce..6179100126 100644
--- a/src/basic/unit-file.c
+++ b/src/basic/unit-file.c
@@ -255,6 +255,7 @@ int unit_file_build_name_map(
_cleanup_hashmap_free_ Hashmap *ids = NULL, *names = NULL;
_cleanup_set_free_free_ Set *paths = NULL;
+ _cleanup_strv_free_ char **expanded_search_paths = NULL;
uint64_t timestamp_hash;
char **dir;
int r;
@@ -274,6 +275,34 @@ int unit_file_build_name_map(
return log_oom();
}
+ /* Go over all our search paths, chase their symlinks and store the
+ * result in the expanded_search_paths list.
+ *
+ * This is important for cases where any of the unit directories itself
+ * are symlinks into other directories and would therefore cause all of
+ * the unit files to be recognized as linked units.
+ *
+ * This is important for distributions such as NixOS where most paths
+ * in /etc/ are symlinks to some other location on the filesystem (e.g.
+ * into /nix/store/).
+ */
+ STRV_FOREACH(dir, (char**) lp->search_path) {
+ _cleanup_free_ char *resolved_dir = NULL;
+ r = strv_extend(&expanded_search_paths, *dir);
+ if (r < 0)
+ return log_oom();
+
+ r = chase_symlinks(*dir, NULL, 0, &resolved_dir, NULL);
+ if (r < 0) {
+ if (r != -ENOENT)
+ log_warning_errno(r, "Failed to resolve symlink %s, ignoring: %m", *dir);
+ continue;
+ }
+
+ if (strv_consume(&expanded_search_paths, TAKE_PTR(resolved_dir)) < 0)
+ return log_oom();
+ }
+
STRV_FOREACH(dir, (char**) lp->search_path) {
_cleanup_closedir_ DIR *d = NULL;
@@ -386,11 +415,11 @@ int unit_file_build_name_map(
continue;
}
- /* Check if the symlink goes outside of our search path.
+ /* Check if the symlink goes outside of our (expanded) 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 source directly.
* If not, let's verify that it's a good symlink. */
- char *tail = path_startswith_strv(simplified, lp->search_path);
+ char *tail = path_startswith_strv(simplified, expanded_search_paths);
if (!tail) {
log_debug("%s: linked unit file: %s → %s",
__func__, filename, simplified);
--
2.34.0