install: preset in the scope the caller asked for
unit_file_preset() and unit_file_preset_all() zero-initialized their install contexts, so their scope was always RUNTIME_SCOPE_SYSTEM. In the global scope, specifiers in [Install] were then resolved as if for the system: %U became 0 and a unit got enabled into target-0.target.wants/. Set the scope the caller asked for, so that this fails with -EUNATCH instead. Covered by a new test that presets a unit using %U in the global scope, with both functions. (cherry picked from commit 0a4491ef3fce30d31a35c95031c8026a0235e0a2)
This commit is contained in:
committed by
Luca Boccassi
parent
d14b9ace0c
commit
c74e3aa5b7
@@ -3688,7 +3688,7 @@ int unit_file_preset(
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
_cleanup_(install_context_done) InstallContext plus = {}, minus = {};
|
||||
_cleanup_(install_context_done) InstallContext plus = { .scope = scope }, minus = { .scope = scope };
|
||||
_cleanup_(lookup_paths_done) LookupPaths lp = {};
|
||||
_cleanup_(unit_file_presets_done) UnitFilePresets presets = {};
|
||||
const char *config_path;
|
||||
@@ -3727,7 +3727,7 @@ int unit_file_preset_all(
|
||||
InstallChange **changes,
|
||||
size_t *n_changes) {
|
||||
|
||||
_cleanup_(install_context_done) InstallContext plus = {}, minus = {};
|
||||
_cleanup_(install_context_done) InstallContext plus = { .scope = scope }, minus = { .scope = scope };
|
||||
_cleanup_(lookup_paths_done) LookupPaths lp = {};
|
||||
_cleanup_(unit_file_presets_done) UnitFilePresets presets = {};
|
||||
const char *config_path = NULL;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "path-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "special.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
@@ -1131,6 +1132,48 @@ TEST(preset_multiple_instances) {
|
||||
install_changes_free(changes, n_changes);
|
||||
}
|
||||
|
||||
TEST(preset_scope) {
|
||||
const char *unit, *preset, *link;
|
||||
InstallChange *changes = NULL;
|
||||
size_t n_changes = 0;
|
||||
|
||||
/* %U can't be resolved in the global scope, since there's no user to resolve it to. Make sure
|
||||
* presetting in the global scope fails because of that, instead of resolving specifiers in the
|
||||
* system scope (where %U is 0) and creating a target-0.target.wants/ symlink. Check both
|
||||
* unit_file_preset() and unit_file_preset_all(), they set up their install contexts separately. */
|
||||
|
||||
unit = strjoina(root, "/usr/lib/systemd/user/scoped.service");
|
||||
ASSERT_OK(mkdir_parents(unit, 0755));
|
||||
ASSERT_OK(write_string_file(unit,
|
||||
"[Install]\n"
|
||||
"WantedBy=target-%U.target\n", WRITE_STRING_FILE_CREATE));
|
||||
|
||||
preset = strjoina(root, "/usr/lib/systemd/user-preset/50-scoped.preset");
|
||||
ASSERT_OK(mkdir_parents(preset, 0755));
|
||||
ASSERT_OK(write_string_file(preset, "enable scoped.service\n", WRITE_STRING_FILE_CREATE));
|
||||
|
||||
ASSERT_ERROR(unit_file_preset(RUNTIME_SCOPE_GLOBAL, 0, root, STRV_MAKE("scoped.service"),
|
||||
UNIT_FILE_PRESET_FULL, &changes, &n_changes), EUNATCH);
|
||||
ASSERT_EQ(n_changes, 1u);
|
||||
ASSERT_EQ(changes[0].type, -EUNATCH);
|
||||
ASSERT_STREQ(changes[0].path, "target-%U.target");
|
||||
install_changes_free(changes, n_changes);
|
||||
changes = NULL; n_changes = 0;
|
||||
|
||||
link = strjoina(root, USER_CONFIG_UNIT_DIR"/target-0.target.wants/scoped.service");
|
||||
ASSERT_ERROR(is_symlink(link), ENOENT);
|
||||
|
||||
ASSERT_ERROR(unit_file_preset_all(RUNTIME_SCOPE_GLOBAL, 0, root, UNIT_FILE_PRESET_FULL,
|
||||
&changes, &n_changes), EUNATCH);
|
||||
ASSERT_EQ(n_changes, 1u);
|
||||
ASSERT_EQ(changes[0].type, -EUNATCH);
|
||||
ASSERT_STREQ(changes[0].path, "target-%U.target");
|
||||
install_changes_free(changes, n_changes);
|
||||
changes = NULL; n_changes = 0;
|
||||
|
||||
ASSERT_ERROR(is_symlink(link), ENOENT);
|
||||
}
|
||||
|
||||
static void verify_one(
|
||||
const InstallInfo *i,
|
||||
const char *alias,
|
||||
|
||||
Reference in New Issue
Block a user