summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-10-08 22:31:56 +0200
committerLennart Poettering <lennart@poettering.net>2015-11-12 17:57:04 +0100
commit0ec0deaa30d0e68430f03fa6f32affa576481d18 (patch)
treeecfd89525b710466dc7785dfc877645bc1f12540 /src/core
parentd073dea0a89c271fc4a769d5b3b2db395aa0239a (diff)
install: follow unit file symlinks in /usr, but not /etc when looking for [Install] data
Some distributions use alias unit files via symlinks in /usr to cover for legacy service names. With this change we'll allow "systemctl enable" on such aliases. Previously, our rule was that symlinks are user configuration that "systemctl enable" + "systemctl disable" creates and removes, while unit files is where the instructions to do so are store. As a result of the rule we'd never read install information through symlinks, since that would mix enablement state with installation instructions. Now, the new rule is that only symlinks inside of /etc are configuration. Unit files, and symlinks in /usr are now valid for installation instructions. This patch is quite a rework of the whole install logic, and makes the following addional changes: - Adds a complete test "test-instal-root" that tests the install logic pretty comprehensively. - Never uses canonicalize_file_name(), because that's incompatible with operation relative to a specific root directory. - unit_file_get_state() is reworked to return a proper error, and returns the state in a call-by-ref parameter. This cleans up confusion between the enum type and errno-like errors. - The new logic puts a limit on how long to follow unit file symlinks: it will do so only for 64 steps at max. - The InstallContext object's fields are renamed to will_process and has_processed (will_install and has_installed) since they are also used for deinstallation and all kinds of other operations. - The root directory is always verified before use. - install.c is reordered to place the exported functions together. - Stricter rules are followed when traversing symlinks: the unit suffix must say identical, and it's not allowed to link between regular units and templated units. - Various modernizations - The "invalid" unit file state has been renamed to "bad", in order to avoid confusion between UNIT_FILE_INVALID and _UNIT_FILE_STATE_INVALID. Given that the state should normally not be seen and is not documented this should not be a problematic change. The new name is now documented however. Fixes #1375, #1718, #1706
Diffstat (limited to 'src/core')
-rw-r--r--src/core/dbus-manager.c6
-rw-r--r--src/core/unit.c16
2 files changed, 15 insertions, 7 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index efc716913b..d3bcc795ae 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1521,9 +1521,9 @@ static int method_get_unit_file_state(sd_bus_message *message, void *userdata, s
scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
- state = unit_file_get_state(scope, NULL, name);
- if (state < 0)
- return state;
+ r = unit_file_get_state(scope, NULL, name, &state);
+ if (r < 0)
+ return r;
return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
}
diff --git a/src/core/unit.c b/src/core/unit.c
index ccdc5191e8..a67b9f282f 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -3148,12 +3148,19 @@ int unit_following_set(Unit *u, Set **s) {
}
UnitFileState unit_get_unit_file_state(Unit *u) {
+ int r;
+
assert(u);
- if (u->unit_file_state < 0 && u->fragment_path)
- u->unit_file_state = unit_file_get_state(
+ if (u->unit_file_state < 0 && u->fragment_path) {
+ r = unit_file_get_state(
u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
- NULL, basename(u->fragment_path));
+ NULL,
+ basename(u->fragment_path),
+ &u->unit_file_state);
+ if (r < 0)
+ u->unit_file_state = UNIT_FILE_BAD;
+ }
return u->unit_file_state;
}
@@ -3164,7 +3171,8 @@ int unit_get_unit_file_preset(Unit *u) {
if (u->unit_file_preset < 0 && u->fragment_path)
u->unit_file_preset = unit_file_query_preset(
u->manager->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER,
- NULL, basename(u->fragment_path));
+ NULL,
+ basename(u->fragment_path));
return u->unit_file_preset;
}