diff --git a/src/basic/unit-file.c b/src/basic/unit-file.c index 3383d1afad..236fc64a8f 100644 --- a/src/basic/unit-file.c +++ b/src/basic/unit-file.c @@ -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 { diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index d0aeaf1c76..92ce62be4b 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -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; diff --git a/test/units/testsuite-15.sh b/test/units/testsuite-15.sh index b872a24c20..bf6a5c7a87 100755 --- a/test/units/testsuite-15.sh +++ b/test/units/testsuite-15.sh @@ -124,6 +124,32 @@ EOF clear_services test15-a test15-b test15-c } +test_linked_units () { + echo "Testing linked units..." + echo "*** test linked unit (same basename)" + + create_service test15-a + mv /etc/systemd/system/test15-a.service / + ln -s /test15-a.service /etc/systemd/system/ + ln -s test15-a.service /etc/systemd/system/test15-b.service + + check_ok test15-a Names test15-a.service + check_ok test15-a Names test15-b.service + + echo "*** test linked unit (cross basename)" + + mv /test15-a.service /test15-a@.scope + ln -fs /test15-a@.scope /etc/systemd/system/test15-a.service + systemctl daemon-reload + + check_ok test15-a Names test15-a.service + check_ok test15-a Names test15-b.service + check_ko test15-a Names test15-b@ + + rm /test15-a@.scope + clear_services test15-a test15-b +} + test_hierarchical_dropins () { echo "Testing hierarchical dropins..." echo "*** test service.d/ top level drop-in" @@ -465,6 +491,7 @@ test_invalid_dropins () { } test_basic_dropins +test_linked_units test_hierarchical_dropins test_template_dropins test_alias_dropins