From: Zbigniew Jędrzejewski-Szmek Date: Thu, 5 May 2022 14:22:45 +0000 (+0200) Subject: Move printing of boot entries from bootctl.c to shared/ X-Git-Tag: v251-rc3~39^2~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=432ce537376c43298552b7e5ddd5f6099df3c368;p=thirdparty%2Fsystemd.git Move printing of boot entries from bootctl.c to shared/ I want to use this for fuzzing, but also later to return jsonified list of entries from logind. --- diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index 1f29577f00b..b6bd1dfd65d 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -558,39 +558,6 @@ static int status_variables(void) { return 0; } -static int boot_entry_file_check(const char *root, const char *p) { - _cleanup_free_ char *path = NULL; - - path = path_join(root, p); - if (!path) - return log_oom(); - - return RET_NERRNO(access(path, F_OK)); -} - -static void boot_entry_file_list(const char *field, const char *root, const char *p, int *ret_status) { - int status = boot_entry_file_check(root, p); - - printf("%13s%s ", strempty(field), field ? ":" : " "); - if (status < 0) { - errno = -status; - printf("%s%s%s (%m)\n", ansi_highlight_red(), p, ansi_normal()); - } else - printf("%s\n", p); - - if (*ret_status == 0 && status < 0) - *ret_status = status; -} - -static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = { - [BOOT_ENTRY_CONF] = "Boot Loader Specification Type #1 (.conf)", - [BOOT_ENTRY_UNIFIED] = "Boot Loader Specification Type #2 (.efi)", - [BOOT_ENTRY_LOADER] = "Reported by Boot Loader", - [BOOT_ENTRY_LOADER_AUTO] = "Automatic", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType); - static int boot_config_load_and_select( BootConfig *config, const char *esp_path, @@ -620,104 +587,6 @@ static int boot_config_load_and_select( return boot_config_select_special_entries(config); } -static int boot_entry_show( - const BootEntry *e, - bool show_as_default, - bool show_as_selected, - bool show_reported) { - - int status = 0; - - /* Returns 0 on success, negative on processing error, and positive if something is wrong with the - boot entry itself. */ - - assert(e); - - printf(" type: %s\n", - boot_entry_type_to_string(e->type)); - - printf(" title: %s%s%s", - ansi_highlight(), boot_entry_title(e), ansi_normal()); - - if (show_as_default) - printf(" %s(default)%s", - ansi_highlight_green(), ansi_normal()); - - if (show_as_selected) - printf(" %s(selected)%s", - ansi_highlight_magenta(), ansi_normal()); - - if (show_reported) { - if (e->type == BOOT_ENTRY_LOADER) - printf(" %s(reported/absent)%s", - ansi_highlight_red(), ansi_normal()); - else if (!e->reported_by_loader && e->type != BOOT_ENTRY_LOADER_AUTO) - printf(" %s(not reported/new)%s", - ansi_highlight_green(), ansi_normal()); - } - - putchar('\n'); - - if (e->id) - printf(" id: %s\n", e->id); - if (e->path) { - _cleanup_free_ char *link = NULL; - - /* Let's urlify the link to make it easy to view in an editor, but only if it is a text - * file. Unified images are binary ELFs, and EFI variables are not pure text either. */ - if (e->type == BOOT_ENTRY_CONF) - (void) terminal_urlify_path(e->path, NULL, &link); - - printf(" source: %s\n", link ?: e->path); - } - if (e->sort_key) - printf(" sort-key: %s\n", e->sort_key); - if (e->version) - printf(" version: %s\n", e->version); - if (e->machine_id) - printf(" machine-id: %s\n", e->machine_id); - if (e->architecture) - printf(" architecture: %s\n", e->architecture); - if (e->kernel) - boot_entry_file_list("linux", e->root, e->kernel, &status); - - STRV_FOREACH(s, e->initrd) - boot_entry_file_list(s == e->initrd ? "initrd" : NULL, - e->root, - *s, - &status); - - if (!strv_isempty(e->options)) { - _cleanup_free_ char *t = NULL, *t2 = NULL; - _cleanup_strv_free_ char **ts = NULL; - - t = strv_join(e->options, " "); - if (!t) - return log_oom(); - - ts = strv_split_newlines(t); - if (!ts) - return log_oom(); - - t2 = strv_join(ts, "\n "); - if (!t2) - return log_oom(); - - printf(" options: %s\n", t2); - } - - if (e->device_tree) - boot_entry_file_list("devicetree", e->root, e->device_tree, &status); - - STRV_FOREACH(s, e->device_tree_overlay) - boot_entry_file_list(s == e->device_tree_overlay ? "devicetree-overlay" : NULL, - e->root, - *s, - &status); - - return -status; -} - static int status_entries( const BootConfig *config, const char *esp_path, @@ -752,7 +621,7 @@ static int status_entries( else { printf("Default Boot Loader Entry:\n"); - r = boot_entry_show( + r = show_boot_entry( boot_config_default_entry(config), /* show_as_default= */ false, /* show_as_selected= */ false, @@ -1861,65 +1730,13 @@ static int verb_list(int argc, char *argv[], void *userdata) { if (r < 0) return r; - if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) { - - pager_open(arg_pager_flags); - - for (size_t i = 0; i < config.n_entries; i++) { - _cleanup_free_ char *opts = NULL; - BootEntry *e = config.entries + i; - _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; - - if (!strv_isempty(e->options)) { - opts = strv_join(e->options, " "); - if (!opts) - return log_oom(); - } - - r = json_build(&v, JSON_BUILD_OBJECT( - JSON_BUILD_PAIR_CONDITION(e->id, "id", JSON_BUILD_STRING(e->id)), - JSON_BUILD_PAIR_CONDITION(e->path, "path", JSON_BUILD_STRING(e->path)), - JSON_BUILD_PAIR_CONDITION(e->root, "root", JSON_BUILD_STRING(e->root)), - JSON_BUILD_PAIR_CONDITION(e->title, "title", JSON_BUILD_STRING(e->title)), - JSON_BUILD_PAIR_CONDITION(boot_entry_title(e), "showTitle", JSON_BUILD_STRING(boot_entry_title(e))), - JSON_BUILD_PAIR_CONDITION(e->sort_key, "sortKey", JSON_BUILD_STRING(e->sort_key)), - JSON_BUILD_PAIR_CONDITION(e->version, "version", JSON_BUILD_STRING(e->version)), - JSON_BUILD_PAIR_CONDITION(e->machine_id, "machineId", JSON_BUILD_STRING(e->machine_id)), - JSON_BUILD_PAIR_CONDITION(e->architecture, "architecture", JSON_BUILD_STRING(e->architecture)), - JSON_BUILD_PAIR_CONDITION(opts, "options", JSON_BUILD_STRING(opts)), - JSON_BUILD_PAIR_CONDITION(e->kernel, "linux", JSON_BUILD_STRING(e->kernel)), - JSON_BUILD_PAIR_CONDITION(e->efi, "efi", JSON_BUILD_STRING(e->efi)), - JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->initrd), "initrd", JSON_BUILD_STRV(e->initrd)), - JSON_BUILD_PAIR_CONDITION(e->device_tree, "devicetree", JSON_BUILD_STRING(e->device_tree)), - JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->device_tree_overlay), "devicetreeOverlay", JSON_BUILD_STRV(e->device_tree_overlay)))); - if (r < 0) - return log_oom(); - - json_variant_dump(v, arg_json_format_flags, stdout, NULL); - } - - } else if (config.n_entries == 0) + if (config.n_entries == 0 && FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) { log_info("No boot loader entries found."); - else { - pager_open(arg_pager_flags); - - printf("Boot Loader Entries:\n"); - - for (size_t n = 0; n < config.n_entries; n++) { - r = boot_entry_show( - config.entries + n, - /* show_as_default= */ n == (size_t) config.default_entry, - /* show_as_selected= */ n == (size_t) config.selected_entry, - /* show_discovered= */ true); - if (r < 0) - return r; - - if (n+1 < config.n_entries) - putchar('\n'); - } + return 0; } - return 0; + pager_open(arg_pager_flags); + return show_boot_entries(&config, arg_json_format_flags); } static int install_random_seed(const char *esp) { diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 91cb605fb1c..6647aade042 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -2,23 +2,36 @@ #include -#include "bootspec.h" #include "bootspec-fundamental.h" +#include "bootspec.h" #include "conf-files.h" #include "devnum-util.h" #include "dirent-util.h" #include "efi-loader.h" #include "env-file.h" +#include "errno-util.h" #include "fd-util.h" #include "fileio.h" #include "find-esp.h" #include "path-util.h" #include "pe-header.h" +#include "pretty-print.h" #include "recurse-dir.h" #include "sort-util.h" +#include "string-table.h" #include "strv.h" +#include "terminal-util.h" #include "unaligned.h" +static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = { + [BOOT_ENTRY_CONF] = "Boot Loader Specification Type #1 (.conf)", + [BOOT_ENTRY_UNIFIED] = "Boot Loader Specification Type #2 (.efi)", + [BOOT_ENTRY_LOADER] = "Reported by Boot Loader", + [BOOT_ENTRY_LOADER_AUTO] = "Automatic", +}; + +DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType); + static void boot_entry_free(BootEntry *entry) { assert(entry); @@ -987,6 +1000,16 @@ int boot_config_augment_from_loader( return 0; } +static int boot_entry_file_check(const char *root, const char *p) { + _cleanup_free_ char *path = NULL; + + path = path_join(root, p); + if (!path) + return log_oom(); + + return RET_NERRNO(access(path, F_OK)); +} + BootEntry* boot_config_find_entry(BootConfig *config, const char *id) { assert(config); assert(id); @@ -998,3 +1021,172 @@ BootEntry* boot_config_find_entry(BootConfig *config, const char *id) { return NULL; } + +static void boot_entry_file_list(const char *field, const char *root, const char *p, int *ret_status) { + int status = boot_entry_file_check(root, p); + + printf("%13s%s ", strempty(field), field ? ":" : " "); + if (status < 0) { + errno = -status; + printf("%s%s%s (%m)\n", ansi_highlight_red(), p, ansi_normal()); + } else + printf("%s\n", p); + + if (*ret_status == 0 && status < 0) + *ret_status = status; +} + +int show_boot_entry( + const BootEntry *e, + bool show_as_default, + bool show_as_selected, + bool show_reported) { + + int status = 0; + + /* Returns 0 on success, negative on processing error, and positive if something is wrong with the + boot entry itself. */ + + assert(e); + + printf(" type: %s\n", + boot_entry_type_to_string(e->type)); + + printf(" title: %s%s%s", + ansi_highlight(), boot_entry_title(e), ansi_normal()); + + if (show_as_default) + printf(" %s(default)%s", + ansi_highlight_green(), ansi_normal()); + + if (show_as_selected) + printf(" %s(selected)%s", + ansi_highlight_magenta(), ansi_normal()); + + if (show_reported) { + if (e->type == BOOT_ENTRY_LOADER) + printf(" %s(reported/absent)%s", + ansi_highlight_red(), ansi_normal()); + else if (!e->reported_by_loader && e->type != BOOT_ENTRY_LOADER_AUTO) + printf(" %s(not reported/new)%s", + ansi_highlight_green(), ansi_normal()); + } + + putchar('\n'); + + if (e->id) + printf(" id: %s\n", e->id); + if (e->path) { + _cleanup_free_ char *link = NULL; + + /* Let's urlify the link to make it easy to view in an editor, but only if it is a text + * file. Unified images are binary ELFs, and EFI variables are not pure text either. */ + if (e->type == BOOT_ENTRY_CONF) + (void) terminal_urlify_path(e->path, NULL, &link); + + printf(" source: %s\n", link ?: e->path); + } + if (e->sort_key) + printf(" sort-key: %s\n", e->sort_key); + if (e->version) + printf(" version: %s\n", e->version); + if (e->machine_id) + printf(" machine-id: %s\n", e->machine_id); + if (e->architecture) + printf(" architecture: %s\n", e->architecture); + if (e->kernel) + boot_entry_file_list("linux", e->root, e->kernel, &status); + + STRV_FOREACH(s, e->initrd) + boot_entry_file_list(s == e->initrd ? "initrd" : NULL, + e->root, + *s, + &status); + + if (!strv_isempty(e->options)) { + _cleanup_free_ char *t = NULL, *t2 = NULL; + _cleanup_strv_free_ char **ts = NULL; + + t = strv_join(e->options, " "); + if (!t) + return log_oom(); + + ts = strv_split_newlines(t); + if (!ts) + return log_oom(); + + t2 = strv_join(ts, "\n "); + if (!t2) + return log_oom(); + + printf(" options: %s\n", t2); + } + + if (e->device_tree) + boot_entry_file_list("devicetree", e->root, e->device_tree, &status); + + STRV_FOREACH(s, e->device_tree_overlay) + boot_entry_file_list(s == e->device_tree_overlay ? "devicetree-overlay" : NULL, + e->root, + *s, + &status); + + return -status; +} + +int show_boot_entries(const BootConfig *config, JsonFormatFlags json_format) { + int r; + + if (!FLAGS_SET(json_format, JSON_FORMAT_OFF)) { + for (size_t i = 0; i < config->n_entries; i++) { + _cleanup_free_ char *opts = NULL; + const BootEntry *e = config->entries + i; + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + + if (!strv_isempty(e->options)) { + opts = strv_join(e->options, " "); + if (!opts) + return log_oom(); + } + + r = json_build(&v, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR_CONDITION(e->id, "id", JSON_BUILD_STRING(e->id)), + JSON_BUILD_PAIR_CONDITION(e->path, "path", JSON_BUILD_STRING(e->path)), + JSON_BUILD_PAIR_CONDITION(e->root, "root", JSON_BUILD_STRING(e->root)), + JSON_BUILD_PAIR_CONDITION(e->title, "title", JSON_BUILD_STRING(e->title)), + JSON_BUILD_PAIR_CONDITION(boot_entry_title(e), "showTitle", JSON_BUILD_STRING(boot_entry_title(e))), + JSON_BUILD_PAIR_CONDITION(e->sort_key, "sortKey", JSON_BUILD_STRING(e->sort_key)), + JSON_BUILD_PAIR_CONDITION(e->version, "version", JSON_BUILD_STRING(e->version)), + JSON_BUILD_PAIR_CONDITION(e->machine_id, "machineId", JSON_BUILD_STRING(e->machine_id)), + JSON_BUILD_PAIR_CONDITION(e->architecture, "architecture", JSON_BUILD_STRING(e->architecture)), + JSON_BUILD_PAIR_CONDITION(opts, "options", JSON_BUILD_STRING(opts)), + JSON_BUILD_PAIR_CONDITION(e->kernel, "linux", JSON_BUILD_STRING(e->kernel)), + JSON_BUILD_PAIR_CONDITION(e->efi, "efi", JSON_BUILD_STRING(e->efi)), + JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->initrd), "initrd", JSON_BUILD_STRV(e->initrd)), + JSON_BUILD_PAIR_CONDITION(e->device_tree, "devicetree", JSON_BUILD_STRING(e->device_tree)), + JSON_BUILD_PAIR_CONDITION(!strv_isempty(e->device_tree_overlay), "devicetreeOverlay", JSON_BUILD_STRV(e->device_tree_overlay)))); + if (r < 0) + return log_oom(); + + json_variant_dump(v, json_format, stdout, NULL); + } + + } else { + printf("Boot Loader Entries:\n"); + + for (size_t n = 0; n < config->n_entries; n++) { + r = show_boot_entry( + config->entries + n, + /* show_as_default= */ n == (size_t) config->default_entry, + /* show_as_selected= */ n == (size_t) config->selected_entry, + /* show_discovered= */ true); + if (r < 0) + return r; + + if (n+1 < config->n_entries) + putchar('\n'); + } + } + + return 0; +} diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h index 56e06f6be9a..f235830c3c0 100644 --- a/src/shared/bootspec.h +++ b/src/shared/bootspec.h @@ -7,6 +7,7 @@ #include #include +#include "json.h" #include "set.h" #include "string-util.h" @@ -69,6 +70,8 @@ typedef struct BootConfig { .selected_entry = -1, \ } +const char* boot_entry_type_to_string(BootEntryType); + BootEntry* boot_config_find_entry(BootConfig *config, const char *id); static inline const BootEntry* boot_config_default_entry(const BootConfig *config) { @@ -94,3 +97,12 @@ static inline const char* boot_entry_title(const BootEntry *entry) { return ASSERT_PTR(entry->show_title ?: entry->title ?: entry->id); } + +int show_boot_entry( + const BootEntry *e, + bool show_as_default, + bool show_as_selected, + bool show_reported); +int show_boot_entries( + const BootConfig *config, + JsonFormatFlags json_format);