]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/unit-file: when loading linked unit files, use link source as "fragment path"
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 14 Feb 2021 13:38:32 +0000 (14:38 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 14 Feb 2021 13:49:00 +0000 (14:49 +0100)
The general idea is that when a unit file is "linked" (i.e. installed by
symlinking from outside of the search paths), the *destination* name is
irrelevant. It doesn't even have to be a valid unit name, or to match the type
or instance value. The obvious collorary is that we shouldn't look at the
symlink destination name to derive the unit name, instance value, or anything
else at all.

When building the name map, when we find a linked unit (possibly at the end
of a series of alias redirects), store the *source* of the final symlink as the
fragment path. This has two effects:
- we stop looking at the *target* file name to derive unit info, i.e. actually
  implement the stuff described in the first paragraph.
- we load the unit fragment through the symlink. If someone were to remove the
  symlink, we'll not load the unit. This seems like the right thing.

Fixes #18058.
Before this change, we were generally quite confused about unit alises for
linked units. Fortunately most poeple use the same symlink source and target,
so in practice we wouldn't hit this too often.

In unit_load_fragment() a comment is added to explain what we're doing there.

src/basic/unit-file.c
src/core/load-fragment.c

index 3383d1afadfc0d1fa52a51a623de8b20aae1a9f6..236fc64a8f308cc999c2057e759d59aaad92fd77 100644 (file)
@@ -354,10 +354,16 @@ int unit_file_build_name_map(
 
                                 /* Check if the symlink goes outside of our search path.
                                  * If yes, it's a linked unit file or mask, and we don't care about the target name.
-                                 * Let's just store the link destination directly.
+                                 * Let's just store the link source directly.
                                  * If not, let's verify that it's a good symlink. */
                                 char *tail = path_startswith_strv(simplified, lp->search_path);
-                                if (tail) {
+                                if (!tail) {
+                                        log_debug("%s: linked unit file: %s → %s",
+                                                  __func__, filename, simplified);
+
+                                        dst = filename;
+                                } else {
+
                                         bool self_alias;
 
                                         dst = basename(simplified);
@@ -380,10 +386,6 @@ int unit_file_build_name_map(
                                         }
 
                                         log_debug("%s: alias: %s/%s → %s", __func__, *dir, de->d_name, dst);
-                                } else {
-                                        dst  = simplified;
-
-                                        log_debug("%s: linked unit file: %s/%s → %s", __func__, *dir, de->d_name, dst);
                                 }
 
                         } else {
index d0aeaf1c76b7090fc46e56512de4242bb79d6681..92ce62be4b163ee516143ce44c5a842de224d521 100644 (file)
@@ -5536,10 +5536,11 @@ int unit_load_fragment(Unit *u) {
                 }
         }
 
-        /* We do the merge dance here because for some unit types, the unit might have aliases which are not
+        /* Call merge_by_names with the name derived from the fragment path as the preferred name.
+         *
+         * We do the merge dance here because for some unit types, the unit might have aliases which are not
          * declared in the file system. In particular, this is true (and frequent) for device and swap units.
          */
-        Unit *merged;
         const char *id = u->id;
         _cleanup_free_ char *free_id = NULL;
 
@@ -5556,7 +5557,7 @@ int unit_load_fragment(Unit *u) {
                 }
         }
 
-        merged = u;
+        Unit *merged = u;
         r = merge_by_names(&merged, names, id);
         if (r < 0)
                 return r;