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