summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-02-07 16:22:49 +0100
committerLennart Poettering <lennart@poettering.net>2017-02-07 16:22:49 +0100
commit9f6cbcf53cd3abe416b9808bbfb5648c6b808400 (patch)
tree5fa198f67ded05065ac5bb2101a624bcb4e7b60a /src
parentd52fbaa58c6b0c928d1d9a2d015edcc63acb0df6 (diff)
install: don't enter loop when traversing a template symlinks
Before this patch, if we'd encounter an instance or template symlink while traversing a chain of symlinks we'd fill in the instance name and retry the iteration. This makes no sense if the resulting name is actually the same as we are coming from, as we'd just spin a couple of times in the loop, until the UNIT_FILE_FOLLOW_SYMLINK_MAX iteration limit is hit. Fix this, by accepted the symlink as it is, if it identical to what we filled in.
Diffstat (limited to 'src')
-rw-r--r--src/shared/install.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/shared/install.c b/src/shared/install.c
index 478abac8ab..975a789ebe 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1354,7 +1354,8 @@ static int install_info_follow(
InstallContext *c,
UnitFileInstallInfo *i,
const char *root_dir,
- SearchFlags flags) {
+ SearchFlags flags,
+ bool ignore_different_name) {
assert(c);
assert(i);
@@ -1367,7 +1368,7 @@ static int install_info_follow(
/* If the basename doesn't match, the caller should add a
* complete new entry for this. */
- if (!streq(basename(i->symlink_target), i->name))
+ if (!ignore_different_name && !streq(basename(i->symlink_target), i->name))
return -EXDEV;
free_and_replace(i->path, i->symlink_target);
@@ -1415,7 +1416,7 @@ static int install_info_traverse(
return -ELOOP;
}
- r = install_info_follow(c, i, paths->root_dir, flags);
+ r = install_info_follow(c, i, paths->root_dir, flags, false);
if (r == -EXDEV) {
_cleanup_free_ char *buffer = NULL;
const char *bn;
@@ -1439,6 +1440,18 @@ static int install_info_traverse(
if (r < 0)
return r;
+ if (streq(buffer, i->name)) {
+
+ /* We filled in the instance, and the target stayed the same? If so, then let's
+ * honour the link as it is. */
+
+ r = install_info_follow(c, i, paths->root_dir, flags, true);
+ if (r < 0)
+ return r;
+
+ continue;
+ }
+
bn = buffer;
}