Merge pull request #22519 from poettering/boot-order-title-revert

sd-boot: rework boot entry sorting
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2022-03-18 19:04:48 +01:00
committed by GitHub
12 changed files with 281 additions and 80 deletions
+73 -32
View File
@@ -27,6 +27,7 @@ static void boot_entry_free(BootEntry *entry) {
free(entry->root);
free(entry->title);
free(entry->show_title);
free(entry->sort_key);
free(entry->version);
free(entry->machine_id);
free(entry->architecture);
@@ -113,6 +114,8 @@ static int boot_entry_load(
if (streq(field, "title"))
r = free_and_strdup(&tmp.title, p);
else if (streq(field, "sort-key"))
r = free_and_strdup(&tmp.sort_key, p);
else if (streq(field, "version"))
r = free_and_strdup(&tmp.version, p);
else if (streq(field, "machine-id"))
@@ -245,6 +248,28 @@ static int boot_loader_read_conf(const char *path, BootConfig *config) {
}
static int boot_entry_compare(const BootEntry *a, const BootEntry *b) {
int r;
assert(a);
assert(b);
r = CMP(!a->sort_key, !b->sort_key);
if (r != 0)
return r;
if (a->sort_key && b->sort_key) {
r = strcmp(a->sort_key, b->sort_key);
if (r != 0)
return r;
r = strcmp_ptr(a->machine_id, b->machine_id);
if (r != 0)
return r;
r = -strverscmp_improved(a->version, b->version);
if (r != 0)
return r;
}
return strverscmp_improved(a->id, b->id);
}
@@ -293,7 +318,7 @@ static int boot_entry_load_unified(
_cleanup_(boot_entry_free) BootEntry tmp = {
.type = BOOT_ENTRY_UNIFIED,
};
const char *k, *good_name, *good_version;
const char *k, *good_name, *good_version, *good_sort_key;
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -321,7 +346,7 @@ static int boot_entry_load_unified(
if (r < 0)
return log_error_errno(r, "Failed to parse os-release data from unified kernel image %s: %m", path);
if (!bootspec_pick_name_version(
if (!bootspec_pick_name_version_sort_key(
os_pretty_name,
os_image_id,
os_name,
@@ -331,7 +356,8 @@ static int boot_entry_load_unified(
os_version_id,
os_build_id,
&good_name,
&good_version))
&good_version,
&good_sort_key))
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Missing fields in os-release data from unified kernel image %s, refusing.", path);
r = path_extract_filename(path, &tmp.id);
@@ -369,6 +395,10 @@ static int boot_entry_load_unified(
if (!tmp.title)
return log_oom();
tmp.sort_key = strdup(good_sort_key);
if (!tmp.sort_key)
return log_oom();
tmp.version = strdup(good_version);
if (!tmp.version)
return log_oom();
@@ -616,6 +646,19 @@ static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
return 0;
}
static int boot_config_find(const BootConfig *config, const char *id) {
assert(config);
if (!id)
return -1;
for (size_t i = 0; i < config->n_entries; i++)
if (fnmatch(id, config->entries[i].id, FNM_CASEFOLD) == 0)
return i;
return -1;
}
static int boot_entries_select_default(const BootConfig *config) {
int i;
@@ -627,47 +670,45 @@ static int boot_entries_select_default(const BootConfig *config) {
return -1; /* -1 means "no default" */
}
if (config->entry_oneshot)
for (i = config->n_entries - 1; i >= 0; i--)
if (streq(config->entry_oneshot, config->entries[i].id)) {
log_debug("Found default: id \"%s\" is matched by LoaderEntryOneShot",
config->entries[i].id);
return i;
}
if (config->entry_oneshot) {
i = boot_config_find(config, config->entry_oneshot);
if (i >= 0) {
log_debug("Found default: id \"%s\" is matched by LoaderEntryOneShot",
config->entries[i].id);
return i;
}
}
if (config->entry_default)
for (i = config->n_entries - 1; i >= 0; i--)
if (streq(config->entry_default, config->entries[i].id)) {
log_debug("Found default: id \"%s\" is matched by LoaderEntryDefault",
config->entries[i].id);
return i;
}
if (config->entry_default) {
i = boot_config_find(config, config->entry_default);
if (i >= 0) {
log_debug("Found default: id \"%s\" is matched by LoaderEntryDefault",
config->entries[i].id);
return i;
}
}
if (config->default_pattern)
for (i = config->n_entries - 1; i >= 0; i--)
if (fnmatch(config->default_pattern, config->entries[i].id, FNM_CASEFOLD) == 0) {
log_debug("Found default: id \"%s\" is matched by pattern \"%s\"",
config->entries[i].id, config->default_pattern);
return i;
}
if (config->default_pattern) {
i = boot_config_find(config, config->default_pattern);
if (i >= 0) {
log_debug("Found default: id \"%s\" is matched by pattern \"%s\"",
config->entries[i].id, config->default_pattern);
return i;
}
}
log_debug("Found default: last entry \"%s\"", config->entries[config->n_entries - 1].id);
return config->n_entries - 1;
log_debug("Found default: first entry \"%s\"", config->entries[0].id);
return 0;
}
static int boot_entries_select_selected(const BootConfig *config) {
assert(config);
assert(config->entries || config->n_entries == 0);
if (!config->entry_selected || config->n_entries == 0)
return -1;
for (int i = config->n_entries - 1; i >= 0; i--)
if (streq(config->entry_selected, config->entries[i].id))
return i;
return -1;
return boot_config_find(config, config->entry_selected);
}
static int boot_load_efi_entry_pointers(BootConfig *config) {
+1
View File
@@ -27,6 +27,7 @@ typedef struct BootEntry {
char *root; /* The root path in which the drop-in was found, i.e. to which 'kernel', 'efi' and 'initrd' are relative */
char *title;
char *show_title;
char *sort_key;
char *version;
char *machine_id;
char *architecture;