1abbee
From 412044ee341c574e5163bf2be32e5da9618f2640 Mon Sep 17 00:00:00 2001
1abbee
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
1abbee
Date: Sat, 13 Aug 2016 01:20:29 -0400
1abbee
Subject: [PATCH] shared/install: ignore unit symlinks when doing preset-all
1abbee
1abbee
Before, when interating over unit files during preset-all, behaviour was the
1abbee
following:
1abbee
1abbee
- if we hit the real unit name first, presets were queried for that name, and
1abbee
  that unit was enabled or disabled accordingly,
1abbee
1abbee
- if we hit an alias first (one of the symlinks chaining to the real unit), we
1abbee
  checked the presets using the symlink name, and then proceeded to enable or
1abbee
  disable the real unit.
1abbee
1abbee
E.g. for systemd-networkd.service we have the alias dbus-org.freedesktop.network1.service
1abbee
(/usr/lib/systemd/system/dbus-org.freedesktop.network1.service), but the preset
1abbee
is only for the systemd-networkd.service name. The service would be enabled or
1abbee
disabled pseudorandomly depending on the order of iteration.
1abbee
1abbee
For "preset", behaviour was analogous: preset on the alias name disabled the
1abbee
service (following the default disable policy), preset on the "real" name
1abbee
applied the presets.
1abbee
1abbee
With the patch, for "preset" and "preset-all" we silently skip symlinks. This
1abbee
gives mostly the right behaviour, with the limitation that presets on aliases
1abbee
are ignored.  I think that presets on aliases are not that common (at least my
1abbee
preset files on Fedora don't exhibit any such usage), and should not be
1abbee
necessary, since whoever installs the preset can just refer to the real unit
1abbee
file. It would be possible to overcome this limitation by gathering a list of
1abbee
names of a unit first, and then checking whether *any* of the names matches the
1abbee
presets list. That would require a significant redesign of the code, and be
1abbee
a lot slower (since we would have to fully read all unit directories to preset
1abbee
one unit) to so I'm not doing that for now.
1abbee
1abbee
With this patch, two properties are satisfied:
1abbee
- preset-all and preset are idempotent, and the second and subsequent invocations
1abbee
  do not produce any changes,
1abbee
- preset-all and preset for a specific name produce the same state for that unit.
1abbee
1abbee
Fixes #3616.
1abbee
1abbee
Cherry-picked from: 11e11fd57a837ea1cb142009c3048882392f3ed3
1abbee
Related: #1375097
1abbee
---
1abbee
 src/shared/install.c | 12 ++++++++++--
1abbee
 1 file changed, 10 insertions(+), 2 deletions(-)
1abbee
1abbee
diff --git a/src/shared/install.c b/src/shared/install.c
c62b8e
index b0a29ddd7e..f01a212620 100644
1abbee
--- a/src/shared/install.c
1abbee
+++ b/src/shared/install.c
1abbee
@@ -2270,12 +2270,20 @@ static int preset_prepare_one(
1abbee
                 const char *name) {
1abbee
 
1abbee
         InstallInfo *i;
1abbee
+        _cleanup_(install_context_done) InstallContext tmp = {};
1abbee
         int r;
1abbee
 
1abbee
-        if (install_info_find(plus, name) ||
1abbee
-            install_info_find(minus, name))
1abbee
+        if (install_info_find(plus, name) || install_info_find(minus, name))
1abbee
                 return 0;
1abbee
 
1abbee
+        r = install_info_discover(scope, &tmp, root_dir, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, &i);
1abbee
+        if (r < 0)
1abbee
+                return r;
1abbee
+        if (!streq(name, i->name)) {
1abbee
+                log_debug("Skipping %s because is an alias for %s", name, i->name);
1abbee
+                return 0;
1abbee
+        }
1abbee
+
1abbee
         r = unit_file_query_preset(scope, root_dir, name);
1abbee
         if (r < 0)
1abbee
                 return r;