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.
177 lines
8.0 KiB
177 lines
8.0 KiB
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(
|
|
|