Merge pull request #10175 from poettering/sd-boot-count-bootctl

the bootctl changes from PR #9437 (the boot counting PR)
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2018-10-08 23:14:14 +02:00 committed by GitHub
commit 304d6b1886
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 482 additions and 233 deletions

View File

@ -112,6 +112,13 @@ systemd-timedated:
first existing unit listed in the environment variable, and
`timedatectl set-ntp off` disables and stops all listed units.
bootctl and other tools that access the EFI System Partition (ESP):
* `$SYSTEMD_RELAX_ESP_CHECKS=1` — if set, the ESP validation checks are
relaxed. Specifically, validation checks that ensure the specified ESP path
is a FAT file system are turned off, as are checks that the path is located
on a GPT partition with the correct type UUID.
systemd itself:
* `$SYSTEMD_ACTIVATION_UNIT` — set for all NSS and PAM module invocations that

View File

@ -34,10 +34,10 @@
<refsect1>
<title>Description</title>
<para><command>bootctl</command> can check the EFI boot loader status, list
available entries, and install, update, or remove the
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>
boot loader on the current system.</para>
<para><command>bootctl</command> can check the EFI boot loader status, list available boot loaders and boot loader
entries, and install, update, or remove the
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> boot loader on the
current system.</para>
</refsect1>
<refsect1>
@ -45,8 +45,6 @@
<para>The following options are understood:</para>
<variablelist>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
<varlistentry>
<term><option>--path=</option></term>
<listitem><para>Path to the EFI System Partition (ESP). If not specified, <filename>/efi</filename>,
@ -64,8 +62,12 @@
<varlistentry>
<term><option>--no-variables</option></term>
<listitem><para>Do not touch the EFI boot variables.</para></listitem>
<listitem><para>Do not touch the firmware's boot loader list stored in EFI variables.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="no-pager"/>
<xi:include href="standard-options.xml" xpointer="help"/>
<xi:include href="standard-options.xml" xpointer="version"/>
</variablelist>
</refsect1>
@ -76,42 +78,54 @@
<varlistentry>
<term><option>status</option></term>
<listitem><para>Shows the currently installed versions of the boot loader binaries and all current
EFI boot variables. If no command is specified, this is the implied default.</para></listitem>
<listitem><para>Shows brief information about the system firmware, the boot loader that was used to boot the
system, the boot loaders currently available in the ESP, the boot loaders listed in the firmware's list of boot
loaders and the current default boot loader entry. If no command is specified, this is the implied
default.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>list</option></term>
<term><option>install</option></term>
<listitem><para>Shows all configured boot loader entries.</para></listitem>
<listitem><para>Installs systemd-boot into the EFI system partition. A copy of <command>systemd-boot</command>
will be stored as the EFI default/fallback loader at
<filename><replaceable>ESP</replaceable>/EFI/BOOT/BOOT*.EFI</filename>. The boot loader is then added to the
top of the firmware's boot loader list.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>update</option></term>
<listitem><para>Updates all installed versions of
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
if the current version is newer than the version installed in the EFI system
partition. This also includes the EFI default/fallback loader at
<filename><replaceable>ESP</replaceable>/EFI/BOOT/BOOT*.EFI</filename>. A
systemd-boot entry in the EFI boot variables is created if there is no current
entry. The created entry will be added to the end of the boot order list.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>install</option></term>
<listitem><para>Installs systemd-boot into the EFI system partition. A copy of systemd-boot will
be stored as the EFI default/fallback loader at
<filename><replaceable>ESP</replaceable>/EFI/BOOT/BOOT*.EFI</filename>. A systemd-boot entry in
the EFI boot variables is created and added to the top of the boot order list.</para></listitem>
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry>, if the
available version is newer than the version installed in the EFI system partition. This also includes the EFI
default/fallback loader at <filename><replaceable>ESP</replaceable>/EFI/BOOT/BOOT*.EFI</filename>. The boot
loader is then added to end of the firmware's boot loader list if missing.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>remove</option></term>
<listitem><para>Removes all installed versions of systemd-boot from the EFI system partition,
and removes systemd-boot from the EFI boot variables.</para></listitem>
<listitem><para>Removes all installed versions of <command>systemd-boot</command> from the EFI system partition
and the firmware's boot loader list.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>list</option></term>
<listitem><para>Shows all available boot loader entries implementing the <ulink
url="https://github.com/systemd/systemd/blob/master/docs/BOOT_LOADER_SPECIFICATION.md">Boot Loader
Specification</ulink>, as well as any other entries discovered or automatically generated by the boot
loader.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>set-default</option> <replaceable>ID</replaceable></term>
<term><option>set-oneshot</option> <replaceable>ID</replaceable></term>
<listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string as argument. The
<option>set-oneshot</option> command will set the default entry only for the next boot, the
<option>set-default</option> will set it persistently for all future boots.</para></listitem>
</varlistentry>
</variablelist>
@ -122,6 +136,13 @@
<para>On success, 0 is returned, a non-zero failure code otherwise.</para>
</refsect1>
<refsect1>
<title>Environment</title>
<para>If <varname>$SYSTEMD_RELAX_ESP_CHECKS=1</varname> is set the validation checks for the ESP are relaxed, and
the path specified with <option>--path=</option> may refer to any kind of file system on any kind of
partition.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>

View File

@ -1715,7 +1715,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlag
* it: the IMMUTABLE bit. Let's use this here, if this is requested. */
if (flags & BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE)
(void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL);
(void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL, NULL);
} else {
r = btrfs_subvol_set_read_only(new_path, true);
if (r < 0)

View File

@ -10,7 +10,7 @@
#include "fd-util.h"
#include "macro.h"
int chattr_fd(int fd, unsigned value, unsigned mask) {
int chattr_fd(int fd, unsigned value, unsigned mask, unsigned *previous) {
unsigned old_attr, new_attr;
struct stat st;
@ -28,23 +28,29 @@ int chattr_fd(int fd, unsigned value, unsigned mask) {
if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
return -ENOTTY;
if (mask == 0)
if (mask == 0 && !previous)
return 0;
if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
return -errno;
new_attr = (old_attr & ~mask) | (value & mask);
if (new_attr == old_attr)
if (new_attr == old_attr) {
if (previous)
*previous = old_attr;
return 0;
}
if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
return -errno;
if (previous)
*previous = old_attr;
return 1;
}
int chattr_path(const char *p, unsigned value, unsigned mask) {
int chattr_path(const char *p, unsigned value, unsigned mask, unsigned *previous) {
_cleanup_close_ int fd = -1;
assert(p);
@ -56,7 +62,7 @@ int chattr_path(const char *p, unsigned value, unsigned mask) {
if (fd < 0)
return -errno;
return chattr_fd(fd, value, mask);
return chattr_fd(fd, value, mask, previous);
}
int read_attr_fd(int fd, unsigned *ret) {

View File

@ -1,8 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
int chattr_fd(int fd, unsigned value, unsigned mask);
int chattr_path(const char *p, unsigned value, unsigned mask);
int chattr_fd(int fd, unsigned value, unsigned mask, unsigned *previous);
int chattr_path(const char *p, unsigned value, unsigned mask, unsigned *previous);
int read_attr_fd(int fd, unsigned *ret);
int read_attr_path(const char *p, unsigned *ret);

View File

@ -695,7 +695,7 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode, unsigned
}
if (chattr_flags != 0)
(void) chattr_fd(fdt, chattr_flags, (unsigned) -1);
(void) chattr_fd(fdt, chattr_flags, (unsigned) -1, NULL);
r = copy_file_fd(from, fdt, copy_flags);
if (r < 0) {
@ -743,7 +743,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, unsigned cha
}
if (chattr_flags != 0)
(void) chattr_fd(fdt, chattr_flags, (unsigned) -1);
(void) chattr_fd(fdt, chattr_flags, (unsigned) -1, NULL);
r = copy_file_fd(from, fdt, copy_flags);
if (r < 0)

View File

@ -29,6 +29,7 @@
#include "fileio.h"
#include "fs-util.h"
#include "locale-util.h"
#include "pager.h"
#include "parse-util.h"
#include "rm-rf.h"
#include "stat-util.h"
@ -36,6 +37,7 @@
#include "strv.h"
#include "terminal-util.h"
#include "umask-util.h"
#include "utf8.h"
#include "util.h"
#include "verbs.h"
#include "virt.h"
@ -43,6 +45,7 @@
static char *arg_path = NULL;
static bool arg_print_path = false;
static bool arg_touch_variables = true;
static bool arg_no_pager = false;
static int acquire_esp(
bool unprivileged_mode,
@ -155,7 +158,7 @@ static int enumerate_binaries(const char *esp_path, const char *path, const char
if (r < 0)
return r;
if (r > 0)
printf(" File: %s/%s/%s (%s)\n", special_glyph(TREE_RIGHT), path, de->d_name, v);
printf(" File: %s/%s/%s (%s%s%s)\n", special_glyph(TREE_RIGHT), path, de->d_name, ansi_highlight(), v, ansi_normal());
else
printf(" File: %s/%s/%s\n", special_glyph(TREE_RIGHT), path, de->d_name);
c++;
@ -167,7 +170,7 @@ static int enumerate_binaries(const char *esp_path, const char *path, const char
static int status_binaries(const char *esp_path, sd_id128_t partition) {
int r;
printf("Boot Loader Binaries:\n");
printf("Available Boot Loaders on ESP:\n");
if (!esp_path) {
printf(" ESP: Cannot find or access mount point of ESP.\n\n");
@ -181,13 +184,13 @@ static int status_binaries(const char *esp_path, sd_id128_t partition) {
r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
if (r == 0)
log_error("systemd-boot not installed in ESP.");
log_info("systemd-boot not installed in ESP.");
else if (r < 0)
return r;
r = enumerate_binaries(esp_path, "EFI/BOOT", "boot");
if (r == 0)
log_error("No default/fallback boot loader installed in ESP.");
log_info("No default/fallback boot loader installed in ESP.");
else if (r < 0)
return r;
@ -213,7 +216,7 @@ static int print_efi_option(uint16_t id, bool in_order) {
efi_tilt_backslashes(path);
printf(" Title: %s\n", strna(title));
printf(" Title: %s%s%s\n", ansi_highlight(), strna(title), ansi_normal());
printf(" ID: 0x%04X\n", id);
printf(" Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : "");
printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", SD_ID128_FORMAT_VAL(partition));
@ -224,9 +227,8 @@ static int print_efi_option(uint16_t id, bool in_order) {
}
static int status_variables(void) {
int n_options, n_order;
_cleanup_free_ uint16_t *options = NULL, *order = NULL;
int i;
int n_options, n_order, i;
n_options = efi_get_boot_options(&options);
if (n_options == -ENOENT)
@ -243,7 +245,7 @@ static int status_variables(void) {
return log_error_errno(n_order, "Failed to read EFI boot order.");
/* print entries in BootOrder first */
printf("Boot Loader Entries in EFI Variables:\n");
printf("Boot Loaders Listed in EFI Variables:\n");
for (i = 0; i < n_order; i++)
print_efi_option(order[i], true);
@ -264,49 +266,65 @@ static int status_variables(void) {
return 0;
}
static int boot_entry_show(const BootEntry *e, bool show_as_default) {
assert(e);
printf(" title: %s%s%s%s%s%s\n",
ansi_highlight(),
boot_entry_title(e),
ansi_normal(),
ansi_highlight_green(),
show_as_default ? " (default)" : "",
ansi_normal());
if (e->id)
printf(" id: %s\n", e->id);
if (e->version)
printf(" version: %s\n", e->version);
if (e->machine_id)
printf(" machine-id: %s\n", e->machine_id);
if (e->architecture)
printf(" architecture: %s\n", e->architecture);
if (e->kernel)
printf(" linux: %s\n", e->kernel);
if (!strv_isempty(e->initrd)) {
_cleanup_free_ char *t;
t = strv_join(e->initrd, " ");
if (!t)
return log_oom();
printf(" initrd: %s\n", t);
}
if (!strv_isempty(e->options)) {
_cleanup_free_ char *t;
t = strv_join(e->options, " ");
if (!t)
return log_oom();
printf(" options: %s\n", t);
}
if (e->device_tree)
printf(" devicetree: %s\n", e->device_tree);
return 0;
}
static int status_entries(const char *esp_path, sd_id128_t partition) {
int r;
_cleanup_(boot_config_free) BootConfig config = {};
printf("Default Boot Entry:\n");
int r;
r = boot_entries_load_config(esp_path, &config);
if (r < 0)
return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m",
esp_path);
return r;
if (config.default_entry < 0)
printf("%zu entries, no entry suitable as default\n", config.n_entries);
printf("%zu entries, no entry could be determined as default.\n", config.n_entries);
else {
const BootEntry *e = &config.entries[config.default_entry];
printf("Default Boot Loader Entry:\n");
printf(" title: %s\n", boot_entry_title(e));
if (e->version)
printf(" version: %s\n", e->version);
if (e->kernel)
printf(" linux: %s\n", e->kernel);
if (!strv_isempty(e->initrd)) {
_cleanup_free_ char *t;
t = strv_join(e->initrd, " ");
if (!t)
return log_oom();
printf(" initrd: %s\n", t);
}
if (!strv_isempty(e->options)) {
_cleanup_free_ char *t;
t = strv_join(e->options, " ");
if (!t)
return log_oom();
printf(" options: %s\n", t);
}
if (e->device_tree)
printf(" devicetree: %s\n", e->device_tree);
puts("");
boot_entry_show(config.entries + config.default_entry, false);
}
return 0;
@ -806,9 +824,9 @@ static int install_loader_config(const char *esp_path) {
return log_oom();
}
fprintf(f, "#timeout 3\n");
fprintf(f, "#console-mode keep\n");
fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
fprintf(f, "#timeout 3\n"
"#console-mode keep\n"
"default %s-*\n", sd_id128_to_string(machine_id, machine_string));
r = fflush_sync_and_check(f);
if (r < 0)
@ -840,16 +858,19 @@ static int help(int argc, char *argv[], void *userdata) {
" --path=PATH Path to the EFI System Partition (ESP)\n"
" -p --print-path Print path to the EFI partition\n"
" --no-variables Don't touch EFI variables\n"
"\nCommands:\n"
" --no-pager Do not pipe output into a pager\n"
"\nBoot Loader Commands:\n"
" status Show status of installed systemd-boot and EFI variables\n"
" list List boot entries\n"
" install Install systemd-boot to the ESP and EFI variables\n"
" update Update systemd-boot in the ESP and EFI variables\n"
" remove Remove systemd-boot from the ESP and EFI variables\n"
"\nBoot Loader Entries Commands:\n"
" list List boot loader entries\n"
" set-default ID Set default boot loader entry\n"
" set-oneshot ID Set default boot loader entry, for next boot only\n"
"\nSee the %s for details.\n"
, program_invocation_short_name
, link
);
, link);
return 0;
}
@ -859,6 +880,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_PATH = 0x100,
ARG_VERSION,
ARG_NO_VARIABLES,
ARG_NO_PAGER,
};
static const struct option options[] = {
@ -867,7 +889,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "path", required_argument, NULL, ARG_PATH },
{ "print-path", no_argument, NULL, 'p' },
{ "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
{ NULL, 0, NULL, 0 }
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
};
int c, r;
@ -899,6 +922,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_touch_variables = false;
break;
case ARG_NO_PAGER:
arg_no_pager = true;
break;
case '?':
return -EINVAL;
@ -938,6 +965,8 @@ static int verb_status(int argc, char *argv[], void *userdata) {
r = 0; /* If we couldn't determine the path, then don't consider that a problem from here on, just show what we
* can show */
(void) pager_open(arg_no_pager, false);
if (is_efi_boot()) {
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL;
sd_id128_t loader_part_uuid = SD_ID128_NULL;
@ -956,13 +985,13 @@ static int verb_status(int argc, char *argv[], void *userdata) {
r = log_warning_errno(k, "Failed to read EFI variable LoaderDevicePartUUID: %m");
printf("System:\n");
printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
printf(" Firmware: %s%s (%s)%s\n", ansi_highlight(), strna(fw_type), strna(fw_info), ansi_normal());
printf(" Secure Boot: %sd\n", enable_disable(is_efi_secure_boot()));
printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user");
printf("\n");
printf("Current Loader:\n");
printf(" Product: %s\n", strna(loader));
printf("Current Boot Loader:\n");
printf(" Product: %s%s%s\n", ansi_highlight(), strna(loader), ansi_normal());
if (stub)
printf(" Stub: %s\n", stub);
if (!sd_id128_is_null(loader_part_uuid))
@ -998,8 +1027,8 @@ static int verb_status(int argc, char *argv[], void *userdata) {
static int verb_list(int argc, char *argv[], void *userdata) {
_cleanup_(boot_config_free) BootConfig config = {};
_cleanup_free_ char **found_by_loader = NULL;
sd_id128_t uuid = SD_ID128_NULL;
unsigned n;
int r;
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
@ -1014,58 +1043,60 @@ static int verb_list(int argc, char *argv[], void *userdata) {
r = boot_entries_load_config(arg_path, &config);
if (r < 0)
return log_error_errno(r, "Failed to load bootspec config from \"%s/loader\": %m",
arg_path);
return r;
printf("Available boot entries:\n");
r = efi_loader_get_entries(&found_by_loader);
if (r < 0 && !IN_SET(r, -ENOENT, -EOPNOTSUPP))
log_debug_errno(r, "Failed to acquire boot loader discovered entries: %m");
for (n = 0; n < config.n_entries; n++) {
const BootEntry *e = &config.entries[n];
if (config.n_entries == 0)
log_info("No boot loader entries found.");
else {
size_t n;
printf(" title: %s%s%s%s%s%s\n",
ansi_highlight(),
boot_entry_title(e),
ansi_normal(),
ansi_highlight_green(),
n == (unsigned) config.default_entry ? " (default)" : "",
ansi_normal());
if (e->id)
printf(" id: %s\n", e->id);
if (e->version)
printf(" version: %s\n", e->version);
if (e->machine_id)
printf(" machine-id: %s\n", e->machine_id);
if (e->architecture)
printf(" architecture: %s\n", e->architecture);
if (e->kernel)
printf(" linux: %s\n", e->kernel);
if (!strv_isempty(e->initrd)) {
_cleanup_free_ char *t;
(void) pager_open(arg_no_pager, false);
t = strv_join(e->initrd, " ");
if (!t)
return log_oom();
printf("Boot Loader Entries:\n");
printf(" initrd: %s\n", t);
for (n = 0; n < config.n_entries; n++) {
r = boot_entry_show(config.entries + n, n == (size_t) config.default_entry);
if (r < 0)
return r;
puts("");
strv_remove(found_by_loader, config.entries[n].id);
}
if (!strv_isempty(e->options)) {
_cleanup_free_ char *t;
}
t = strv_join(e->options, " ");
if (!t)
return log_oom();
if (!strv_isempty(found_by_loader)) {
char **i;
printf(" options: %s\n", t);
}
if (e->device_tree)
printf(" devicetree: %s\n", e->device_tree);
printf("Automatic/Other Entries Found by Boot Loader:\n\n");
puts("");
STRV_FOREACH(i, found_by_loader)
puts(*i);
}
return 0;
}
static int sync_esp(void) {
_cleanup_close_ int fd = -1;
if (!arg_path)
return 0;
fd = open(arg_path, O_CLOEXEC|O_DIRECTORY|O_RDONLY);
if (fd < 0)
return log_error_errno(errno, "Couldn't open ESP '%s' for synchronization: %m", arg_path);
if (syncfs(fd) < 0)
return log_error_errno(errno, "Failed to synchronize the ESP '%s': %m", arg_path);
return 1;
}
static int verb_install(int argc, char *argv[], void *userdata) {
sd_id128_t uuid = SD_ID128_NULL;
@ -1092,6 +1123,8 @@ static int verb_install(int argc, char *argv[], void *userdata) {
}
}
(void) sync_esp();
if (arg_touch_variables)
r = install_variables(arg_path,
part, pstart, psize, uuid,
@ -1111,6 +1144,8 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
r = remove_binaries(arg_path);
(void) sync_esp();
if (arg_touch_variables) {
int q;
@ -1122,15 +1157,66 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
return r;
}
static int verb_set_default(int argc, char *argv[], void *userdata) {
const char *name;
int r;
if (!is_efi_boot()) {
log_error("Not booted with UEFI.");
return -EOPNOTSUPP;
}
if (access("/sys/firmware/efi/efivars/LoaderInfo-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", F_OK) < 0) {
if (errno == ENOENT) {
log_error_errno(errno, "Not booted with a supported boot loader.");
return -EOPNOTSUPP;
}
return log_error_errno(errno, "Failed to detect whether boot loader supports '%s' operation: %m", argv[0]);
}
if (detect_container() > 0) {
log_error("'%s' operation not supported in a container.", argv[0]);
return -EOPNOTSUPP;
}
if (!arg_touch_variables) {
log_error("'%s' operation cannot be combined with --touch-variables=no.", argv[0]);
return -EINVAL;
}
name = streq(argv[0], "set-default") ? "LoaderEntryDefault" : "LoaderEntryOneShot";
if (isempty(argv[1])) {
r = efi_set_variable(EFI_VENDOR_LOADER, name, NULL, 0);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to remove EFI variale: %m");
} else {
_cleanup_free_ char16_t *encoded = NULL;
encoded = utf8_to_utf16(argv[1], strlen(argv[1]));
if (!encoded)
return log_oom();
r = efi_set_variable(EFI_VENDOR_LOADER, name, encoded, char16_strlen(encoded) * 2 + 2);
if (r < 0)
return log_error_errno(r, "Failed to update EFI variable: %m");
}
return 0;
}
static int bootctl_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "help", VERB_ANY, VERB_ANY, 0, help },
{ "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
{ "list", VERB_ANY, 1, 0, verb_list },
{ "install", VERB_ANY, 1, VERB_MUST_BE_ROOT, verb_install },
{ "update", VERB_ANY, 1, VERB_MUST_BE_ROOT, verb_install },
{ "remove", VERB_ANY, 1, VERB_MUST_BE_ROOT, verb_remove },
{ "help", VERB_ANY, VERB_ANY, 0, help },
{ "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
{ "install", VERB_ANY, 1, VERB_MUST_BE_ROOT, verb_install },
{ "update", VERB_ANY, 1, VERB_MUST_BE_ROOT, verb_install },
{ "remove", VERB_ANY, 1, VERB_MUST_BE_ROOT, verb_remove },
{ "list", VERB_ANY, 1, 0, verb_list },
{ "set-default", 2, 2, VERB_MUST_BE_ROOT, verb_set_default },
{ "set-oneshot", 2, 2, VERB_MUST_BE_ROOT, verb_set_default },
{}
};
@ -1154,6 +1240,8 @@ int main(int argc, char *argv[]) {
r = bootctl_main(argc, argv);
finish:
pager_close();
free(arg_path);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@ -175,7 +175,7 @@ static int raw_import_maybe_convert_qcow2(RawImport *i) {
if (converted_fd < 0)
return log_error_errno(errno, "Failed to create %s: %m", t);
r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL);
r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
if (r < 0)
log_warning_errno(r, "Failed to set file attributes on %s: %m", t);
@ -260,7 +260,7 @@ static int raw_import_open_disk(RawImport *i) {
if (i->output_fd < 0)
return log_error_errno(errno, "Failed to open destination %s: %m", i->temp_path);
r = chattr_fd(i->output_fd, FS_NOCOW_FL, FS_NOCOW_FL);
r = chattr_fd(i->output_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
if (r < 0)
log_warning_errno(r, "Failed to set file attributes on %s: %m", i->temp_path);

View File

@ -237,7 +237,7 @@ static int raw_pull_maybe_convert_qcow2(RawPull *i) {
if (converted_fd < 0)
return log_error_errno(errno, "Failed to create %s: %m", t);
r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL);
r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
if (r < 0)
log_warning_errno(r, "Failed to set file attributes on %s: %m", t);
@ -353,7 +353,7 @@ static int raw_pull_make_local_copy(RawPull *i) {
* performance on COW file systems like btrfs, since it
* reduces fragmentation caused by not allowing in-place
* writes. */
r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL);
r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
if (r < 0)
log_warning_errno(r, "Failed to set file attributes on %s: %m", tp);
@ -595,7 +595,7 @@ static int raw_pull_job_on_open_disk_raw(PullJob *j) {
if (r < 0)
return r;
r = chattr_fd(j->disk_fd, FS_NOCOW_FL, FS_NOCOW_FL);
r = chattr_fd(j->disk_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL);
if (r < 0)
log_warning_errno(r, "Failed to set file attributes on %s, ignoring: %m", i->temp_path);

View File

@ -372,7 +372,7 @@ JournalFile* journal_file_close(JournalFile *f) {
* reenable all the good bits COW usually provides
* (such as data checksumming). */
(void) chattr_fd(f->fd, 0, FS_NOCOW_FL);
(void) chattr_fd(f->fd, 0, FS_NOCOW_FL, NULL);
(void) btrfs_defrag_fd(f->fd);
}
@ -3563,7 +3563,7 @@ int journal_file_open_reliably(
/* btrfs doesn't cope well with our write pattern and
* fragments heavily. Let's defrag all files we rotate */
(void) chattr_path(p, 0, FS_NOCOW_FL);
(void) chattr_path(p, 0, FS_NOCOW_FL, NULL);
(void) btrfs_defrag(p);
log_warning_errno(r, "File %s corrupted or uncleanly shut down, renaming and replacing.", fname);

View File

@ -1732,7 +1732,7 @@ static int setup_keys(void) {
/* Enable secure remove, exclusion from dump, synchronous
* writing and in-place updating */
r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL);
r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, NULL);
if (r < 0)
log_warning_errno(r, "Failed to set file attributes: %m");

View File

@ -12,6 +12,7 @@
#include "def.h"
#include "device-nodes.h"
#include "efivars.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "parse-util.h"
@ -20,7 +21,7 @@
#include "strv.h"
#include "virt.h"
void boot_entry_free(BootEntry *entry) {
static void boot_entry_free(BootEntry *entry) {
assert(entry);
free(entry->id);
@ -37,7 +38,7 @@ void boot_entry_free(BootEntry *entry) {
free(entry->device_tree);
}
int boot_entry_load(const char *path, BootEntry *entry) {
static int boot_entry_load(const char *path, BootEntry *entry) {
_cleanup_(boot_entry_free) BootEntry tmp = {};
_cleanup_fclose_ FILE *f = NULL;
unsigned line = 1;
@ -144,7 +145,7 @@ void boot_config_free(BootConfig *config) {
free(config->entries);
}
int boot_loader_read_conf(const char *path, BootConfig *config) {
static int boot_loader_read_conf(const char *path, BootConfig *config) {
_cleanup_fclose_ FILE *f = NULL;
unsigned line = 1;
int r;
@ -153,8 +154,12 @@ int boot_loader_read_conf(const char *path, BootConfig *config) {
assert(config);
f = fopen(path, "re");
if (!f)
if (!f) {
if (errno == ENOENT)
return 0;
return log_error_errno(errno, "Failed to open \"%s\": %m", path);
}
for (;;) {
_cleanup_free_ char *buf = NULL, *field = NULL;
@ -204,14 +209,14 @@ int boot_loader_read_conf(const char *path, BootConfig *config) {
return log_error_errno(r, "%s:%u: Error while reading: %m", path, line);
}
return 0;
return 1;
}
static int boot_entry_compare(const BootEntry *a, const BootEntry *b) {
return str_verscmp(a->id, b->id);
}
int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *ret_n_entries) {
static int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *ret_n_entries) {
_cleanup_strv_free_ char **files = NULL;
char **f;
int r;
@ -362,24 +367,26 @@ int boot_entries_load_config(const char *esp_path, BootConfig *config) {
p = strjoina(esp_path, "/loader/loader.conf");
r = boot_loader_read_conf(p, config);
if (r < 0)
return log_error_errno(r, "Failed to read boot config from \"%s\": %m", p);
return r;
p = strjoina(esp_path, "/loader/entries");
r = boot_entries_find(p, &config->entries, &config->n_entries);
if (r < 0)
return log_error_errno(r, "Failed to read boot entries from \"%s\": %m", p);
return r;
r = boot_entries_uniquify(config->entries, config->n_entries);
if (r < 0)
return log_error_errno(r, "Failed to uniquify boot entries: %m");
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &config->entry_oneshot);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to read EFI var \"LoaderEntryOneShot\": %m");
if (is_efi_boot()) {
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &config->entry_oneshot);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to read EFI var \"LoaderEntryOneShot\": %m");
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryDefault", &config->entry_default);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to read EFI var \"LoaderEntryDefault\": %m");
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryDefault", &config->entry_default);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to read EFI var \"LoaderEntryDefault\": %m");
}
config->default_entry = boot_entries_select_default(config);
return 0;
@ -406,28 +413,33 @@ static int verify_esp(
struct statfs sfs;
sd_id128_t uuid = SD_ID128_NULL;
uint32_t part = 0;
bool relax_checks;
int r;
assert(p);
relax_checks = getenv_bool("SYSTEMD_RELAX_ESP_CHECKS") > 0;
/* Non-root user can only check the status, so if an error occured in the following, it does not cause any
* issues. Let's also, silence the error messages. */
if (statfs(p, &sfs) < 0) {
/* If we are searching for the mount point, don't generate a log message if we can't find the path */
if (errno == ENOENT && searching)
return -ENOENT;
if (!relax_checks) {
if (statfs(p, &sfs) < 0) {
/* If we are searching for the mount point, don't generate a log message if we can't find the path */
if (errno == ENOENT && searching)
return -ENOENT;
return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
"Failed to check file system type of \"%s\": %m", p);
}
return log_full_errno(unprivileged_mode && errno == EACCES ? LOG_DEBUG : LOG_ERR, errno,
"Failed to check file system type of \"%s\": %m", p);
}
if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC)) {
if (searching)
return -EADDRNOTAVAIL;
if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC)) {
if (searching)
return -EADDRNOTAVAIL;
log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p);
return -ENODEV;
log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p);
return -ENODEV;
}
}
if (stat(p, &st) < 0)
@ -452,7 +464,7 @@ static int verify_esp(
/* In a container we don't have access to block devices, skip this part of the verification, we trust the
* container manager set everything up correctly on its own. Also skip the following verification for non-root user. */
if (detect_container() > 0 || unprivileged_mode)
if (detect_container() > 0 || unprivileged_mode || relax_checks)
goto finish;
#if HAVE_BLKID

View File

@ -39,11 +39,6 @@ typedef struct BootConfig {
ssize_t default_entry;
} BootConfig;
void boot_entry_free(BootEntry *entry);
int boot_entry_load(const char *path, BootEntry *entry);
int boot_entries_find(const char *dir, BootEntry **entries, size_t *n_entries);
int boot_loader_read_conf(const char *path, BootConfig *config);
void boot_config_free(BootConfig *config);
int boot_entries_load_config(const char *esp_path, BootConfig *config);

View File

@ -4,6 +4,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <linux/fs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -13,6 +14,7 @@
#include "sd-id128.h"
#include "alloc-util.h"
#include "chattr-util.h"
#include "dirent-util.h"
#include "efivars.h"
#include "fd-util.h"
@ -20,6 +22,7 @@
#include "macro.h"
#include "parse-util.h"
#include "stdio-util.h"
#include "strv.h"
#include "time-util.h"
#include "utf8.h"
#include "util.h"
@ -63,7 +66,10 @@ struct device_path {
} _packed_;
bool is_efi_boot(void) {
return access("/sys/firmware/efi", F_OK) >= 0;
if (detect_container() > 0)
return false;
return access("/sys/firmware/efi/", F_OK) >= 0;
}
static int read_flag(const char *varname) {
@ -72,6 +78,9 @@ static int read_flag(const char *varname) {
size_t s;
int r;
if (!is_efi_boot()) /* If this is not an EFI boot, assume the queried flags are zero */
return 0;
r = efi_get_variable(EFI_VENDOR_GLOBAL, varname, NULL, &v, &s);
if (r < 0)
return r;
@ -80,7 +89,7 @@ static int read_flag(const char *varname) {
return -EINVAL;
b = *(uint8_t *)v;
return b > 0;
return !!b;
}
bool is_efi_secure_boot(void) {
@ -97,7 +106,7 @@ int efi_reboot_to_firmware_supported(void) {
size_t s;
int r;
if (!is_efi_boot() || detect_container() > 0)
if (!is_efi_boot())
return -EOPNOTSUPP;
r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", NULL, &v, &s);
@ -120,21 +129,18 @@ static int get_os_indications(uint64_t *os_indication) {
size_t s;
int r;
/* Let's verify general support first */
r = efi_reboot_to_firmware_supported();
if (r < 0)
return r;
r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s);
if (r == -ENOENT) {
/* Some firmware implementations that do support
* OsIndications and report that with
* OsIndicationsSupported will remove the
* OsIndications variable when it is unset. Let's
* pretend it's 0 then, to hide this implementation
* detail. Note that this call will return -ENOENT
* then only if the support for OsIndications is
* missing entirely, as determined by
* efi_reboot_to_firmware_supported() above. */
/* Some firmware implementations that do support OsIndications and report that with
* OsIndicationsSupported will remove the OsIndications variable when it is unset. Let's pretend it's 0
* then, to hide this implementation detail. Note that this call will return -ENOENT then only if the
* support for OsIndications is missing entirely, as determined by efi_reboot_to_firmware_supported()
* above. */
*os_indication = 0;
return 0;
} else if (r < 0)
@ -252,6 +258,9 @@ int efi_set_variable(
} _packed_ * _cleanup_free_ buf = NULL;
_cleanup_free_ char *p = NULL;
_cleanup_close_ int fd = -1;
bool saved_flags_valid = false;
unsigned saved_flags;
int r;
assert(name);
assert(value || size == 0);
@ -261,24 +270,60 @@ int efi_set_variable(
name, SD_ID128_FORMAT_VAL(vendor)) < 0)
return -ENOMEM;
/* Newer efivarfs protects variables that are not in a whitelist with FS_IMMUTABLE_FL by default, to protect
* them for accidental removal and modification. We are not changing these variables accidentally however,
* hence let's unset the bit first. */
r = chattr_path(p, 0, FS_IMMUTABLE_FL, &saved_flags);
if (r < 0 && r != -ENOENT)
log_debug_errno(r, "Failed to drop FS_IMMUTABLE_FL flag from '%s', ignoring: %m", p);
saved_flags_valid = r >= 0;
if (size == 0) {
if (unlink(p) < 0)
return -errno;
if (unlink(p) < 0) {
r = -errno;
goto finish;
}
return 0;
}
fd = open(p, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0644);
if (fd < 0)
return -errno;
if (fd < 0) {
r = -errno;
goto finish;
}
buf = malloc(sizeof(uint32_t) + size);
if (!buf)
return -ENOMEM;
if (!buf) {
r = -ENOMEM;
goto finish;
}
buf->attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS;
memcpy(buf->buf, value, size);
return loop_write(fd, buf, sizeof(uint32_t) + size, false);
r = loop_write(fd, buf, sizeof(uint32_t) + size, false);
if (r < 0)
goto finish;
r = 0;
finish:
if (saved_flags_valid) {
int q;
/* Restore the original flags field, just in case */
if (fd < 0)
q = chattr_path(p, saved_flags, FS_IMMUTABLE_FL, NULL);
else
q = chattr_fd(fd, saved_flags, FS_IMMUTABLE_FL, NULL);
if (q < 0)
log_debug_errno(q, "Failed to restore FS_IMMUTABLE_FL on '%s', ignoring: %m", p);
}
return r;
}
int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) {
@ -344,6 +389,9 @@ int efi_get_boot_option(
sd_id128_t p_uuid = SD_ID128_NULL;
int r;
if (!is_efi_boot())
return -EOPNOTSUPP;
xsprintf(boot_id, "Boot%04X", id);
r = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l);
if (r < 0)
@ -455,23 +503,30 @@ static uint16_t *tilt_slashes(uint16_t *s) {
return s;
}
int efi_add_boot_option(uint16_t id, const char *title,
uint32_t part, uint64_t pstart, uint64_t psize,
sd_id128_t part_uuid, const char *path) {
char boot_id[9];
size_t size;
size_t title_len;
size_t path_len;
int efi_add_boot_option(
uint16_t id,
const char *title,
uint32_t part,
uint64_t pstart,
uint64_t psize,
sd_id128_t part_uuid,
const char *path) {
size_t size, title_len, path_len;
_cleanup_free_ char *buf = NULL;
struct boot_option *option;
struct device_path *devicep;
_cleanup_free_ char *buf = NULL;
char boot_id[9];
if (!is_efi_boot())
return -EOPNOTSUPP;
title_len = (strlen(title)+1) * 2;
path_len = (strlen(path)+1) * 2;
buf = calloc(sizeof(struct boot_option) + title_len +
sizeof(struct drive_path) +
sizeof(struct device_path) + path_len, 1);
buf = malloc0(sizeof(struct boot_option) + title_len +
sizeof(struct drive_path) +
sizeof(struct device_path) + path_len);
if (!buf)
return -ENOMEM;
@ -520,6 +575,9 @@ int efi_add_boot_option(uint16_t id, const char *title,
int efi_remove_boot_option(uint16_t id) {
char boot_id[9];
if (!is_efi_boot())
return -EOPNOTSUPP;
xsprintf(boot_id, "Boot%04X", id);
return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, 0);
}
@ -529,6 +587,9 @@ int efi_get_boot_order(uint16_t **order) {
size_t l;
int r;
if (!is_efi_boot())
return -EOPNOTSUPP;
r = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l);
if (r < 0)
return r;
@ -545,12 +606,15 @@ int efi_get_boot_order(uint16_t **order) {
}
int efi_set_boot_order(uint16_t *order, size_t n) {
if (!is_efi_boot())
return -EOPNOTSUPP;
return efi_set_variable(EFI_VENDOR_GLOBAL, "BootOrder", order, n * sizeof(uint16_t));
}
static int boot_id_hex(const char s[4]) {
int i;
int id = 0;
int id = 0, i;
for (i = 0; i < 4; i++)
if (s[i] >= '0' && s[i] <= '9')
@ -569,13 +633,16 @@ static int cmp_uint16(const uint16_t *a, const uint16_t *b) {
int efi_get_boot_options(uint16_t **options) {
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *de;
_cleanup_free_ uint16_t *list = NULL;
struct dirent *de;
size_t alloc = 0;
int count = 0;
assert(options);
if (!is_efi_boot())
return -EOPNOTSUPP;
dir = opendir("/sys/firmware/efi/efivars/");
if (!dir)
return -errno;
@ -636,6 +703,9 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
assert(firmware);
assert(loader);
if (!is_efi_boot())
return -EOPNOTSUPP;
r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x);
if (r < 0)
return r;
@ -660,6 +730,9 @@ int efi_loader_get_device_part_uuid(sd_id128_t *u) {
_cleanup_free_ char *p = NULL;
int r, parsed[16];
if (!is_efi_boot())
return -EOPNOTSUPP;
r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", &p);
if (r < 0)
return r;
@ -681,6 +754,56 @@ int efi_loader_get_device_part_uuid(sd_id128_t *u) {
return 0;
}
int efi_loader_get_entries(char ***ret) {
_cleanup_free_ char16_t *entries = NULL;
_cleanup_strv_free_ char **l = NULL;
size_t size, i, start;
int r;
assert(ret);
if (!is_efi_boot())
return -EOPNOTSUPP;
r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntries", NULL, (void**) &entries, &size);
if (r < 0)
return r;
/* The variable contains a series of individually NUL terminated UTF-16 strings. */
for (i = 0, start = 0;; i++) {
char *decoded;
bool end;
/* Is this the end of the variable's data? */
end = i * sizeof(char16_t) >= size;
/* Are we in the middle of a string? (i.e. not at the end of the variable, nor at a NUL terminator?) If
* so, let's go to the next entry. */
if (!end && entries[i] != 0)
continue;
/* We reached the end of a string, let's decode it into UTF-8 */
decoded = utf16_to_utf8(entries + start, (i - start) * sizeof(char16_t));
if (!decoded)
return -ENOMEM;
r = strv_consume(&l, decoded);
if (r < 0)
return r;
/* We reached the end of the variable */
if (end)
break;
/* Continue after the NUL byte */
start = i + 1;
}
*ret = TAKE_PTR(l);
return 0;
}
#endif
char *efi_tilt_backslashes(char *s) {

View File

@ -41,6 +41,8 @@ int efi_get_boot_options(uint16_t **options);
int efi_loader_get_device_part_uuid(sd_id128_t *u);
int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader);
int efi_loader_get_entries(char ***ret);
#else
static inline bool is_efi_boot(void) {
@ -111,6 +113,10 @@ static inline int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
return -EOPNOTSUPP;
}
static inline int efi_loader_get_entries(char ***ret) {
return -EOPNOTSUPP;
}
#endif
char *efi_tilt_backslashes(char *s);

View File

@ -637,7 +637,7 @@ int image_remove(Image *i) {
case IMAGE_DIRECTORY:
/* Allow deletion of read-only directories */
(void) chattr_path(i->path, 0, FS_IMMUTABLE_FL);
(void) chattr_path(i->path, 0, FS_IMMUTABLE_FL, NULL);
r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
if (r < 0)
return r;
@ -736,7 +736,7 @@ int image_rename(Image *i, const char *new_name) {
(void) read_attr_path(i->path, &file_attr);
if (file_attr & FS_IMMUTABLE_FL)
(void) chattr_path(i->path, 0, FS_IMMUTABLE_FL);
(void) chattr_path(i->path, 0, FS_IMMUTABLE_FL, NULL);
_fallthrough_;
case IMAGE_SUBVOLUME:
@ -777,7 +777,7 @@ int image_rename(Image *i, const char *new_name) {
/* Restore the immutable bit, if it was set before */
if (file_attr & FS_IMMUTABLE_FL)
(void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL);
(void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL, NULL);
free_and_replace(i->path, new_path);
free_and_replace(i->name, nn);
@ -927,7 +927,7 @@ int image_read_only(Image *i, bool b) {
a read-only subvolume, but at least something, and
we can read the value back. */
r = chattr_path(i->path, b ? FS_IMMUTABLE_FL : 0, FS_IMMUTABLE_FL);
r = chattr_path(i->path, b ? FS_IMMUTABLE_FL : 0, FS_IMMUTABLE_FL, NULL);
if (r < 0)
return r;

View File

@ -8,19 +8,15 @@
#include "util.h"
static int test_acpi_fpdt(void) {
usec_t loader_start;
usec_t loader_exit;
char ts_start[FORMAT_TIMESPAN_MAX];
char ts_exit[FORMAT_TIMESPAN_MAX];
char ts_span[FORMAT_TIMESPAN_MAX];
char ts_start[FORMAT_TIMESPAN_MAX], ts_exit[FORMAT_TIMESPAN_MAX], ts_span[FORMAT_TIMESPAN_MAX];
usec_t loader_start, loader_exit;
int r;
r = acpi_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -ENODATA;
log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
r, "Failed to read ACPI FPDT: %m");
log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read ACPI FPDT: %m");
return ok ? 0 : r;
}
@ -32,19 +28,15 @@ static int test_acpi_fpdt(void) {
}
static int test_efi_loader(void) {
usec_t loader_start;
usec_t loader_exit;
char ts_start[FORMAT_TIMESPAN_MAX];
char ts_exit[FORMAT_TIMESPAN_MAX];
char ts_span[FORMAT_TIMESPAN_MAX];
char ts_start[FORMAT_TIMESPAN_MAX], ts_exit[FORMAT_TIMESPAN_MAX], ts_span[FORMAT_TIMESPAN_MAX];
usec_t loader_start, loader_exit;
int r;
r = efi_loader_get_boot_usec(&loader_start, &loader_exit);
if (r < 0) {
bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -EOPNOTSUPP;
log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
r, "Failed to read EFI loader data: %m");
log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read EFI loader data: %m");
return ok ? 0 : r;
}
@ -57,17 +49,16 @@ static int test_efi_loader(void) {
static int test_boot_timestamps(void) {
char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)];
int r;
dual_timestamp fw, l, k;
int r;
dual_timestamp_from_monotonic(&k, 0);
r = boot_timestamps(NULL, &fw, &l);
if (r < 0) {
bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES);
bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -EOPNOTSUPP;
log_full_errno(ok ? LOG_DEBUG : LOG_ERR,
r, "Failed to read variables: %m");
log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read variables: %m");
return ok ? 0 : r;
}

View File

@ -1232,7 +1232,7 @@ static int fd_set_attribute(Item *item, int fd, const char *path, const struct s
if (procfs_fd < 0)
return log_error_errno(procfs_fd, "Failed to re-open '%s': %m", path);
r = chattr_fd(procfs_fd, f, item->attribute_mask);
r = chattr_fd(procfs_fd, f, item->attribute_mask, NULL);
if (r < 0)
log_full_errno(IN_SET(r, -ENOTTY, -EOPNOTSUPP) ? LOG_DEBUG : LOG_WARNING,
r,