0daf48d9aa
Resolves: #2047682,#2068043,#2068131,#2073003,#2073994,#2082131,#2083493,#2087652,#2100340
178 lines
8.0 KiB
Diff
178 lines
8.0 KiB
Diff
From 43f62843fbc5e5d085874393c24cf52ebb6658eb Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
|
Date: Wed, 16 Mar 2022 17:37:58 +0100
|
|
Subject: [PATCH] shared/install: when looking for symlinks in
|
|
.wants/.requires, ignore symlink target
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
We'd say that file is enabled indirectly if we had a symlink like:
|
|
foo@.service ← bar.target.wants/foo@one.service
|
|
but not when we had
|
|
foo@one.service ← bar.target.wants/foo@one.service
|
|
|
|
The effect of both link types is the same. In fact we don't care
|
|
about the symlink target. (We'll warn if it is mismatched, but we honour
|
|
it anyway.)
|
|
|
|
So let's use the original match logic only for aliases.
|
|
For .wants/.requires we instead look for a matching source name,
|
|
or a source name that matches after stripping of instance.
|
|
|
|
(cherry picked from commit 466f6979c90aaee62c33723392cc49c6638a3f46)
|
|
|
|
Related: #2082131
|
|
---
|
|
src/shared/install.c | 93 ++++++++++++++++++++++++++++----------------
|
|
1 file changed, 60 insertions(+), 33 deletions(-)
|
|
|
|
diff --git a/src/shared/install.c b/src/shared/install.c
|
|
index 1a2b0ccf24..a864039f44 100644
|
|
--- a/src/shared/install.c
|
|
+++ b/src/shared/install.c
|
|
@@ -748,7 +748,8 @@ static int find_symlinks_in_directory(
|
|
const char *dir_path,
|
|
const char *root_dir,
|
|
const UnitFileInstallInfo *info,
|
|
- bool match_aliases,
|
|
+ bool ignore_destination,
|
|
+ bool match_name,
|
|
bool ignore_same_name,
|
|
const char *config_path,
|
|
bool *same_name_link) {
|
|
@@ -756,51 +757,67 @@ static int find_symlinks_in_directory(
|
|
int r = 0;
|
|
|
|
FOREACH_DIRENT(de, dir, return -errno) {
|
|
- _cleanup_free_ char *dest = NULL;
|
|
- bool found_path = false, found_dest, b = false;
|
|
+ bool found_path = false, found_dest = false, b = false;
|
|
int q;
|
|
|
|
if (de->d_type != DT_LNK)
|
|
continue;
|
|
|
|
- /* Acquire symlink destination */
|
|
- q = readlinkat_malloc(dirfd(dir), de->d_name, &dest);
|
|
- if (q == -ENOENT)
|
|
- continue;
|
|
- if (q < 0) {
|
|
- if (r == 0)
|
|
- r = q;
|
|
- continue;
|
|
- }
|
|
+ if (!ignore_destination) {
|
|
+ _cleanup_free_ char *dest = NULL;
|
|
+
|
|
+ /* Acquire symlink destination */
|
|
+ q = readlinkat_malloc(dirfd(dir), de->d_name, &dest);
|
|
+ if (q == -ENOENT)
|
|
+ continue;
|
|
+ if (q < 0) {
|
|
+ if (r == 0)
|
|
+ r = q;
|
|
+ continue;
|
|
+ }
|
|
|
|
- /* Make absolute */
|
|
- if (!path_is_absolute(dest)) {
|
|
- char *x;
|
|
+ /* Make absolute */
|
|
+ if (!path_is_absolute(dest)) {
|
|
+ char *x;
|
|
|
|
- x = path_join(dir_path, dest);
|
|
- if (!x)
|
|
- return -ENOMEM;
|
|
+ x = path_join(dir_path, dest);
|
|
+ if (!x)
|
|
+ return -ENOMEM;
|
|
|
|
- free_and_replace(dest, x);
|
|
+ free_and_replace(dest, x);
|
|
+ }
|
|
+
|
|
+ /* Check if what the symlink points to matches what we are looking for */
|
|
+ found_dest = streq(basename(dest), info->name);
|
|
}
|
|
|
|
assert(unit_name_is_valid(info->name, UNIT_NAME_ANY));
|
|
- if (!ignore_same_name)
|
|
- /* Check if the symlink itself matches what we are looking for.
|
|
- *
|
|
- * If ignore_same_name is specified, we are in one of the directories which
|
|
- * have lower priority than the unit file, and even if a file or symlink with
|
|
- * this name was found, we should ignore it. */
|
|
- found_path = streq(de->d_name, info->name);
|
|
|
|
- /* Check if what the symlink points to matches what we are looking for */
|
|
- found_dest = streq(basename(dest), info->name);
|
|
+ /* Check if the symlink itself matches what we are looking for.
|
|
+ *
|
|
+ * If ignore_destination is specified, we only look at the source name.
|
|
+ *
|
|
+ * If ignore_same_name is specified, we are in one of the directories which
|
|
+ * have lower priority than the unit file, and even if a file or symlink with
|
|
+ * this name was found, we should ignore it. */
|
|
+
|
|
+ if (ignore_destination || !ignore_same_name)
|
|
+ found_path = streq(de->d_name, info->name);
|
|
+
|
|
+ if (!found_path && ignore_destination) {
|
|
+ _cleanup_free_ char *template = NULL;
|
|
+
|
|
+ q = unit_name_template(de->d_name, &template);
|
|
+ if (q < 0 && q != -EINVAL)
|
|
+ return q;
|
|
+ if (q >= 0)
|
|
+ found_dest = streq(template, info->name);
|
|
+ }
|
|
|
|
if (found_path && found_dest) {
|
|
_cleanup_free_ char *p = NULL, *t = NULL;
|
|
|
|
- /* Filter out same name links in the main
|
|
- * config path */
|
|
+ /* Filter out same name links in the main config path */
|
|
p = path_make_absolute(de->d_name, dir_path);
|
|
t = path_make_absolute(info->name, config_path);
|
|
|
|
@@ -813,7 +830,7 @@ static int find_symlinks_in_directory(
|
|
if (b)
|
|
*same_name_link = true;
|
|
else if (found_path || found_dest) {
|
|
- if (!match_aliases)
|
|
+ if (!match_name)
|
|
return 1;
|
|
|
|
/* Check if symlink name is in the set of names used by [Install] */
|
|
@@ -872,7 +889,12 @@ static int find_symlinks(
|
|
continue;
|
|
}
|
|
|
|
- r = find_symlinks_in_directory(d, path, root_dir, i, match_name, ignore_same_name, config_path, same_name_link);
|
|
+ r = find_symlinks_in_directory(d, path, root_dir, i,
|
|
+ /* ignore_destination= */ true,
|
|
+ /* match_name= */ match_name,
|
|
+ /* ignore_same_name= */ ignore_same_name,
|
|
+ config_path,
|
|
+ same_name_link);
|
|
if (r > 0)
|
|
return 1;
|
|
else if (r < 0)
|
|
@@ -881,7 +903,12 @@ static int find_symlinks(
|
|
|
|
/* We didn't find any suitable symlinks in .wants or .requires directories, let's look for linked unit files in this directory. */
|
|
rewinddir(config_dir);
|
|
- return find_symlinks_in_directory(config_dir, config_path, root_dir, i, match_name, ignore_same_name, config_path, same_name_link);
|
|
+ return find_symlinks_in_directory(config_dir, config_path, root_dir, i,
|
|
+ /* ignore_destination= */ false,
|
|
+ /* match_name= */ match_name,
|
|
+ /* ignore_same_name= */ ignore_same_name,
|
|
+ config_path,
|
|
+ same_name_link);
|
|
}
|
|
|
|
static int find_symlinks_in_scope(
|