81 lines
3.7 KiB
Diff
81 lines
3.7 KiB
Diff
|
From 5f17b65d30480e489e135b403a072b38535b2911 Mon Sep 17 00:00:00 2001
|
||
|
From: Andreas Rammhold <andreas@rammhold.de>
|
||
|
Date: Wed, 18 Aug 2021 19:10:08 +0200
|
||
|
Subject: [PATCH] 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 884a0674a9..3ae2a115d0 100644
|
||
|
--- a/src/basic/unit-file.c
|
||
|
+++ b/src/basic/unit-file.c
|
||
|
@@ -254,6 +254,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;
|
||
|
@@ -273,6 +274,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) {
|
||
|
struct dirent *de;
|
||
|
_cleanup_closedir_ DIR *d = NULL;
|
||
|
@@ -351,11 +380,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.32.0
|
||
|
|