mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-04 17:47:03 +03:00
boot: Deduplicate old-style loader entries.
In cases where systemd (and thus bootctl) is updated to a version including the earlier unique-ID fix, but the corresponding new version of systemd-boot is not installed to the ESP and run at least once, the bootloader will report old-style entry IDs cached in the LoaderEntries EFI variable, while bootctl will report new-style IDs for the same entries, producing duplicate entries. This commit makes bootctl compute and retain old-style IDs for non-auto entries so that it can properly deduplicate entries even if the cache contains old-style IDs.
This commit is contained in:
parent
ae474efc3f
commit
15b82eecb6
@ -36,6 +36,7 @@ static void boot_entry_free(BootEntry *entry) {
|
||||
assert(entry);
|
||||
|
||||
free(entry->id);
|
||||
free(entry->id_old);
|
||||
free(entry->path);
|
||||
free(entry->root);
|
||||
free(entry->title);
|
||||
@ -74,7 +75,8 @@ static int boot_entry_load(
|
||||
|
||||
b = basename(path);
|
||||
tmp.id = strdup(b);
|
||||
if (!tmp.id)
|
||||
tmp.id_old = strndup(b, c - b);
|
||||
if (!tmp.id || !tmp.id_old)
|
||||
return log_oom();
|
||||
|
||||
if (!efi_loader_entry_name_valid(tmp.id))
|
||||
@ -283,7 +285,7 @@ static int boot_entry_load_unified(
|
||||
const char *cmdline,
|
||||
BootEntry *ret) {
|
||||
|
||||
_cleanup_free_ char *os_pretty_name = NULL;
|
||||
_cleanup_free_ char *os_pretty_name = NULL, *os_id = NULL, *version_id = NULL, *build_id = NULL;
|
||||
_cleanup_(boot_entry_free) BootEntry tmp = {
|
||||
.type = BOOT_ENTRY_UNIFIED,
|
||||
};
|
||||
@ -304,16 +306,21 @@ static int boot_entry_load_unified(
|
||||
if (!f)
|
||||
return log_error_errno(errno, "Failed to open os-release buffer: %m");
|
||||
|
||||
r = parse_env_file(f, "os-release", "PRETTY_NAME", &os_pretty_name);
|
||||
r = parse_env_file(f, "os-release",
|
||||
"PRETTY_NAME", &os_pretty_name,
|
||||
"ID", &os_id,
|
||||
"VERSION_ID", &version_id,
|
||||
"BUILD_ID", &build_id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse os-release data from unified kernel image %s: %m", path);
|
||||
|
||||
if (!os_pretty_name)
|
||||
if (!os_pretty_name || !os_id || !(version_id || build_id))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Missing fields in os-release data from unified kernel image %s, refusing.", path);
|
||||
|
||||
b = basename(path);
|
||||
tmp.id = strdup(b);
|
||||
if (!tmp.id)
|
||||
tmp.id_old = strjoin(os_id, "-", version_id ?: build_id);
|
||||
if (!tmp.id || !tmp.id_old)
|
||||
return log_oom();
|
||||
|
||||
if (!efi_loader_entry_name_valid(tmp.id))
|
||||
|
@ -21,6 +21,7 @@ typedef enum BootEntryType {
|
||||
typedef struct BootEntry {
|
||||
BootEntryType type;
|
||||
char *id; /* This is the file basename without extension */
|
||||
char *id_old; /* Old-style ID, for deduplication purposes. */
|
||||
char *path; /* This is the full path to the drop-in file */
|
||||
char *root; /* The root path in which the drop-in was found, i.e. to which 'kernel', 'efi' and 'initrd' are relative */
|
||||
char *title;
|
||||
@ -54,9 +55,12 @@ typedef struct BootConfig {
|
||||
static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < config->n_entries; j++)
|
||||
if (streq(config->entries[j].id, id))
|
||||
for (j = 0; j < config->n_entries; j++) {
|
||||
const char* entry_id_old = config->entries[j].id_old;
|
||||
if (streq(config->entries[j].id, id) ||
|
||||
(entry_id_old && streq(entry_id_old, id)))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user