From: Lennart Poettering Date: Fri, 5 Sep 2025 20:12:48 +0000 (+0200) Subject: kernel-install: rework in preparation for varlink X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=533afe86c3b04a96b8fbb0d1fcb260f01c460fa9;p=thirdparty%2Fsystemd.git kernel-install: rework in preparation for varlink This reworks things a bit, so that the "Context" object can later be allocated for each Varlink call separately. For example we define a more precise CONTEXT_NULL that invalidates truly all fields, so that we can discern "defaults" from "unspecified" later on. Other minor rearrangements too --- diff --git a/src/kernel-install/kernel-install.c b/src/kernel-install/kernel-install.c index b79e830844e..5f081954ec7 100644 --- a/src/kernel-install/kernel-install.c +++ b/src/kernel-install/kernel-install.c @@ -109,7 +109,15 @@ typedef struct Context { char **envp; } Context; -#define CONTEXT_NULL (Context) { .rfd = -EBADF } +#define CONTEXT_NULL \ + (Context) { \ + .rfd = XAT_FDROOT, \ + .action = _ACTION_INVALID, \ + .kernel_image_type = _KERNEL_IMAGE_TYPE_INVALID, \ + .layout = _LAYOUT_INVALID, \ + .entry_type = _BOOT_ENTRY_TYPE_INVALID, \ + .entry_token_type = _BOOT_ENTRY_TOKEN_TYPE_INVALID, \ + } static void context_done(Context *c) { assert(c); @@ -768,9 +776,18 @@ static int context_ensure_layout(Context *c) { if (!srel_path) return log_oom(); - _cleanup_free_ char *srel = NULL; - r = read_one_line_file_at(c->rfd, srel_path, &srel); - if (r >= 0) { + _cleanup_fclose_ FILE *f = NULL; + r = chase_and_fopenat_unlocked(c->rfd, srel_path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_MUST_BE_REGULAR, "re", /* ret_path= */ NULL, &f); + if (r < 0) { + if (r != -ENOENT) + return log_error_errno(r, "Failed to open '%s': %m", srel_path); + } else { + _cleanup_free_ char *srel = NULL; + + r = read_line(f, LONG_LINE_MAX, &srel); + if (r < 0) + return log_error_errno(r, "Failed to read %s: %m", srel_path); + if (streq(srel, "type1")) /* The loader/entries.srel file clearly indicates that the installed boot loader * implements the proper standard upstream boot loader spec for Type #1 entries. @@ -784,17 +801,17 @@ static int context_ensure_layout(Context *c) { log_debug("%s with '%s' found, using layout=%s.", srel_path, srel, layout_to_string(c->layout)); return 0; - } else if (r != -ENOENT) - return log_error_errno(r, "Failed to read %s: %m", srel_path); + } _cleanup_free_ char *entry_token_path = path_join(c->boot_root, c->entry_token); if (!entry_token_path) return log_oom(); - r = is_dir_at(c->rfd, entry_token_path, /* follow= */ false); - if (r < 0 && r != -ENOENT) - return log_error_errno(r, "Failed to check if '%s' is a directory: %m", entry_token_path); - if (r > 0) { + r = chaseat(c->rfd, entry_token_path, CHASE_AT_RESOLVE_IN_ROOT|CHASE_MUST_BE_DIRECTORY, /* ret_path= */ NULL, /* ret_fd= */ NULL); + if (r < 0) { + if (!IN_SET(r, -ENOENT, -ENOTDIR)) + return log_error_errno(r, "Failed to check if '%s' exists and is a directory: %m", entry_token_path); + } else { /* If the metadata in $BOOT_ROOT doesn't tell us anything, then check if the entry token * directory already exists. If so, let's assume it's the standard boot loader spec, too. */ c->layout = LAYOUT_BLS; @@ -1091,6 +1108,26 @@ static bool bypass(void) { return should_bypass("KERNEL_INSTALL"); } +static int kernel_from_version(const char *version, char **ret_kernel) { + _cleanup_free_ char *vmlinuz = NULL; + int r; + + assert(version); + + vmlinuz = path_join("/usr/lib/modules/", version, "/vmlinuz"); + if (!vmlinuz) + return log_oom(); + + r = access_nofollow(vmlinuz, F_OK); + if (r == -ENOENT) + return log_error_errno(r, "Kernel image not installed to '%s', specify kernel kernel image path explicitly.", vmlinuz); + if (r < 0) + return log_error_errno(r, "Failed to determine if kernel image is installed to '%s': %m", vmlinuz); + + *ret_kernel = TAKE_PTR(vmlinuz); + return 0; +} + static int do_add( Context *c, const char *version, @@ -1100,8 +1137,21 @@ static int do_add( int r; assert(c); - assert(version); - assert(kernel); + + struct utsname un; + if (!version) { + assert_se(uname(&un) >= 0); + version = un.release; + } + + _cleanup_free_ char *vmlinuz = NULL; + if (!kernel) { + r = kernel_from_version(version, &vmlinuz); + if (r < 0) + return r; + + kernel = vmlinuz; + } r = context_set_version(c, version); if (r < 0) @@ -1122,33 +1172,10 @@ static int do_add( return context_execute(c); } -static int kernel_from_version(const char *version, char **ret_kernel) { - _cleanup_free_ char *vmlinuz = NULL; - int r; - - assert(version); - - vmlinuz = path_join("/usr/lib/modules/", version, "/vmlinuz"); - if (!vmlinuz) - return log_oom(); - - r = access_nofollow(vmlinuz, F_OK); - if (r == -ENOENT) - return log_error_errno(r, "Kernel image not installed to '%s', requiring manual kernel image path specification.", vmlinuz); - if (r < 0) - return log_error_errno(r, "Failed to determine if kernel image is installed to '%s': %m", vmlinuz); - - *ret_kernel = TAKE_PTR(vmlinuz); - return 0; -} - static int verb_add(int argc, char *argv[], void *userdata) { Context *c = ASSERT_PTR(userdata); - _cleanup_free_ char *vmlinuz = NULL; const char *version, *kernel; char **initrds; - struct utsname un; - int r; assert(argv); @@ -1168,19 +1195,6 @@ static int verb_add(int argc, char *argv[], void *userdata) { (argc > 1 ? empty_or_dash_to_null(argv[1]) : NULL); initrds = strv_skip(argv, 3); - if (!version) { - assert_se(uname(&un) >= 0); - version = un.release; - } - - if (!kernel) { - r = kernel_from_version(version, &vmlinuz); - if (r < 0) - return r; - - kernel = vmlinuz; - } - return do_add(c, version, kernel, initrds); } @@ -1661,6 +1675,11 @@ static int parse_argv(int argc, char *argv[], Context *c) { if (arg_image && arg_root) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported."); + if (c->kernel_image_type < 0) + c->kernel_image_type = KERNEL_IMAGE_TYPE_UNKNOWN; + if (c->entry_token_type < 0) + c->entry_token_type = BOOT_ENTRY_TOKEN_AUTO; + return 1; } @@ -1673,24 +1692,17 @@ static int run(int argc, char* argv[]) { { "list", 1, 1, 0, verb_list }, {} }; - _cleanup_(context_done) Context c = { - .rfd = AT_FDCWD, - .action = _ACTION_INVALID, - .kernel_image_type = KERNEL_IMAGE_TYPE_UNKNOWN, - .layout = _LAYOUT_INVALID, - .entry_type = _BOOT_ENTRY_TYPE_INVALID, - .entry_token_type = BOOT_ENTRY_TOKEN_AUTO, - }; - _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; - _cleanup_(umount_and_freep) char *mounted_dir = NULL; int r; log_setup(); + _cleanup_(context_done) Context c = CONTEXT_NULL; r = parse_argv(argc, argv, &c); if (r <= 0) return r; + _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; + _cleanup_(umount_and_freep) char *mounted_dir = NULL; if (arg_image) { assert(!arg_root);