From: Zbigniew Jędrzejewski-Szmek Date: Fri, 20 Oct 2017 15:58:13 +0000 (+0200) Subject: bootctl: show unique titles X-Git-Tag: v236~174^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=64f05708cf10f4a0f85ae0301e101c67ec87ba7a;p=thirdparty%2Fsystemd.git bootctl: show unique titles --- diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index e632d9bc5d0..6b3bbc28fda 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -461,7 +461,7 @@ static int status_entries(const char *esp_path, sd_id128_t partition) { else { const BootEntry *e = &config.entries[config.default_entry]; - printf(" title: %s\n", strna(e->title)); + printf(" title: %s\n", boot_entry_title(e)); if (e->version) printf(" version: %s\n", e->version); if (e->kernel) @@ -1182,7 +1182,7 @@ static int verb_list(int argc, char *argv[], void *userdata) { printf(" title: %s%s%s%s%s%s\n", ansi_highlight(), - strna(e->title), + boot_entry_title(e), ansi_normal(), ansi_highlight_green(), n == config.default_entry ? " (default)" : "", diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 8394f4fe35d..53b8184915c 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -33,6 +33,7 @@ void boot_entry_free(BootEntry *entry) { free(entry->filename); free(entry->title); + free(entry->show_title); free(entry->version); free(entry->machine_id); free(entry->architecture); @@ -274,6 +275,71 @@ int boot_entries_find(const char *dir, BootEntry **entries, size_t *n_entries) { return 0; } +static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) { + unsigned i, j; + bool non_unique = false; + + for (i = 0; i < n_entries; i++) + arr[i] = false; + + for (i = 0; i < n_entries; i++) + for (j = 0; j < n_entries; j++) + if (i != j && streq(boot_entry_title(entries + i), + boot_entry_title(entries + j))) + non_unique = arr[i] = arr[j] = true; + + return non_unique; +} + +static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) { + char *s; + unsigned i; + int r; + bool arr[n_entries]; + + /* Find _all_ non-unique titles */ + if (!find_nonunique(entries, n_entries, arr)) + return 0; + + /* Add version to non-unique titles */ + for (i = 0; i < n_entries; i++) + if (arr[i] && entries[i].version) { + r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version); + if (r < 0) + return -ENOMEM; + + free_and_replace(entries[i].show_title, s); + } + + if (!find_nonunique(entries, n_entries, arr)) + return 0; + + /* Add machine-id to non-unique titles */ + for (i = 0; i < n_entries; i++) + if (arr[i] && entries[i].machine_id) { + r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id); + if (r < 0) + return -ENOMEM; + + free_and_replace(entries[i].show_title, s); + } + + if (!find_nonunique(entries, n_entries, arr)) + return 0; + + /* Add file name to non-unique titles */ + for (i = 0; i < n_entries; i++) + if (arr[i]) { + r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].filename); + if (r < 0) + return -ENOMEM; + + free_and_replace(entries[i].show_title, s); + } + + return 0; +} + int boot_entries_select_default(const BootConfig *config) { int i; @@ -322,6 +388,10 @@ int boot_entries_load_config(const char *esp_path, BootConfig *config) { if (r < 0) return log_error_errno(r, "Failed to read boot entries from \"%s\": %m", p); + r = boot_entries_uniquify(config->entries, config->n_entries); + if (r < 0) + return log_error_errno(r, "Failed to uniquify boot entries: %m"); + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &config->entry_oneshot); if (r < 0 && r != -ENOENT) return log_error_errno(r, "Failed to read EFI var \"LoaderEntryOneShot\": %m"); diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h index ff2b90cd329..b45fdafd70b 100644 --- a/src/shared/bootspec.h +++ b/src/shared/bootspec.h @@ -25,6 +25,7 @@ typedef struct BootEntry { char *filename; char *title; + char *show_title; char *version; char *machine_id; char *architecture; @@ -56,3 +57,7 @@ int boot_entries_select_default(const BootConfig *config); int boot_loader_read_conf(const char *path, BootConfig *config); void boot_config_free(BootConfig *config); int boot_entries_load_config(const char *esp_path, BootConfig *config); + +static inline const char* boot_entry_title(const BootEntry *entry) { + return entry->show_title ?: entry->title ?: entry->filename; +}