mirror of
https://github.com/systemd/systemd.git
synced 2025-01-13 17:18:18 +03:00
bootctl: split-out entry token related definitions into boot-entry.[ch]
No functional change, just preparation for later commits. These can be used in kernel-install later. Note, unlike the our usual coding style, the arguments for boot_entry_token_ensure() and parse_boot_entry_token_type() are referenced, updated, and may freed, hence, always pass initialized values. That's why they are not named as 'ret_xyz'.
This commit is contained in:
parent
600362aa11
commit
9e43296fd2
@ -133,7 +133,7 @@ static int settle_make_entry_directory(void) {
|
||||
bool layout_type1 = use_boot_loader_spec_type1();
|
||||
if (arg_make_entry_directory < 0) { /* Automatic mode */
|
||||
if (layout_type1) {
|
||||
if (arg_entry_token_type == ARG_ENTRY_TOKEN_MACHINE_ID) {
|
||||
if (arg_entry_token_type == BOOT_ENTRY_TOKEN_MACHINE_ID) {
|
||||
r = path_is_temporary_fs("/etc/machine-id");
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Couldn't determine whether /etc/machine-id is on a temporary file system: %m");
|
||||
@ -510,7 +510,7 @@ static int install_entry_token(void) {
|
||||
/* Let's save the used entry token in /etc/kernel/entry-token if we used it to create the entry
|
||||
* directory, or if anything else but the machine ID */
|
||||
|
||||
if (!arg_make_entry_directory && arg_entry_token_type == ARG_ENTRY_TOKEN_MACHINE_ID)
|
||||
if (!arg_make_entry_directory && arg_entry_token_type == BOOT_ENTRY_TOKEN_MACHINE_ID)
|
||||
return 0;
|
||||
|
||||
p = path_join(arg_root, etc_kernel(), "entry-token");
|
||||
|
@ -5,11 +5,8 @@
|
||||
#include "bootctl.h"
|
||||
#include "bootctl-util.h"
|
||||
#include "fileio.h"
|
||||
#include "os-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "sync-util.h"
|
||||
#include "utf8.h"
|
||||
|
||||
int sync_everything(void) {
|
||||
int ret = 0, k;
|
||||
@ -118,93 +115,14 @@ finish:
|
||||
int settle_entry_token(void) {
|
||||
int r;
|
||||
|
||||
switch (arg_entry_token_type) {
|
||||
|
||||
case ARG_ENTRY_TOKEN_AUTO: {
|
||||
_cleanup_free_ char *buf = NULL, *p = NULL;
|
||||
p = path_join(arg_root, etc_kernel(), "entry-token");
|
||||
if (!p)
|
||||
return log_oom();
|
||||
r = read_one_line_file(p, &buf);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to read %s: %m", p);
|
||||
|
||||
if (!isempty(buf)) {
|
||||
free_and_replace(arg_entry_token, buf);
|
||||
arg_entry_token_type = ARG_ENTRY_TOKEN_LITERAL;
|
||||
} else if (sd_id128_is_null(arg_machine_id)) {
|
||||
_cleanup_free_ char *id = NULL, *image_id = NULL;
|
||||
|
||||
r = parse_os_release(arg_root,
|
||||
"IMAGE_ID", &image_id,
|
||||
"ID", &id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load /etc/os-release: %m");
|
||||
|
||||
if (!isempty(image_id)) {
|
||||
free_and_replace(arg_entry_token, image_id);
|
||||
arg_entry_token_type = ARG_ENTRY_TOKEN_OS_IMAGE_ID;
|
||||
} else if (!isempty(id)) {
|
||||
free_and_replace(arg_entry_token, id);
|
||||
arg_entry_token_type = ARG_ENTRY_TOKEN_OS_ID;
|
||||
} else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No machine ID set, and /etc/os-release carries no ID=/IMAGE_ID= fields.");
|
||||
} else {
|
||||
r = free_and_strdup_warn(&arg_entry_token, SD_ID128_TO_STRING(arg_machine_id));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
arg_entry_token_type = ARG_ENTRY_TOKEN_MACHINE_ID;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_ENTRY_TOKEN_MACHINE_ID:
|
||||
if (sd_id128_is_null(arg_machine_id))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No machine ID set.");
|
||||
|
||||
r = free_and_strdup_warn(&arg_entry_token, SD_ID128_TO_STRING(arg_machine_id));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case ARG_ENTRY_TOKEN_OS_IMAGE_ID: {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
|
||||
r = parse_os_release(arg_root, "IMAGE_ID", &buf);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load /etc/os-release: %m");
|
||||
|
||||
if (isempty(buf))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "IMAGE_ID= field not set in /etc/os-release.");
|
||||
|
||||
free_and_replace(arg_entry_token, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_ENTRY_TOKEN_OS_ID: {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
|
||||
r = parse_os_release(arg_root, "ID", &buf);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load /etc/os-release: %m");
|
||||
|
||||
if (isempty(buf))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "ID= field not set in /etc/os-release.");
|
||||
|
||||
free_and_replace(arg_entry_token, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_ENTRY_TOKEN_LITERAL:
|
||||
assert(!isempty(arg_entry_token)); /* already filled in by command line parser */
|
||||
break;
|
||||
}
|
||||
|
||||
if (isempty(arg_entry_token) || !(utf8_is_valid(arg_entry_token) && string_is_safe(arg_entry_token)))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Selected entry token not valid: %s", arg_entry_token);
|
||||
r = boot_entry_token_ensure(
|
||||
arg_root,
|
||||
etc_kernel(),
|
||||
arg_machine_id,
|
||||
&arg_entry_token_type,
|
||||
&arg_entry_token);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_debug("Using entry token: %s", arg_entry_token);
|
||||
return 0;
|
||||
|
@ -43,7 +43,7 @@ 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;
|
||||
char *arg_install_layout = NULL;
|
||||
EntryTokenType arg_entry_token_type = ARG_ENTRY_TOKEN_AUTO;
|
||||
BootEntryTokenType arg_entry_token_type = BOOT_ENTRY_TOKEN_AUTO;
|
||||
char *arg_entry_token = NULL;
|
||||
JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
|
||||
bool arg_arch_all = false;
|
||||
@ -328,30 +328,11 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_quiet = true;
|
||||
break;
|
||||
|
||||
case ARG_ENTRY_TOKEN: {
|
||||
const char *e;
|
||||
|
||||
if (streq(optarg, "machine-id")) {
|
||||
arg_entry_token_type = ARG_ENTRY_TOKEN_MACHINE_ID;
|
||||
arg_entry_token = mfree(arg_entry_token);
|
||||
} else if (streq(optarg, "os-image-id")) {
|
||||
arg_entry_token_type = ARG_ENTRY_TOKEN_OS_IMAGE_ID;
|
||||
arg_entry_token = mfree(arg_entry_token);
|
||||
} else if (streq(optarg, "os-id")) {
|
||||
arg_entry_token_type = ARG_ENTRY_TOKEN_OS_ID;
|
||||
arg_entry_token = mfree(arg_entry_token);
|
||||
} else if ((e = startswith(optarg, "literal:"))) {
|
||||
arg_entry_token_type = ARG_ENTRY_TOKEN_LITERAL;
|
||||
|
||||
r = free_and_strdup_warn(&arg_entry_token, e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Unexpected parameter for --entry-token=: %s", optarg);
|
||||
|
||||
case ARG_ENTRY_TOKEN:
|
||||
r = parse_boot_entry_token_type(optarg, &arg_entry_token_type, &arg_entry_token);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_MAKE_ENTRY_DIRECTORY:
|
||||
if (streq(optarg, "auto")) /* retained for backwards compatibility */
|
||||
|
@ -3,17 +3,10 @@
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "boot-entry.h"
|
||||
#include "json.h"
|
||||
#include "pager.h"
|
||||
|
||||
typedef enum EntryTokenType {
|
||||
ARG_ENTRY_TOKEN_MACHINE_ID,
|
||||
ARG_ENTRY_TOKEN_OS_IMAGE_ID,
|
||||
ARG_ENTRY_TOKEN_OS_ID,
|
||||
ARG_ENTRY_TOKEN_LITERAL,
|
||||
ARG_ENTRY_TOKEN_AUTO,
|
||||
} EntryTokenType;
|
||||
|
||||
typedef enum InstallSource {
|
||||
ARG_INSTALL_SOURCE_IMAGE,
|
||||
ARG_INSTALL_SOURCE_HOST,
|
||||
@ -32,7 +25,7 @@ extern bool arg_quiet;
|
||||
extern int arg_make_entry_directory; /* tri-state: < 0 for automatic logic */
|
||||
extern sd_id128_t arg_machine_id;
|
||||
extern char *arg_install_layout;
|
||||
extern EntryTokenType arg_entry_token_type;
|
||||
extern BootEntryTokenType arg_entry_token_type;
|
||||
extern char *arg_entry_token;
|
||||
extern JsonFormatFlags arg_json_format_flags;
|
||||
extern bool arg_arch_all;
|
||||
|
224
src/shared/boot-entry.c
Normal file
224
src/shared/boot-entry.c
Normal file
@ -0,0 +1,224 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "boot-entry.h"
|
||||
#include "fileio.h"
|
||||
#include "id128-util.h"
|
||||
#include "os-util.h"
|
||||
#include "path-util.h"
|
||||
#include "string-util.h"
|
||||
#include "utf8.h"
|
||||
|
||||
bool boot_entry_token_valid(const char *p) {
|
||||
return utf8_is_valid(p) && string_is_safe(p) && filename_is_valid(p);
|
||||
}
|
||||
|
||||
static int entry_token_load(const char *root, const char *etc_kernel, BootEntryTokenType *type, char **token) {
|
||||
_cleanup_free_ char *buf = NULL, *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(type);
|
||||
assert(*type == BOOT_ENTRY_TOKEN_AUTO);
|
||||
assert(token);
|
||||
|
||||
if (!etc_kernel)
|
||||
return 0;
|
||||
|
||||
p = path_join(root, etc_kernel, "entry-token");
|
||||
if (!p)
|
||||
return log_oom();
|
||||
|
||||
r = read_one_line_file(p, &buf);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read %s: %m", p);
|
||||
|
||||
if (isempty(buf))
|
||||
return 0;
|
||||
|
||||
if (!boot_entry_token_valid(buf)) {
|
||||
log_debug("Invalid entry token specified in %s, ignoring.", p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*token = TAKE_PTR(buf);
|
||||
*type = BOOT_ENTRY_TOKEN_LITERAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int entry_token_from_machine_id(sd_id128_t machine_id, BootEntryTokenType *type, char **token) {
|
||||
char *p;
|
||||
|
||||
assert(type);
|
||||
assert(IN_SET(*type, BOOT_ENTRY_TOKEN_AUTO, BOOT_ENTRY_TOKEN_MACHINE_ID));
|
||||
assert(token);
|
||||
|
||||
if (sd_id128_is_null(machine_id))
|
||||
return 0;
|
||||
|
||||
p = strdup(SD_ID128_TO_STRING(machine_id));
|
||||
if (!p)
|
||||
return log_oom();
|
||||
|
||||
*token = p;
|
||||
*type = BOOT_ENTRY_TOKEN_MACHINE_ID;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int entry_token_from_os_release(const char *root, BootEntryTokenType *type, char **token) {
|
||||
_cleanup_free_ char *id = NULL, *image_id = NULL;
|
||||
int r;
|
||||
|
||||
assert(type);
|
||||
assert(IN_SET(*type, BOOT_ENTRY_TOKEN_AUTO, BOOT_ENTRY_TOKEN_OS_IMAGE_ID, BOOT_ENTRY_TOKEN_OS_ID));
|
||||
assert(token);
|
||||
|
||||
switch (*type) {
|
||||
case BOOT_ENTRY_TOKEN_AUTO:
|
||||
r = parse_os_release(root,
|
||||
"IMAGE_ID", &image_id,
|
||||
"ID", &id);
|
||||
break;
|
||||
|
||||
case BOOT_ENTRY_TOKEN_OS_IMAGE_ID:
|
||||
r = parse_os_release(root, "IMAGE_ID", &image_id);
|
||||
break;
|
||||
|
||||
case BOOT_ENTRY_TOKEN_OS_ID:
|
||||
r = parse_os_release(root, "ID", &id);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to load %s/etc/os-release: %m", strempty(root));
|
||||
|
||||
if (!isempty(image_id) && boot_entry_token_valid(image_id)) {
|
||||
*token = TAKE_PTR(image_id);
|
||||
*type = BOOT_ENTRY_TOKEN_OS_IMAGE_ID;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!isempty(id) && boot_entry_token_valid(id)) {
|
||||
*token = TAKE_PTR(id);
|
||||
*type = BOOT_ENTRY_TOKEN_OS_ID;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int boot_entry_token_ensure(
|
||||
const char *root,
|
||||
const char *etc_kernel,
|
||||
sd_id128_t machine_id,
|
||||
BootEntryTokenType *type,
|
||||
char **token) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(type);
|
||||
assert(token);
|
||||
|
||||
if (*token)
|
||||
return 0; /* Already set. */
|
||||
|
||||
switch (*type) {
|
||||
|
||||
case BOOT_ENTRY_TOKEN_AUTO:
|
||||
r = entry_token_load(root, etc_kernel, type, token);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = entry_token_from_machine_id(machine_id, type, token);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = entry_token_from_os_release(root, type, token);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"No machine ID set, and %s/etc/os-release carries no ID=/IMAGE_ID= fields.",
|
||||
strempty(root));
|
||||
|
||||
case BOOT_ENTRY_TOKEN_MACHINE_ID:
|
||||
r = entry_token_from_machine_id(machine_id, type, token);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No machine ID set.");
|
||||
|
||||
case BOOT_ENTRY_TOKEN_OS_IMAGE_ID:
|
||||
r = entry_token_from_os_release(root, type, token);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"IMAGE_ID= field not set in %s/etc/os-release.",
|
||||
strempty(root));
|
||||
|
||||
case BOOT_ENTRY_TOKEN_OS_ID:
|
||||
r = entry_token_from_os_release(root, type, token);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"ID= field not set in %s/etc/os-release.",
|
||||
strempty(root));
|
||||
|
||||
case BOOT_ENTRY_TOKEN_LITERAL:
|
||||
/* In this case, the token should be already set by the user input. */
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
int parse_boot_entry_token_type(const char *s, BootEntryTokenType *type, char **token) {
|
||||
assert(s);
|
||||
assert(type);
|
||||
assert(token);
|
||||
|
||||
/*
|
||||
* This function is intended to be used in command line parsers, to handle token that are passed in.
|
||||
*
|
||||
* NOTE THAT THIS WILL FREE THE PREVIOUS ARGUMENT POINTER ON SUCCESS!
|
||||
* Hence, do not pass in uninitialized pointers.
|
||||
*/
|
||||
|
||||
if (streq(s, "machine-id")) {
|
||||
*type = BOOT_ENTRY_TOKEN_MACHINE_ID;
|
||||
*token = mfree(*token);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (streq(s, "os-image-id")) {
|
||||
*type = BOOT_ENTRY_TOKEN_OS_IMAGE_ID;
|
||||
*token = mfree(*token);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (streq(s, "os-id")) {
|
||||
*type = BOOT_ENTRY_TOKEN_OS_ID;
|
||||
*token = mfree(*token);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *e = startswith(s, "literal:");
|
||||
if (e) {
|
||||
if (!boot_entry_token_valid(e))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid entry token literal is specified for --entry-token=.");
|
||||
|
||||
*type = BOOT_ENTRY_TOKEN_LITERAL;
|
||||
return free_and_strdup_warn(token, e);
|
||||
}
|
||||
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Unexpected parameter for --entry-token=: %s", s);
|
||||
}
|
25
src/shared/boot-entry.h
Normal file
25
src/shared/boot-entry.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
typedef enum BootEntryTokenType {
|
||||
BOOT_ENTRY_TOKEN_MACHINE_ID,
|
||||
BOOT_ENTRY_TOKEN_OS_IMAGE_ID,
|
||||
BOOT_ENTRY_TOKEN_OS_ID,
|
||||
BOOT_ENTRY_TOKEN_LITERAL,
|
||||
BOOT_ENTRY_TOKEN_AUTO,
|
||||
} BootEntryTokenType;
|
||||
|
||||
bool boot_entry_token_valid(const char *p);
|
||||
|
||||
int boot_entry_token_ensure(
|
||||
const char *root,
|
||||
const char *etc_kernel, /* will be prefixed with root, typically /etc/kernel. */
|
||||
sd_id128_t machine_id,
|
||||
BootEntryTokenType *type, /* input and output */
|
||||
char **token); /* output, but do not pass uninitialized value. */
|
||||
|
||||
int parse_boot_entry_token_type(const char *s, BootEntryTokenType *type, char **token);
|
@ -10,6 +10,7 @@ shared_sources = files(
|
||||
'bitmap.c',
|
||||
'blockdev-util.c',
|
||||
'bond-util.c',
|
||||
'boot-entry.c',
|
||||
'boot-timestamps.c',
|
||||
'bootspec.c',
|
||||
'bpf-dlopen.c',
|
||||
|
Loading…
Reference in New Issue
Block a user