diff options
author | Lennart Poettering <lennart@poettering.net> | 2015-10-08 22:31:56 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2015-11-12 17:57:04 +0100 |
commit | 0ec0deaa30d0e68430f03fa6f32affa576481d18 (patch) | |
tree | ecfd89525b710466dc7785dfc877645bc1f12540 /src/shared/install.h | |
parent | d073dea0a89c271fc4a769d5b3b2db395aa0239a (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/shared/install.h')
-rw-r--r-- | src/shared/install.h | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/src/shared/install.h b/src/shared/install.h index 74d9ebab65..b1ab66f0d4 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -25,13 +25,15 @@ typedef enum UnitFileScope UnitFileScope; typedef enum UnitFileState UnitFileState; typedef enum UnitFilePresetMode UnitFilePresetMode; typedef enum UnitFileChangeType UnitFileChangeType; +typedef enum UnitFileType UnitFileType; typedef struct UnitFileChange UnitFileChange; typedef struct UnitFileList UnitFileList; typedef struct UnitFileInstallInfo UnitFileInstallInfo; #include "hashmap.h" -#include "unit-name.h" #include "path-lookup.h" +#include "strv.h" +#include "unit-name.h" enum UnitFileScope { UNIT_FILE_SYSTEM, @@ -51,7 +53,7 @@ enum UnitFileState { UNIT_FILE_STATIC, UNIT_FILE_DISABLED, UNIT_FILE_INDIRECT, - UNIT_FILE_INVALID, + UNIT_FILE_BAD, _UNIT_FILE_STATE_MAX, _UNIT_FILE_STATE_INVALID = -1 }; @@ -82,6 +84,14 @@ struct UnitFileList { UnitFileState state; }; +enum UnitFileType { + UNIT_FILE_TYPE_REGULAR, + UNIT_FILE_TYPE_SYMLINK, + UNIT_FILE_TYPE_MASKED, + _UNIT_FILE_TYPE_MAX, + _UNIT_FILE_TYPE_INVALID = -1, +}; + struct UnitFileInstallInfo { char *name; char *path; @@ -93,8 +103,26 @@ struct UnitFileInstallInfo { char **also; char *default_instance; + + UnitFileType type; + + char *symlink_target; }; +static inline bool UNIT_FILE_INSTALL_INFO_HAS_RULES(UnitFileInstallInfo *i) { + assert(i); + + return !strv_isempty(i->aliases) || + !strv_isempty(i->wanted_by) || + !strv_isempty(i->required_by); +} + +static inline bool UNIT_FILE_INSTALL_INFO_HAS_ALSO(UnitFileInstallInfo *i) { + assert(i); + + return !strv_isempty(i->also); +} + int unit_file_enable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_disable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes); int unit_file_reenable(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes); @@ -105,14 +133,14 @@ int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char **files, UnitFileChange **changes, unsigned *n_changes); int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, bool force, UnitFileChange **changes, unsigned *n_changes); int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name); -int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes); +int unit_file_add_dependency(UnitFileScope scope, bool runtime, const char *root_dir, char **files, const char *target, UnitDependency dep, bool force, UnitFileChange **changes, unsigned *n_changes); -UnitFileState unit_file_lookup_state(UnitFileScope scope, const char *root_dir,const LookupPaths *paths, const char *name); -UnitFileState unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename); +int unit_file_lookup_state(UnitFileScope scope, const char *root_dir,const LookupPaths *paths, const char *name, UnitFileState *ret); +int unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename, UnitFileState *ret); int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h); +Hashmap* unit_file_list_free(Hashmap *h); -void unit_file_list_free(Hashmap *h); int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source); void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes); |