Merge pull request #15692 from keszybz/preset-cleanup

Make systemctl list-unit-files output more useful
This commit is contained in:
Lennart Poettering
2020-05-06 08:19:37 +02:00
committed by GitHub
11 changed files with 193 additions and 144 deletions
+60 -53
View File
@@ -55,16 +55,11 @@ typedef enum {
PRESET_DISABLE,
} PresetAction;
typedef struct {
struct UnitFilePresetRule {
char *pattern;
PresetAction action;
char **instances;
} PresetRule;
typedef struct {
PresetRule *rules;
size_t n_rules;
} Presets;
};
static bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i) {
assert(i);
@@ -80,7 +75,7 @@ static bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) {
return !strv_isempty(i->also);
}
static void presets_freep(Presets *p) {
void unit_file_presets_freep(UnitFilePresets *p) {
size_t i;
if (!p)
@@ -1231,7 +1226,7 @@ static int unit_file_load(
return -EINVAL;
if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) && !unit_type_may_template(type))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unit type %s cannot be templated.", unit_type_to_string(type));
"%s: unit type %s cannot be templated, ignoring.", path, unit_type_to_string(type));
if (!(flags & SEARCH_LOAD)) {
r = lstat(path, &st);
@@ -2772,6 +2767,12 @@ int unit_file_lookup_state(
break;
case UNIT_FILE_TYPE_REGULAR:
/* Check if the name we were querying is actually an alias */
if (!streq(name, basename(i->path)) && !unit_name_is_valid(i->name, UNIT_NAME_INSTANCE)) {
state = UNIT_FILE_ALIAS;
break;
}
r = path_is_generator(paths, i->path);
if (r < 0)
return r;
@@ -2913,8 +2914,8 @@ static int presets_find_config(UnitFileScope scope, const char *root_dir, char *
return conf_files_list_strv(files, ".preset", root_dir, 0, dirs);
}
static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) {
_cleanup_(presets_freep) Presets ps = {};
static int read_presets(UnitFileScope scope, const char *root_dir, UnitFilePresets *presets) {
_cleanup_(unit_file_presets_freep) UnitFilePresets ps = {};
size_t n_allocated = 0;
_cleanup_strv_free_ char **files = NULL;
char **p;
@@ -2942,7 +2943,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
for (;;) {
_cleanup_free_ char *line = NULL;
PresetRule rule = {};
UnitFilePresetRule rule = {};
const char *parameter;
char *l;
@@ -2972,7 +2973,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
continue;
}
rule = (PresetRule) {
rule = (UnitFilePresetRule) {
.pattern = unit_name,
.action = PRESET_ENABLE,
.instances = instances,
@@ -2987,7 +2988,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
if (!pattern)
return -ENOMEM;
rule = (PresetRule) {
rule = (UnitFilePresetRule) {
.pattern = pattern,
.action = PRESET_DISABLE,
};
@@ -3005,14 +3006,15 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
}
}
ps.initialized = true;
*presets = ps;
ps = (Presets){};
ps = (UnitFilePresets){};
return 0;
}
static int pattern_match_multiple_instances(
const PresetRule rule,
const UnitFilePresetRule rule,
const char *unit_name,
char ***ret) {
@@ -3066,17 +3068,17 @@ static int pattern_match_multiple_instances(
return 0;
}
static int query_presets(const char *name, const Presets presets, char ***instance_name_list) {
static int query_presets(const char *name, const UnitFilePresets *presets, char ***instance_name_list) {
PresetAction action = PRESET_UNKNOWN;
size_t i;
char **s;
if (!unit_name_is_valid(name, UNIT_NAME_ANY))
return -EINVAL;
for (i = 0; i < presets.n_rules; i++)
if (pattern_match_multiple_instances(presets.rules[i], name, instance_name_list) > 0 ||
fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) {
action = presets.rules[i].action;
for (i = 0; i < presets->n_rules; i++)
if (pattern_match_multiple_instances(presets->rules[i], name, instance_name_list) > 0 ||
fnmatch(presets->rules[i].pattern, name, FNM_NOESCAPE) == 0) {
action = presets->rules[i].action;
break;
}
@@ -3099,15 +3101,19 @@ static int query_presets(const char *name, const Presets presets, char ***instan
}
}
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) {
_cleanup_(presets_freep) Presets presets = {};
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name, UnitFilePresets *cached) {
_cleanup_(unit_file_presets_freep) UnitFilePresets tmp = {};
int r;
r = read_presets(scope, root_dir, &presets);
if (r < 0)
return r;
if (!cached)
cached = &tmp;
if (!cached->initialized) {
r = read_presets(scope, root_dir, cached);
if (r < 0)
return r;
}
return query_presets(name, presets, NULL);
return query_presets(name, cached, NULL);
}
static int execute_preset(
@@ -3162,7 +3168,7 @@ static int preset_prepare_one(
InstallContext *minus,
LookupPaths *paths,
const char *name,
Presets presets,
const UnitFilePresets *presets,
UnitFileChange **changes,
size_t *n_changes) {
@@ -3221,7 +3227,7 @@ int unit_file_preset(
_cleanup_(install_context_done) InstallContext plus = {}, minus = {};
_cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(presets_freep) Presets presets = {};
_cleanup_(unit_file_presets_freep) UnitFilePresets presets = {};
const char *config_path;
char **i;
int r;
@@ -3243,7 +3249,7 @@ int unit_file_preset(
return r;
STRV_FOREACH(i, files) {
r = preset_prepare_one(scope, &plus, &minus, &paths, *i, presets, changes, n_changes);
r = preset_prepare_one(scope, &plus, &minus, &paths, *i, &presets, changes, n_changes);
if (r < 0)
return r;
}
@@ -3261,7 +3267,7 @@ int unit_file_preset_all(
_cleanup_(install_context_done) InstallContext plus = {}, minus = {};
_cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(presets_freep) Presets presets = {};
_cleanup_(unit_file_presets_freep) UnitFilePresets presets = {};
const char *config_path = NULL;
char **i;
int r;
@@ -3305,7 +3311,7 @@ int unit_file_preset_all(
continue;
/* we don't pass changes[] in, because we want to handle errors on our own */
r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, presets, NULL, 0);
r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, &presets, NULL, 0);
if (r == -ERFKILL)
r = unit_file_changes_add(changes, n_changes,
UNIT_FILE_IS_MASKED, de->d_name, NULL);
@@ -3344,7 +3350,7 @@ int unit_file_get_list(
char **patterns) {
_cleanup_(lookup_paths_free) LookupPaths paths = {};
char **i;
char **dirname;
int r;
assert(scope >= 0);
@@ -3355,16 +3361,16 @@ int unit_file_get_list(
if (r < 0)
return r;
STRV_FOREACH(i, paths.search_path) {
STRV_FOREACH(dirname, paths.search_path) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
d = opendir(*i);
d = opendir(*dirname);
if (!d) {
if (errno == ENOENT)
continue;
if (IN_SET(errno, ENOTDIR, EACCES)) {
log_debug_errno(errno, "Failed to open \"%s\": %m", *i);
log_debug_errno(errno, "Failed to open \"%s\": %m", *dirname);
continue;
}
@@ -3392,7 +3398,7 @@ int unit_file_get_list(
if (!f)
return -ENOMEM;
f->path = path_make_absolute(de->d_name, *i);
f->path = path_make_absolute(de->d_name, *dirname);
if (!f->path)
return -ENOMEM;
@@ -3416,34 +3422,35 @@ int unit_file_get_list(
}
static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
[UNIT_FILE_ENABLED] = "enabled",
[UNIT_FILE_ENABLED] = "enabled",
[UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime",
[UNIT_FILE_LINKED] = "linked",
[UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
[UNIT_FILE_MASKED] = "masked",
[UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
[UNIT_FILE_STATIC] = "static",
[UNIT_FILE_DISABLED] = "disabled",
[UNIT_FILE_INDIRECT] = "indirect",
[UNIT_FILE_GENERATED] = "generated",
[UNIT_FILE_TRANSIENT] = "transient",
[UNIT_FILE_BAD] = "bad",
[UNIT_FILE_LINKED] = "linked",
[UNIT_FILE_LINKED_RUNTIME] = "linked-runtime",
[UNIT_FILE_ALIAS] = "alias",
[UNIT_FILE_MASKED] = "masked",
[UNIT_FILE_MASKED_RUNTIME] = "masked-runtime",
[UNIT_FILE_STATIC] = "static",
[UNIT_FILE_DISABLED] = "disabled",
[UNIT_FILE_INDIRECT] = "indirect",
[UNIT_FILE_GENERATED] = "generated",
[UNIT_FILE_TRANSIENT] = "transient",
[UNIT_FILE_BAD] = "bad",
};
DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
[UNIT_FILE_SYMLINK] = "symlink",
[UNIT_FILE_UNLINK] = "unlink",
[UNIT_FILE_IS_MASKED] = "masked",
[UNIT_FILE_SYMLINK] = "symlink",
[UNIT_FILE_UNLINK] = "unlink",
[UNIT_FILE_IS_MASKED] = "masked",
[UNIT_FILE_IS_DANGLING] = "dangling",
};
DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = {
[UNIT_FILE_PRESET_FULL] = "full",
[UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
[UNIT_FILE_PRESET_FULL] = "full",
[UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only",
[UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only",
};
+10 -1
View File
@@ -189,7 +189,16 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang
int unit_file_verify_alias(const UnitFileInstallInfo *i, const char *dst, char **ret_dst);
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name);
typedef struct UnitFilePresetRule UnitFilePresetRule;
typedef struct {
UnitFilePresetRule *rules;
size_t n_rules;
bool initialized;
} UnitFilePresets;
void unit_file_presets_freep(UnitFilePresets *p);
int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name, UnitFilePresets *cached);
const char *unit_file_state_to_string(UnitFileState s) _const_;
UnitFileState unit_file_state_from_string(const char *s) _pure_;
+4 -3
View File
@@ -320,7 +320,7 @@ int unit_file_build_name_map(
/* We don't explicitly check for alias loops here. unit_ids_map_get() which
* limits the number of hops should be used to access the map. */
_cleanup_free_ char *target = NULL, *target_abs = NULL;
_cleanup_free_ char *target = NULL;
r = readlinkat_malloc(dirfd(d), de->d_name, &target);
if (r < 0) {
@@ -329,8 +329,9 @@ int unit_file_build_name_map(
continue;
}
if (!path_is_absolute(target)) {
target_abs = path_join(*dir, target);
const bool is_abs = path_is_absolute(target);
if (lp->root_dir || !is_abs) {
char *target_abs = path_join(is_abs ? lp->root_dir : *dir, target);
if (!target_abs)
return log_oom();
+1
View File
@@ -16,6 +16,7 @@ enum UnitFileState {
UNIT_FILE_ENABLED_RUNTIME,
UNIT_FILE_LINKED,
UNIT_FILE_LINKED_RUNTIME,
UNIT_FILE_ALIAS,
UNIT_FILE_MASKED,
UNIT_FILE_MASKED_RUNTIME,
UNIT_FILE_STATIC,
+17 -26
View File
@@ -45,10 +45,19 @@ bool running_in_chroot_or_offline(void) {
return r > 0;
}
const Verb* verbs_find_verb(const char *name, const Verb verbs[]) {
for (size_t i = 0; verbs[i].dispatch; i++)
if (streq_ptr(name, verbs[i].verb) ||
(!name && FLAGS_SET(verbs[i].flags, VERB_DEFAULT)))
return &verbs[i];
/* At the end of the list? */
return NULL;
}
int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
const Verb *verb;
const char *name;
unsigned i;
int left;
assert(verbs);
@@ -62,31 +71,16 @@ int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
optind = 0;
name = argv[0];
for (i = 0;; i++) {
bool found;
/* At the end of the list? */
if (!verbs[i].dispatch) {
if (name)
log_error("Unknown operation %s.", name);
else
log_error("Requires operation parameter.");
return -EINVAL;
}
verb = verbs_find_verb(name, verbs);
if (!verb) {
if (name)
found = streq(name, verbs[i].verb);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unknown command verb %s.", name);
else
found = verbs[i].flags & VERB_DEFAULT;
if (found) {
verb = &verbs[i];
break;
}
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Command verb required.");
}
assert(verb);
if (!name)
left = 1;
@@ -101,10 +95,7 @@ int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
"Too many arguments.");
if ((verb->flags & VERB_ONLINE_ONLY) && running_in_chroot_or_offline()) {
if (name)
log_info("Running in chroot, ignoring request: %s", name);
else
log_info("Running in chroot, ignoring request.");
log_info("Running in chroot, ignoring command '%s'", name ?: verb->verb);
return 0;
}
+3 -2
View File
@@ -6,8 +6,8 @@
#define VERB_ANY ((unsigned) -1)
typedef enum VerbFlags {
VERB_DEFAULT = 1 << 0,
VERB_ONLINE_ONLY = 1 << 1,
VERB_DEFAULT = 1 << 0, /* The verb to run if no verb is specified */
VERB_ONLINE_ONLY = 1 << 1, /* Just do nothing when running in chroot or offline */
} VerbFlags;
typedef struct {
@@ -19,4 +19,5 @@ typedef struct {
bool running_in_chroot_or_offline(void);
const Verb* verbs_find_verb(const char *name, const Verb verbs[]);
int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata);