1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-23 17:34:00 +03:00

shared/install: when looking for symlinks in .wants/.requires, ignore symlink target

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.servicebar.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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2022-03-16 17:37:58 +01:00
parent d6c9411072
commit 466f6979c9

View File

@ -746,7 +746,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) {
@ -754,51 +755,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;
/* Make absolute */
if (!path_is_absolute(dest)) {
char *x;
/* 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;
}
x = path_join(dir_path, dest);
if (!x)
return -ENOMEM;
/* Make absolute */
if (!path_is_absolute(dest)) {
char *x;
free_and_replace(dest, x);
x = path_join(dir_path, dest);
if (!x)
return -ENOMEM;
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);
@ -811,7 +828,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] */
@ -870,7 +887,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)
@ -879,7 +901,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(