]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootctl: show unique titles
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 20 Oct 2017 15:58:13 +0000 (17:58 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 7 Nov 2017 14:14:23 +0000 (15:14 +0100)
src/boot/bootctl.c
src/shared/bootspec.c
src/shared/bootspec.h

index e632d9bc5d06995527c9be10059fef0cb0b3da42..6b3bbc28fdad8406fe4135b72248f24192f1fe56 100644 (file)
@@ -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)" : "",
index 8394f4fe35dc7ecedb7d219ff4a45d5dc8eb9e1e..53b8184915c093bfe2807cac0b8620cebc4c58f5 100644 (file)
@@ -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");
index ff2b90cd3296ddaf554656b8661f1e71ac17f902..b45fdafd70bd038ebbc93920a5ba1789ee563a1b 100644 (file)
@@ -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;
+}