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
This commit is contained in:
+1293
-1029
File diff suppressed because it is too large
Load Diff
+34
-6
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user