1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-27 01:55:22 +03:00

bootctl: add --install-source=auto|image|host

When using --root=/--image= the binaries to install/update will be
picked from the directory/image. Add an option to let the caller
choose.
By default (auto) the image is tried first, and if nothing is found
then the host. The other options allow to strictly try the image
or host and ignore the other.
This commit is contained in:
Luca Boccassi 2022-06-13 00:21:41 +01:00
parent 80a2381d5c
commit 02d06ba180
4 changed files with 53 additions and 6 deletions

View File

@ -258,6 +258,16 @@
switch of the same name.</para></listitem> switch of the same name.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--install-source=</option></term>
<listitem><para>When installing binaries with <option>--root=</option> or
<option>--image=</option>, selects where to source them from. Takes one of <literal>auto</literal>
(the default), <literal>image</literal> or <literal>host</literal>. With <literal>auto</literal>
binaries will be picked from the specified directory or image, and if not found they will be picked
from the host. With <literal>image</literal> or <literal>host</literal> no fallback search will be
performed if the binaries are not found in the selected source.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-p</option></term> <term><option>-p</option></term>
<term><option>--print-esp-path</option></term> <term><option>--print-esp-path</option></term>

View File

@ -32,7 +32,7 @@ _bootctl() {
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local -A OPTS=( local -A OPTS=(
[STANDALONE]='-h --help -p --print-esp-path -x --print-boot-path --version --no-variables --no-pager --graceful' [STANDALONE]='-h --help -p --print-esp-path -x --print-boot-path --version --no-variables --no-pager --graceful'
[ARG]='--esp-path --boot-path --make-machine-id-directory --root --image' [ARG]='--esp-path --boot-path --make-machine-id-directory --root --image --install-source'
) )
if __contains_word "$prev" ${OPTS[ARG]}; then if __contains_word "$prev" ${OPTS[ARG]}; then
@ -52,6 +52,9 @@ _bootctl() {
compopt -o nospace compopt -o nospace
comps=$( compgen -A file -- "$cur" ) comps=$( compgen -A file -- "$cur" )
;; ;;
--install-source)
comps="image host auto"
;;
esac esac
COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0 return 0

View File

@ -75,4 +75,5 @@ _arguments \
'--graceful[Do not fail when locating ESP or writing fails]' \ '--graceful[Do not fail when locating ESP or writing fails]' \
'--root=[Operate under the specified directory]:PATH' \ '--root=[Operate under the specified directory]:PATH' \
'--image=[Operate on the specified image]:PATH' \ '--image=[Operate on the specified image]:PATH' \
'--install-source[Where to pick files when using --root=/--image=]:options:(image host auto)' \
'*::bootctl command:_bootctl_commands' '*::bootctl command:_bootctl_commands'

View File

@ -80,6 +80,11 @@ static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
static bool arg_arch_all = false; static bool arg_arch_all = false;
static char *arg_root = NULL; static char *arg_root = NULL;
static char *arg_image = NULL; static char *arg_image = NULL;
static enum {
ARG_INSTALL_SOURCE_IMAGE,
ARG_INSTALL_SOURCE_HOST,
ARG_INSTALL_SOURCE_AUTO,
} arg_install_source = ARG_INSTALL_SOURCE_AUTO;
STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep); STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep); STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
@ -843,6 +848,7 @@ static int create_subdirs(const char *root, const char * const *subdirs) {
} }
static int copy_one_file(const char *esp_path, const char *name, bool force) { static int copy_one_file(const char *esp_path, const char *name, bool force) {
char *root = IN_SET(arg_install_source, ARG_INSTALL_SOURCE_AUTO, ARG_INSTALL_SOURCE_IMAGE) ? arg_root : NULL;
_cleanup_free_ char *source_path = NULL, *dest_path = NULL, *p = NULL, *q = NULL; _cleanup_free_ char *source_path = NULL, *dest_path = NULL, *p = NULL, *q = NULL;
const char *e; const char *e;
char *dest_name, *s; char *dest_name, *s;
@ -857,13 +863,16 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) {
if (!p) if (!p)
return log_oom(); return log_oom();
r = chase_symlinks(p, arg_root, CHASE_PREFIX_ROOT, &source_path, NULL); r = chase_symlinks(p, root, CHASE_PREFIX_ROOT, &source_path, NULL);
/* 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_symlinks(p, NULL, CHASE_PREFIX_ROOT, &source_path, NULL);
if (r < 0) if (r < 0)
return log_error_errno(r, return log_error_errno(r,
"Failed to resolve path %s%s%s: %m", "Failed to resolve path %s%s%s: %m",
p, p,
arg_root ? " under directory " : "", root ? " under directory " : "",
arg_root ? arg_root : ""); root ?: "");
q = path_join("/EFI/systemd/", dest_name); q = path_join("/EFI/systemd/", dest_name);
if (!q) if (!q)
@ -899,13 +908,17 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) {
} }
static int install_binaries(const char *esp_path, const char *arch, bool force) { static int install_binaries(const char *esp_path, const char *arch, bool force) {
char *root = IN_SET(arg_install_source, ARG_INSTALL_SOURCE_AUTO, ARG_INSTALL_SOURCE_IMAGE) ? arg_root : NULL;
_cleanup_closedir_ DIR *d = NULL; _cleanup_closedir_ DIR *d = NULL;
_cleanup_free_ char *path = NULL; _cleanup_free_ char *path = NULL;
int r; int r;
r = chase_symlinks_and_opendir(BOOTLIBDIR, arg_root, CHASE_PREFIX_ROOT, &path, &d); r = chase_symlinks_and_opendir(BOOTLIBDIR, root, CHASE_PREFIX_ROOT, &path, &d);
/* 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_symlinks_and_opendir(BOOTLIBDIR, NULL, CHASE_PREFIX_ROOT, &path, &d);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to open boot loader directory %s: %m", BOOTLIBDIR); return log_error_errno(r, "Failed to open boot loader directory %s%s: %m", root ?: "", BOOTLIBDIR);
const char *suffix = strjoina(arch, ".efi"); const char *suffix = strjoina(arch, ".efi");
const char *suffix_signed = strjoina(arch, ".efi.signed"); const char *suffix_signed = strjoina(arch, ".efi.signed");
@ -1394,6 +1407,8 @@ static int help(int argc, char *argv[], void *userdata) {
" --boot-path=PATH Path to the $BOOT partition\n" " --boot-path=PATH Path to the $BOOT partition\n"
" --root=PATH Operate on an alternate filesystem root\n" " --root=PATH Operate on an alternate filesystem root\n"
" --image=PATH Operate on disk image as filesystem root\n" " --image=PATH Operate on disk image as filesystem root\n"
" --install-source=auto|image|host\n"
" Where to pick files when using --root=/--image=\n"
" -p --print-esp-path Print path to the EFI System Partition\n" " -p --print-esp-path Print path to the EFI System Partition\n"
" -x --print-boot-path Print path to the $BOOT partition\n" " -x --print-boot-path Print path to the $BOOT partition\n"
" --no-variables Don't touch EFI variables\n" " --no-variables Don't touch EFI variables\n"
@ -1426,6 +1441,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_BOOT_PATH, ARG_BOOT_PATH,
ARG_ROOT, ARG_ROOT,
ARG_IMAGE, ARG_IMAGE,
ARG_INSTALL_SOURCE,
ARG_VERSION, ARG_VERSION,
ARG_NO_VARIABLES, ARG_NO_VARIABLES,
ARG_NO_PAGER, ARG_NO_PAGER,
@ -1444,6 +1460,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "boot-path", required_argument, NULL, ARG_BOOT_PATH }, { "boot-path", required_argument, NULL, ARG_BOOT_PATH },
{ "root", required_argument, NULL, ARG_ROOT }, { "root", required_argument, NULL, ARG_ROOT },
{ "image", required_argument, NULL, ARG_IMAGE }, { "image", required_argument, NULL, ARG_IMAGE },
{ "install-source", required_argument, NULL, ARG_INSTALL_SOURCE },
{ "print-esp-path", no_argument, NULL, 'p' }, { "print-esp-path", no_argument, NULL, 'p' },
{ "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */ { "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */
{ "print-boot-path", no_argument, NULL, 'x' }, { "print-boot-path", no_argument, NULL, 'x' },
@ -1499,6 +1516,19 @@ static int parse_argv(int argc, char *argv[]) {
return r; return r;
break; break;
case ARG_INSTALL_SOURCE:
if (streq(optarg, "auto"))
arg_install_source = ARG_INSTALL_SOURCE_AUTO;
else if (streq(optarg, "image"))
arg_install_source = ARG_INSTALL_SOURCE_IMAGE;
else if (streq(optarg, "host"))
arg_install_source = ARG_INSTALL_SOURCE_HOST;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Unexpected parameter for --install-source=: %s", optarg);
break;
case 'p': case 'p':
if (arg_print_dollar_boot_path) if (arg_print_dollar_boot_path)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
@ -1592,6 +1622,9 @@ static int parse_argv(int argc, char *argv[]) {
if (arg_root && arg_image) if (arg_root && arg_image)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported."); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
if (arg_install_source != ARG_INSTALL_SOURCE_AUTO && !arg_root && !arg_image)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--install-from-host is only supported with --root= or --image=.");
return 1; return 1;
} }