From 43b736a84bbceabe7cb7588bcc61389e831e6f73 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 28 Jan 2019 17:57:41 +0100 Subject: [PATCH] bootspec: store 'root' field in each bootspec entry we load MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This 'root' field contains the root path of the partition we found the snippet in. The 'kernel', 'initrd', 'efi', … fields are relative to this path. This becomes particularly useful later when we add support for loading snippets from both the ESP and XBOOTLDR, but already simplifies the code for us a bit in systemctl. --- src/shared/bootspec.c | 28 ++++++++++++++++++++-------- src/shared/bootspec.h | 5 +++-- src/systemctl/systemctl.c | 8 ++++---- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 5715c94..c662e89 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -27,6 +27,7 @@ static void boot_entry_free(BootEntry *entry) { free(entry->id); free(entry->path); + free(entry->root); free(entry->title); free(entry->show_title); free(entry->version); @@ -39,13 +40,18 @@ static void boot_entry_free(BootEntry *entry) { free(entry->device_tree); } -static int boot_entry_load(const char *path, BootEntry *entry) { +static int boot_entry_load( + const char *root, + const char *path, + BootEntry *entry) { + _cleanup_(boot_entry_free) BootEntry tmp = {}; _cleanup_fclose_ FILE *f = NULL; unsigned line = 1; char *b, *c; int r; + assert(root); assert(path); assert(entry); @@ -62,6 +68,10 @@ static int boot_entry_load(const char *path, BootEntry *entry) { if (!tmp.path) return log_oom(); + tmp.root = strdup(root); + if (!tmp.root) + return log_oom(); + f = fopen(path, "re"); if (!f) return log_error_errno(errno, "Failed to open \"%s\": %m", path); @@ -215,13 +225,19 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { return str_verscmp(a->id, b->id); } -static int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *ret_n_entries) { +static int boot_entries_find( + const char *root, + const char *dir, + BootEntry **ret_entries, + size_t *ret_n_entries) { + _cleanup_strv_free_ char **files = NULL; char **f; int r; BootEntry *array = NULL; size_t n_allocated = 0, n = 0; + assert(root); assert(dir); assert(ret_entries); assert(ret_n_entries); @@ -234,7 +250,7 @@ static int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *r if (!GREEDY_REALLOC0(array, n_allocated, n + 1)) return log_oom(); - r = boot_entry_load(*f, array + n); + r = boot_entry_load(root, *f, array + n); if (r < 0) continue; @@ -369,7 +385,7 @@ int boot_entries_load_config(const char *esp_path, BootConfig *config) { return r; p = strjoina(esp_path, "/loader/entries"); - r = boot_entries_find(p, &config->entries, &config->n_entries); + r = boot_entries_find(esp_path, p, &config->entries, &config->n_entries); if (r < 0) return r; @@ -799,7 +815,6 @@ found: int find_default_boot_entry( const char *esp_path, - char **esp_where, BootConfig *config, const BootEntry **e) { @@ -824,8 +839,5 @@ int find_default_boot_entry( *e = &config->entries[config->default_entry]; log_debug("Found default boot entry in file \"%s\"", (*e)->path); - if (esp_where) - *esp_where = TAKE_PTR(where); - return 0; } diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h index 8a22fd5..0fac051 100644 --- a/src/shared/bootspec.h +++ b/src/shared/bootspec.h @@ -10,7 +10,8 @@ typedef struct BootEntry { char *id; /* This is the file basename without extension */ - char *path; /* This is the full path to the file */ + 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; char *show_title; char *version; @@ -49,4 +50,4 @@ static inline const char* boot_entry_title(const BootEntry *entry) { int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid); int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid); -int find_default_boot_entry(const char *esp_path, char **esp_where, BootConfig *config, const BootEntry **e); +int find_default_boot_entry(const char *esp_path, BootConfig *config, const BootEntry **e); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 63dae2c..6900f61 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3519,7 +3519,7 @@ static int prepare_firmware_setup(void) { static int load_kexec_kernel(void) { _cleanup_(boot_config_free) BootConfig config = {}; - _cleanup_free_ char *where = NULL, *kernel = NULL, *initrd = NULL, *options = NULL; + _cleanup_free_ char *kernel = NULL, *initrd = NULL, *options = NULL; const BootEntry *e; pid_t pid; int r; @@ -3532,7 +3532,7 @@ static int load_kexec_kernel(void) { if (access(KEXEC, X_OK) < 0) return log_error_errno(errno, KEXEC" is not available: %m"); - r = find_default_boot_entry(arg_esp_path, &where, &config, &e); + r = find_default_boot_entry(arg_esp_path, &config, &e); if (r == -ENOKEY) /* find_default_boot_entry() doesn't warn about this case */ return log_error_errno(r, "Cannot find the ESP partition mount point."); if (r < 0) @@ -3544,9 +3544,9 @@ static int load_kexec_kernel(void) { return -EINVAL; } - kernel = path_join(where, e->kernel); + kernel = path_join(e->root, e->kernel); if (!strv_isempty(e->initrd)) - initrd = path_join(where, *e->initrd); + initrd = path_join(e->root, *e->initrd); options = strv_join(e->options, " "); if (!options) return log_oom(); -- 2.7.4