]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootctl: make sure install verb also honors implied --graceful
authorMike Yuan <me@yhndnzj.com>
Wed, 3 Sep 2025 14:44:32 +0000 (16:44 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 4 Sep 2025 19:45:33 +0000 (04:45 +0900)
Follow-up for bcc73cafdbd9c3947c53e4cff3498f8a73e56d9d

src/bootctl/bootctl-install.c
src/bootctl/bootctl-random-seed.c
src/bootctl/bootctl-set-efivar.c
src/bootctl/bootctl.c
src/bootctl/bootctl.h

index 27ec4cf0fea9a23cf1b5a738a3487195f38e5e67..197c9d5bd631879322940fbf2b68d3c0223f1f18 100644 (file)
@@ -453,7 +453,7 @@ static int install_binaries(const char *esp_path, const char *arch, bool force)
         /* If we had a root directory to try, we didn't find it and we are in auto mode, retry on the host */
         if (r == -ENOENT && root && arg_install_source == ARG_INSTALL_SOURCE_AUTO)
                 r = chase_and_opendir(BOOTLIBDIR, NULL, CHASE_PREFIX_ROOT|CHASE_PROHIBIT_SYMLINKS|CHASE_TRIGGER_AUTOFS, &path, &d);
-        if (r == -ENOENT && arg_graceful) {
+        if (r == -ENOENT && arg_graceful() != ARG_GRACEFUL_NO) {
                 log_debug("Source directory does not exist, ignoring.");
                 return 0;
         }
@@ -481,7 +481,7 @@ static int install_binaries(const char *esp_path, const char *arch, bool force)
                 k = copy_one_file(esp_path, de->d_name, force);
                 /* Don't propagate an error code if no update necessary, installed version already equal or
                  * newer version, or other boot loader in place. */
-                if (arg_graceful && IN_SET(k, -ESTALE, -ESRCH))
+                if (arg_graceful() != ARG_GRACEFUL_NO && IN_SET(k, -ESTALE, -ESRCH))
                         continue;
                 RET_GATHER(r, k);
         }
@@ -961,7 +961,9 @@ int verb_install(int argc, char *argv[], void *userdata) {
         /* Invoked for both "update" and "install" */
 
         install = streq(argv[0], "install");
-        graceful = !install && arg_graceful; /* support graceful mode for updates */
+
+        /* Support graceful mode only for updates, unless forcibly enabled in chroot environments */
+        graceful = arg_graceful() == ARG_GRACEFUL_FORCE || (!install && arg_graceful() != ARG_GRACEFUL_NO);
 
         if (arg_secure_boot_auto_enroll) {
                 if (arg_certificate_source_type == OPENSSL_CERTIFICATE_SOURCE_FILE) {
@@ -1365,7 +1367,7 @@ int verb_is_installed(int argc, char *argv[], void *userdata) {
         int r;
 
         r = acquire_esp(/* unprivileged_mode= */ false,
-                        /* graceful= */ arg_graceful,
+                        /* graceful= */ arg_graceful() != ARG_GRACEFUL_NO,
                         NULL, NULL, NULL, NULL, NULL);
         if (r < 0)
                 return r;
index a9826ca9e6b67cb2cf8f13fdc50e526fb1f2e548..7cd39624c11a1df236d2cf19b0f63c0c6a57a182 100644 (file)
@@ -96,7 +96,7 @@ static int set_system_token(void) {
         WITH_UMASK(0077) {
                 r = efi_set_variable(EFI_LOADER_VARIABLE_STR("LoaderSystemToken"), buffer, sizeof(buffer));
                 if (r < 0) {
-                        if (!arg_graceful)
+                        if (arg_graceful() == ARG_GRACEFUL_NO)
                                 return log_error_errno(r, "Failed to write 'LoaderSystemToken' EFI variable: %m");
 
                         if (r == -EINVAL)
@@ -213,7 +213,7 @@ int verb_random_seed(int argc, char *argv[], void *userdata) {
         r = find_esp_and_warn(arg_root, arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL, NULL);
         if (r == -ENOKEY) {
                 /* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
-                if (!arg_graceful)
+                if (arg_graceful() == ARG_GRACEFUL_NO)
                         return log_error_errno(r, "Unable to find ESP.");
 
                 log_notice("No ESP found, not initializing random seed.");
index c989f73aee45046a06cb36e21ec592fcee23b422..b102d6600ea8b9ea60239fecd221eab421a116d7 100644 (file)
@@ -40,7 +40,7 @@ static int parse_timeout(const char *arg1, char16_t **ret_timeout, size_t *ret_t
 
                 (void) efi_loader_get_features(&loader_features);
                 if (!(loader_features & EFI_LOADER_FEATURE_MENU_DISABLE)) {
-                        if (!arg_graceful)
+                        if (arg_graceful() == ARG_GRACEFUL_NO)
                                 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Loader does not support 'menu-disabled'.");
 
                         log_warning("Loader does not support 'menu-disabled', setting anyway.");
index 2f86e87476ef9f458c3e8e00c042677e43f7e378..192f9ddb603ac62eace5b9a7db0b242301f014bb 100644 (file)
@@ -45,6 +45,8 @@
  * having to deal with a potentially too long string. */
 #define EFI_BOOT_OPTION_DESCRIPTION_MAX ((size_t) 255)
 
+static GracefulMode _arg_graceful = ARG_GRACEFUL_NO;
+
 char *arg_esp_path = NULL;
 char *arg_xbootldr_path = NULL;
 bool arg_print_esp_path = false;
@@ -55,7 +57,6 @@ unsigned arg_print_root_device = 0;
 int arg_touch_variables = -1;
 bool arg_install_random_seed = true;
 PagerFlags arg_pager_flags = 0;
-bool arg_graceful = false;
 bool arg_quiet = false;
 int arg_make_entry_directory = false; /* tri-state: < 0 for automatic logic */
 sd_id128_t arg_machine_id = SD_ID128_NULL;
@@ -245,6 +246,21 @@ bool touch_variables(void) {
         return true;
 }
 
+GracefulMode arg_graceful(void) {
+        static bool chroot_checked = false;
+
+        if (!chroot_checked && running_in_chroot() > 0) {
+                if (_arg_graceful == ARG_GRACEFUL_NO)
+                        log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Running in a chroot, enabling --graceful.");
+
+                _arg_graceful = ARG_GRACEFUL_FORCE;
+        }
+
+        chroot_checked = true;
+
+        return _arg_graceful;
+}
+
 static int help(int argc, char *argv[], void *userdata) {
         _cleanup_free_ char *link = NULL;
         int r;
@@ -519,7 +535,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_GRACEFUL:
-                        arg_graceful = true;
+                        _arg_graceful = ARG_GRACEFUL_YES;
                         break;
 
                 case 'q':
@@ -644,11 +660,6 @@ static int parse_argv(int argc, char *argv[]) {
         if (arg_secure_boot_auto_enroll && !arg_private_key)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Secure boot auto-enrollment requested but no private key provided");
 
-        if (!arg_graceful && running_in_chroot() > 0) {
-                log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Running in a chroot, enabling --graceful.");
-                arg_graceful = true;
-        }
-
         r = sd_varlink_invocation(SD_VARLINK_ALLOW_ACCEPT);
         if (r < 0)
                 return log_error_errno(r, "Failed to check if invoked in Varlink mode: %m");
index 8d064f5de24e4e8a7021d48f346efd65c6364302..7504d5715cfd9fe5dda538aa8f6937ec63c1561b 100644 (file)
@@ -9,6 +9,12 @@ typedef enum InstallSource {
         ARG_INSTALL_SOURCE_AUTO,
 } InstallSource;
 
+typedef enum GracefulMode {
+        ARG_GRACEFUL_NO,
+        ARG_GRACEFUL_YES,
+        ARG_GRACEFUL_FORCE,
+} GracefulMode;
+
 extern char *arg_esp_path;
 extern char *arg_xbootldr_path;
 extern bool arg_print_esp_path;
@@ -17,7 +23,6 @@ extern unsigned arg_print_root_device;
 extern int arg_touch_variables;
 extern bool arg_install_random_seed;
 extern PagerFlags arg_pager_flags;
-extern bool arg_graceful;
 extern bool arg_quiet;
 extern int arg_make_entry_directory; /* tri-state: < 0 for automatic logic */
 extern sd_id128_t arg_machine_id;
@@ -46,6 +51,8 @@ static inline const char* arg_dollar_boot_path(void) {
         return arg_xbootldr_path ?: arg_esp_path;
 }
 
+GracefulMode arg_graceful(void);
+
 int acquire_esp(int unprivileged_mode, bool graceful, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid);
 int acquire_xbootldr(int unprivileged_mode, sd_id128_t *ret_uuid, dev_t *ret_devid);