You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
4.2 KiB
89 lines
4.2 KiB
From dc017e5c51e61ddd96d2a94f35223ac7788c8454 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 |
|
MIME-Version: 1.0 |
|
Content-Type: text/plain; charset=UTF-8 |
|
Content-Transfer-Encoding: 8bit |
|
|
|
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. |
|
|
|
Rebased-by: Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> |
|
(cherry picked from commit 66c38cd0536c50769eba6abccf383bbaceb268ca) |
|
|
|
Resolves: #2082131 |
|
--- |
|
src/basic/unit-file.c | 41 ++++++++++++++++++++++++++++++++++++++++- |
|
1 file changed, 40 insertions(+), 1 deletion(-) |
|
|
|
diff --git a/src/basic/unit-file.c b/src/basic/unit-file.c |
|
index 7c1ae515e1..83c29bb25f 100644 |
|
--- a/src/basic/unit-file.c |
|
+++ b/src/basic/unit-file.c |
|
@@ -388,6 +388,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_path = NULL; |
|
uint64_t timestamp_hash; |
|
int r; |
|
|
|
@@ -406,6 +407,44 @@ 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_path 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/). |
|
+ * |
|
+ * Search paths are ordered by priority (highest first), and we need to maintain this order. |
|
+ * If a resolved path is already in the list, we don't need to include. |
|
+ * |
|
+ * Note that we build a list that contains both the original paths and the resolved symlinks: |
|
+ * we need the latter for the case where the directory is symlinked, as described above, and |
|
+ * the former for the case where some unit file alias is a dangling symlink that points to one |
|
+ * of the "original" directories (and can't be followed). |
|
+ */ |
|
+ STRV_FOREACH(dir, lp->search_path) { |
|
+ _cleanup_free_ char *resolved_dir = NULL; |
|
+ |
|
+ r = strv_extend(&expanded_search_path, *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_contains(expanded_search_path, resolved_dir)) |
|
+ continue; |
|
+ |
|
+ if (strv_consume(&expanded_search_path, TAKE_PTR(resolved_dir)) < 0) |
|
+ return log_oom(); |
|
+ } |
|
+ |
|
STRV_FOREACH(dir, lp->search_path) { |
|
_cleanup_closedir_ DIR *d = NULL; |
|
|
|
@@ -504,7 +543,7 @@ int unit_file_build_name_map( |
|
/* 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. */ |
|
|
|
- r = unit_file_resolve_symlink(lp->root_dir, lp->search_path, |
|
+ r = unit_file_resolve_symlink(lp->root_dir, expanded_search_path, |
|
*dir, dirfd(d), de->d_name, |
|
/* resolve_destination_target= */ false, |
|
&dst);
|
|
|