summaryrefslogtreecommitdiff
path: root/src/shared/install.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-12-13 10:46:27 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-12-13 10:46:27 +0100
commit4b37c89f066209490197f680a597af2297ec008c (patch)
tree35ec035ceaaba05940169f462906722d44be5e45 /src/shared/install.c
parent3e8d06d951d33c463e1efb67501e664f82cf3708 (diff)
downloadsystemd-4b37c89f066209490197f680a597af2297ec008c.tar.gz
shared/install: ignore symlinks which have lower priority than the unit file
In #10583, a unit file lives in ~/.config/systemd/user, and 'systemctl --runtime --user mask' is used to create a symlink in /run. This symlink has lower priority than the config file, so 'systemctl --user' will happily load the unit file, and does't care about the symlink at all. But when asked if the unit is enabled, we'd look for all symlinks, find the symlink in the runtime directory, and report that the unit is runtime-enabled. In this particular case the fact that the symlink points at /dev/null, creates additional confusion, but it doesn't really matter: *any* symlink (or regular file) that is lower in the priority order is "covered" by the unit fragment, and should be ignored. Fixes #10583.
Diffstat (limited to 'src/shared/install.c')
-rw-r--r--src/shared/install.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/src/shared/install.c b/src/shared/install.c
index 37d8830781..164eea2bde 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -715,6 +715,7 @@ static int find_symlinks_fd(
const char *root_dir,
const UnitFileInstallInfo *i,
bool match_aliases,
+ bool ignore_same_name,
int fd,
const char *path,
const char *config_path,
@@ -761,7 +762,7 @@ static int find_symlinks_fd(
}
/* This will close nfd, regardless whether it succeeds or not */
- q = find_symlinks_fd(root_dir, i, match_aliases, nfd,
+ q = find_symlinks_fd(root_dir, i, match_aliases, ignore_same_name, nfd,
p, config_path, same_name_link);
if (q > 0)
return 1;
@@ -770,7 +771,7 @@ static int find_symlinks_fd(
} else if (de->d_type == DT_LNK) {
_cleanup_free_ char *p = NULL, *dest = NULL;
- bool found_path, found_dest, b = false;
+ bool found_path = false, found_dest, b = false;
int q;
/* Acquire symlink name */
@@ -799,9 +800,14 @@ static int find_symlinks_fd(
free_and_replace(dest, x);
}
- /* Check if the symlink itself matches what we are looking for */
assert(unit_name_is_valid(i->name, UNIT_NAME_ANY));
- found_path = streq(de->d_name, i->name);
+ 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, i->name);
/* Check if what the symlink points to matches what we are looking for */
found_dest = streq(basename(dest), i->name);
@@ -841,6 +847,7 @@ static int find_symlinks(
const char *root_dir,
const UnitFileInstallInfo *i,
bool match_name,
+ bool ignore_same_name,
const char *config_path,
bool *same_name_link) {
@@ -858,7 +865,7 @@ static int find_symlinks(
}
/* This takes possession of fd and closes it */
- return find_symlinks_fd(root_dir, i, match_name, fd,
+ return find_symlinks_fd(root_dir, i, match_name, ignore_same_name, fd,
config_path, config_path, same_name_link);
}
@@ -871,16 +878,21 @@ static int find_symlinks_in_scope(
bool same_name_link_runtime = false, same_name_link_config = false;
bool enabled_in_runtime = false, enabled_at_all = false;
+ bool ignore_same_name = false;
char **p;
int r;
assert(paths);
assert(i);
+ /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name"
+ * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are
+ * efectively masked, so we should ignore them. */
+
STRV_FOREACH(p, paths->search_path) {
bool same_name_link = false;
- r = find_symlinks(paths->root_dir, i, match_name, *p, &same_name_link);
+ r = find_symlinks(paths->root_dir, i, match_name, ignore_same_name, *p, &same_name_link);
if (r < 0)
return r;
if (r > 0) {
@@ -917,6 +929,11 @@ static int find_symlinks_in_scope(
same_name_link_runtime = true;
}
}
+
+ /* Check if next iteration will be "below" the unit file (either a regular file
+ * or a symlink), and hence should be ignored */
+ if (!ignore_same_name && path_startswith(i->path, *p))
+ ignore_same_name = true;
}
if (enabled_in_runtime) {