1
0
mirror of https://github.com/systemd/systemd synced 2026-04-23 07:24:51 +02:00

Compare commits

..

No commits in common. "f3376ee8fa28aab3f7edfad1ddfbcceca5bc841c" and "1b46eb23bc40206b2ed6e221dcf1d41e18df7613" have entirely different histories.

49 changed files with 426 additions and 687 deletions

2
TODO
View File

@ -78,8 +78,6 @@ Janitorial Clean-ups:
Features: Features:
* bootspec: remove tries counter from boot entry ids
* automatically ignore threaded cgroups in cg_xyz(). * automatically ignore threaded cgroups in cg_xyz().
* add linker script that implicitly adds symbol for build ID and new coredump * add linker script that implicitly adds symbol for build ID and new coredump

View File

@ -266,15 +266,6 @@ tree by the time it notifies the service manager about start-up readiness, so
that the service's main cgroup is definitely an inner node by the time the that the service's main cgroup is definitely an inner node by the time the
service manager might start `ExecStartPost=`.) service manager might start `ExecStartPost=`.)
(Also note, if you intend to use "threaded" cgroups — as added in Linux 4.14 —,
then you should do that *two* levels down from the main service cgroup your
turned delegation on for. Why that? You need one level so that systemd can
properly create the `.control` subgroup, as described above. But that one
cannot be threaded, since that would mean `.control` has to be threaded too —
this is a requirement of threaded cgroups: either a cgroup and all its siblings
are threaded or none , but systemd expects it to be a regular cgroup. Thus you
have to nest a second cgroup beneath it which then can be threaded.)
## Three Scenarios ## Three Scenarios
Let's say you write a container manager, and you wonder what to do regarding Let's say you write a container manager, and you wonder what to do regarding

View File

@ -641,12 +641,7 @@ manpages = [
['sd_id128_randomize', '3', [], ''], ['sd_id128_randomize', '3', [], ''],
['sd_id128_to_string', ['sd_id128_to_string',
'3', '3',
['SD_ID128_STRING_MAX', ['SD_ID128_STRING_MAX', 'SD_ID128_TO_STRING', 'sd_id128_from_string'],
'SD_ID128_TO_STRING',
'SD_ID128_TO_UUID_STRING',
'SD_ID128_UUID_STRING_MAX',
'sd_id128_from_string',
'sd_id128_to_uuid_string'],
''], ''],
['sd_is_fifo', ['sd_is_fifo',
'3', '3',

View File

@ -18,11 +18,8 @@
<refnamediv> <refnamediv>
<refname>sd_id128_to_string</refname> <refname>sd_id128_to_string</refname>
<refname>SD_ID128_TO_STRING</refname> <refname>SD_ID128_TO_STRING</refname>
<refname>SD_ID128_STRING_MAX</refname>
<refname>sd_id128_to_uuid_string</refname>
<refname>SD_ID128_TO_UUID_STRING</refname>
<refname>SD_ID128_UUID_STRING_MAX</refname>
<refname>sd_id128_from_string</refname> <refname>sd_id128_from_string</refname>
<refname>SD_ID128_STRING_MAX</refname>
<refpurpose>Format or parse 128-bit IDs as strings</refpurpose> <refpurpose>Format or parse 128-bit IDs as strings</refpurpose>
</refnamediv> </refnamediv>
@ -32,22 +29,13 @@
<funcsynopsisinfo>#define SD_ID128_STRING_MAX 33U</funcsynopsisinfo> <funcsynopsisinfo>#define SD_ID128_STRING_MAX 33U</funcsynopsisinfo>
<funcsynopsisinfo>#define SD_ID128_UUID_STRING_MAX 37U</funcsynopsisinfo>
<funcsynopsisinfo>#define SD_ID128_TO_STRING(id) …</funcsynopsisinfo> <funcsynopsisinfo>#define SD_ID128_TO_STRING(id) …</funcsynopsisinfo>
<funcsynopsisinfo>#define SD_ID128_TO_UUID_STRING(id) …</funcsynopsisinfo>
<funcprototype> <funcprototype>
<funcdef>char *<function>sd_id128_to_string</function></funcdef> <funcdef>char *<function>sd_id128_to_string</function></funcdef>
<paramdef>sd_id128_t <parameter>id</parameter>, char <parameter>s</parameter>[static SD_ID128_STRING_MAX]</paramdef> <paramdef>sd_id128_t <parameter>id</parameter>, char <parameter>s</parameter>[static SD_ID128_STRING_MAX]</paramdef>
</funcprototype> </funcprototype>
<funcprototype>
<funcdef>char *<function>sd_id128_uuid_string</function></funcdef>
<paramdef>sd_id128_t <parameter>id</parameter>, char <parameter>s</parameter>[static SD_ID128_UUID_STRING_MAX]</paramdef>
</funcprototype>
<funcprototype> <funcprototype>
<funcdef>int <function>sd_id128_from_string</function></funcdef> <funcdef>int <function>sd_id128_from_string</function></funcdef>
<paramdef>const char *<parameter>s</parameter>, sd_id128_t *<parameter>ret</parameter></paramdef> <paramdef>const char *<parameter>s</parameter>, sd_id128_t *<parameter>ret</parameter></paramdef>
@ -70,10 +58,6 @@
which remains valid until the end of the current code block. This is usually the simplest way to acquire which remains valid until the end of the current code block. This is usually the simplest way to acquire
a string representation of a 128-bit ID in a buffer that is valid in the current code block.</para> a string representation of a 128-bit ID in a buffer that is valid in the current code block.</para>
<para><function>sd_id128_to_uuid_string()</function> and <function>SD_ID128_TO_UUID_STRING()</function>
are similar to these two functions/macros, but format the 128bit values as RFC4122 UUIDs, i.e. a series
of 36 lowercase hexadeciaml digits and dashes, terminated by a <constant>NUL</constant> byte.</para>
<para><function>sd_id128_from_string()</function> implements the reverse operation: it takes a 33 <para><function>sd_id128_from_string()</function> implements the reverse operation: it takes a 33
character string with 32 hexadecimal digits (either lowercase or uppercase, terminated by character string with 32 hexadecimal digits (either lowercase or uppercase, terminated by
<constant>NUL</constant>) and parses them back into a 128-bit ID returned in <constant>NUL</constant>) and parses them back into a 128-bit ID returned in
@ -81,7 +65,7 @@
ID formatted as RFC UUID. If <parameter>ret</parameter> is passed as <constant>NULL</constant> the ID formatted as RFC UUID. If <parameter>ret</parameter> is passed as <constant>NULL</constant> the
function will validate the passed ID string, but not actually return it in parsed form.</para> function will validate the passed ID string, but not actually return it in parsed form.</para>
<para>Note that when formatting and parsing 36 character UUIDs this is done strictly in Big Endian byte order, <para>Note that when parsing 37 character UUIDs this is done strictly in Big Endian byte order,
i.e. according to <ulink url="https://tools.ietf.org/html/rfc4122">RFC4122</ulink> Variant 1 rules, even i.e. according to <ulink url="https://tools.ietf.org/html/rfc4122">RFC4122</ulink> Variant 1 rules, even
if the UUID encodes a different variant. This matches behaviour in various other Linux userspace if the UUID encodes a different variant. This matches behaviour in various other Linux userspace
tools. It's probably wise to avoid UUIDs of other variant types.</para> tools. It's probably wise to avoid UUIDs of other variant types.</para>

View File

@ -417,11 +417,14 @@ int same_fd(int a, int b) {
assert(a >= 0); assert(a >= 0);
assert(b >= 0); assert(b >= 0);
/* Compares two file descriptors. Note that semantics are quite different depending on whether we /* Compares two file descriptors. Note that semantics are
* have kcmp() or we don't. If we have kcmp() this will only return true for dup()ed file * quite different depending on whether we have kcmp() or we
* descriptors, but not otherwise. If we don't have kcmp() this will also return true for two fds of * don't. If we have kcmp() this will only return true for
* the same file, created by separate open() calls. Since we use this call mostly for filtering out * dup()ed file descriptors, but not otherwise. If we don't
* duplicates in the fd store this difference hopefully doesn't matter too much. */ * have kcmp() this will also return true for two fds of the same
* file, created by separate open() calls. Since we use this
* call mostly for filtering out duplicates in the fd store
* this difference hopefully doesn't matter too much. */
if (a == b) if (a == b)
return true; return true;
@ -433,7 +436,7 @@ int same_fd(int a, int b) {
return true; return true;
if (r > 0) if (r > 0)
return false; return false;
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) if (!IN_SET(errno, ENOSYS, EACCES, EPERM))
return -errno; return -errno;
/* We don't have kcmp(), use fstat() instead. */ /* We don't have kcmp(), use fstat() instead. */
@ -443,17 +446,23 @@ int same_fd(int a, int b) {
if (fstat(b, &stb) < 0) if (fstat(b, &stb) < 0)
return -errno; return -errno;
if (!stat_inode_same(&sta, &stb)) if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
return false; return false;
/* We consider all device fds different, since two device fds might refer to quite different device /* We consider all device fds different, since two device fds
* contexts even though they share the same inode and backing dev_t. */ * might refer to quite different device contexts even though
* they share the same inode and backing dev_t. */
if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode)) if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
return false; return false;
/* The fds refer to the same inode on disk, let's also check if they have the same fd flags. This is if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
* useful to distinguish the read and write side of a pipe created with pipe(). */ return false;
/* The fds refer to the same inode on disk, let's also check
* if they have the same fd flags. This is useful to
* distinguish the read and write side of a pipe created with
* pipe(). */
fa = fcntl(a, F_GETFL); fa = fcntl(a, F_GETFL);
if (fa < 0) if (fa < 0)
return -errno; return -errno;

View File

@ -856,7 +856,8 @@ int conservative_renameat(
if (fstat(new_fd, &new_stat) < 0) if (fstat(new_fd, &new_stat) < 0)
goto do_rename; goto do_rename;
if (stat_inode_same(&new_stat, &old_stat)) if (new_stat.st_ino == old_stat.st_ino &&
new_stat.st_dev == old_stat.st_dev)
goto is_same; goto is_same;
if (old_stat.st_mode != new_stat.st_mode || if (old_stat.st_mode != new_stat.st_mode ||

View File

@ -298,8 +298,10 @@ fallback_fstat:
if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0) if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
return -errno; return -errno;
/* A directory with same device and inode as its parent? Must be the root directory */ /* A directory with same device and inode as its parent? Must
if (stat_inode_same(&a, &b)) * be the root directory */
if (a.st_dev == b.st_dev &&
a.st_ino == b.st_ino)
return 1; return 1;
return check_st_dev && (a.st_dev != b.st_dev); return check_st_dev && (a.st_dev != b.st_dev);

View File

@ -185,7 +185,8 @@ int files_same(const char *filea, const char *fileb, int flags) {
if (fstatat(AT_FDCWD, fileb, &b, flags) < 0) if (fstatat(AT_FDCWD, fileb, &b, flags) < 0)
return -errno; return -errno;
return stat_inode_same(&a, &b); return a.st_dev == b.st_dev &&
a.st_ino == b.st_ino;
} }
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) { bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
@ -416,18 +417,6 @@ int proc_mounted(void) {
return r; return r;
} }
bool stat_inode_same(const struct stat *a, const struct stat *b) {
/* Returns if the specified stat structure references the same (though possibly modified) inode. Does
* a thorough check, comparing inode nr, backing device and if the inode is still of the same type. */
return a && b &&
(a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */
((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */
a->st_dev == b->st_dev &&
a->st_ino == b->st_ino;
}
bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { bool stat_inode_unmodified(const struct stat *a, const struct stat *b) {
/* Returns if the specified stat structures reference the same, unmodified inode. This check tries to /* Returns if the specified stat structures reference the same, unmodified inode. This check tries to
@ -439,10 +428,14 @@ bool stat_inode_unmodified(const struct stat *a, const struct stat *b) {
* about contents of the file. The purpose here is to detect file contents changes, and nothing * about contents of the file. The purpose here is to detect file contents changes, and nothing
* else. */ * else. */
return stat_inode_same(a, b) && return a && b &&
(a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */
((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */
a->st_mtim.tv_sec == b->st_mtim.tv_sec && a->st_mtim.tv_sec == b->st_mtim.tv_sec &&
a->st_mtim.tv_nsec == b->st_mtim.tv_nsec && a->st_mtim.tv_nsec == b->st_mtim.tv_nsec &&
(!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */ (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */
a->st_dev == b->st_dev &&
a->st_ino == b->st_ino &&
(!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */ (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */
} }

View File

@ -92,7 +92,6 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret
int proc_mounted(void); int proc_mounted(void);
bool stat_inode_same(const struct stat *a, const struct stat *b);
bool stat_inode_unmodified(const struct stat *a, const struct stat *b); bool stat_inode_unmodified(const struct stat *a, const struct stat *b);
int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx); int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx);
@ -115,9 +114,3 @@ int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct s
struct new_statx nsx; \ struct new_statx nsx; \
} var } var
#endif #endif
static inline bool devid_set_and_equal(dev_t a, dev_t b) {
/* Returns true if a and b definitely refer to the same device. If either is zero, this means "don't
* know" and we'll return false */
return a == b && a != 0;
}

View File

@ -14,7 +14,6 @@
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "pretty-print.h" #include "pretty-print.h"
#include "stat-util.h"
#include "sync-util.h" #include "sync-util.h"
#include "terminal-util.h" #include "terminal-util.h"
#include "util.h" #include "util.h"
@ -99,18 +98,17 @@ static int parse_argv(int argc, char *argv[]) {
static int acquire_path(void) { static int acquire_path(void) {
_cleanup_free_ char *esp_path = NULL, *xbootldr_path = NULL; _cleanup_free_ char *esp_path = NULL, *xbootldr_path = NULL;
dev_t esp_devid = 0, xbootldr_devid = 0;
char **a; char **a;
int r; int r;
if (!strv_isempty(arg_path)) if (!strv_isempty(arg_path))
return 0; return 0;
r = find_esp_and_warn(NULL, /* unprivileged_mode= */ false, &esp_path, NULL, NULL, NULL, NULL, &esp_devid); r = find_esp_and_warn(NULL, false, &esp_path, NULL, NULL, NULL, NULL);
if (r < 0 && r != -ENOKEY) /* ENOKEY means not found, and is the only error the function won't log about on its own */ if (r < 0 && r != -ENOKEY) /* ENOKEY means not found, and is the only error the function won't log about on its own */
return r; return r;
r = find_xbootldr_and_warn(NULL, /* unprivileged_mode= */ false, &xbootldr_path, NULL, &xbootldr_devid); r = find_xbootldr_and_warn(NULL, false, &xbootldr_path, NULL);
if (r < 0 && r != -ENOKEY) if (r < 0 && r != -ENOKEY)
return r; return r;
@ -119,10 +117,8 @@ static int acquire_path(void) {
"Couldn't find $BOOT partition. It is recommended to mount it to /boot.\n" "Couldn't find $BOOT partition. It is recommended to mount it to /boot.\n"
"Alternatively, use --path= to specify path to mount point."); "Alternatively, use --path= to specify path to mount point.");
if (esp_path && xbootldr_path && !devid_set_and_equal(esp_devid, xbootldr_devid)) /* in case the two paths refer to the same inode, suppress one */ if (esp_path)
a = strv_new(esp_path, xbootldr_path); a = strv_new(esp_path, xbootldr_path);
else if (esp_path)
a = strv_new(esp_path);
else else
a = strv_new(xbootldr_path); a = strv_new(xbootldr_path);
if (!a) if (!a)
@ -134,7 +130,7 @@ static int acquire_path(void) {
_cleanup_free_ char *j = NULL; _cleanup_free_ char *j = NULL;
j = strv_join(arg_path, ":"); j = strv_join(arg_path, ":");
log_debug("Using %s as boot loader drop-in search path.", strna(j)); log_debug("Using %s as boot loader drop-in search path.", j);
} }
return 0; return 0;

View File

@ -36,7 +36,6 @@
#include "rm-rf.h" #include "rm-rf.h"
#include "stat-util.h" #include "stat-util.h"
#include "stdio-util.h" #include "stdio-util.h"
#include "string-table.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "sync-util.h" #include "sync-util.h"
@ -75,8 +74,7 @@ static int acquire_esp(
uint32_t *ret_part, uint32_t *ret_part,
uint64_t *ret_pstart, uint64_t *ret_pstart,
uint64_t *ret_psize, uint64_t *ret_psize,
sd_id128_t *ret_uuid, sd_id128_t *ret_uuid) {
dev_t *ret_devid) {
char *np; char *np;
int r; int r;
@ -87,7 +85,7 @@ static int acquire_esp(
* we simply eat up the error here, so that --list and --status work too, without noise about * we simply eat up the error here, so that --list and --status work too, without noise about
* this). */ * this). */
r = find_esp_and_warn(arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid); r = find_esp_and_warn(arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid);
if (r == -ENOKEY) { if (r == -ENOKEY) {
if (graceful) if (graceful)
return log_info_errno(r, "Couldn't find EFI system partition, skipping."); return log_info_errno(r, "Couldn't find EFI system partition, skipping.");
@ -105,23 +103,16 @@ static int acquire_esp(
return 1; return 1;
} }
static int acquire_xbootldr( static int acquire_xbootldr(bool unprivileged_mode, sd_id128_t *ret_uuid) {
bool unprivileged_mode,
sd_id128_t *ret_uuid,
dev_t *ret_devid) {
char *np; char *np;
int r; int r;
r = find_xbootldr_and_warn(arg_xbootldr_path, unprivileged_mode, &np, ret_uuid, ret_devid); r = find_xbootldr_and_warn(arg_xbootldr_path, unprivileged_mode, &np, ret_uuid);
if (r == -ENOKEY) { if (r == -ENOKEY) {
log_debug_errno(r, "Didn't find an XBOOTLDR partition, using the ESP as $BOOT."); log_debug_errno(r, "Didn't find an XBOOTLDR partition, using the ESP as $BOOT.");
arg_xbootldr_path = mfree(arg_xbootldr_path);
if (ret_uuid) if (ret_uuid)
*ret_uuid = SD_ID128_NULL; *ret_uuid = SD_ID128_NULL;
if (ret_devid) arg_xbootldr_path = mfree(arg_xbootldr_path);
*ret_devid = 0;
return 0; return 0;
} }
if (r < 0) if (r < 0)
@ -420,21 +411,7 @@ static void boot_entry_file_list(const char *field, const char *root, const char
*ret_status = status; *ret_status = status;
} }
static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = { static int boot_entry_show(const BootEntry *e, bool show_as_default) {
[BOOT_ENTRY_CONF] = "Boot Loader Specification Type #1 (.conf)",
[BOOT_ENTRY_UNIFIED] = "Boot Loader Specification Type #2 (.efi)",
[BOOT_ENTRY_LOADER] = "Reported by Boot Loader",
[BOOT_ENTRY_LOADER_AUTO] = "Automatic",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType);
static int boot_entry_show(
const BootEntry *e,
bool show_as_default,
bool show_as_selected,
bool show_reported) {
int status = 0; int status = 0;
/* Returns 0 on success, negative on processing error, and positive if something is wrong with the /* Returns 0 on success, negative on processing error, and positive if something is wrong with the
@ -442,30 +419,9 @@ static int boot_entry_show(
assert(e); assert(e);
printf(" type: %s\n", printf(" title: %s%s%s" "%s%s%s\n",
boot_entry_type_to_string(e->type)); ansi_highlight(), boot_entry_title(e), ansi_normal(),
ansi_highlight_green(), show_as_default ? " (default)" : "", ansi_normal());
printf(" title: %s%s%s",
ansi_highlight(), boot_entry_title(e), ansi_normal());
if (show_as_default)
printf(" %s(default)%s",
ansi_highlight_green(), ansi_normal());
if (show_as_selected)
printf(" %s(selected)%s",
ansi_highlight_magenta(), ansi_normal());
if (show_reported) {
if (e->type == BOOT_ENTRY_LOADER)
printf(" %s(reported/absent)%s",
ansi_highlight_red(), ansi_normal());
else if (!e->reported_by_loader && e->type != BOOT_ENTRY_LOADER_AUTO)
printf(" %s(not reported/new)%s",
ansi_highlight_green(), ansi_normal());
}
putchar('\n');
if (e->id) if (e->id)
printf(" id: %s\n", e->id); printf(" id: %s\n", e->id);
@ -494,7 +450,6 @@ static int boot_entry_show(
e->root, e->root,
*s, *s,
&status); &status);
if (!strv_isempty(e->options)) { if (!strv_isempty(e->options)) {
_cleanup_free_ char *t = NULL, *t2 = NULL; _cleanup_free_ char *t = NULL, *t2 = NULL;
_cleanup_strv_free_ char **ts = NULL; _cleanup_strv_free_ char **ts = NULL;
@ -513,16 +468,9 @@ static int boot_entry_show(
printf(" options: %s\n", t2); printf(" options: %s\n", t2);
} }
if (e->device_tree) if (e->device_tree)
boot_entry_file_list("devicetree", e->root, e->device_tree, &status); boot_entry_file_list("devicetree", e->root, e->device_tree, &status);
STRV_FOREACH(s, e->device_tree_overlay)
boot_entry_file_list(s == e->device_tree_overlay ? "devicetree-overlay" : NULL,
e->root,
*s,
&status);
return -status; return -status;
} }
@ -563,11 +511,7 @@ static int status_entries(
else { else {
printf("Default Boot Loader Entry:\n"); printf("Default Boot Loader Entry:\n");
r = boot_entry_show( r = boot_entry_show(config.entries + config.default_entry, false);
config.entries + config.default_entry,
/* show_as_default= */ false,
/* show_as_selected= */ false,
/* show_discovered= */ false);
if (r > 0) if (r > 0)
/* < 0 is already logged by the function itself, let's just emit an extra warning if /* < 0 is already logged by the function itself, let's just emit an extra warning if
the default entry is broken */ the default entry is broken */
@ -1444,7 +1388,7 @@ static void print_yes_no_line(bool first, bool good, const char *name) {
static int are_we_installed(void) { static int are_we_installed(void) {
int r; int r;
r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL, NULL); r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL);
if (r < 0) if (r < 0)
return r; return r;
@ -1476,10 +1420,9 @@ static int are_we_installed(void) {
static int verb_status(int argc, char *argv[], void *userdata) { static int verb_status(int argc, char *argv[], void *userdata) {
sd_id128_t esp_uuid = SD_ID128_NULL, xbootldr_uuid = SD_ID128_NULL; sd_id128_t esp_uuid = SD_ID128_NULL, xbootldr_uuid = SD_ID128_NULL;
dev_t esp_devid = 0, xbootldr_devid = 0;
int r, k; int r, k;
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, &esp_uuid, &esp_devid); r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, &esp_uuid);
if (arg_print_esp_path) { if (arg_print_esp_path) {
if (r == -EACCES) /* If we couldn't acquire the ESP path, log about access errors (which is the only if (r == -EACCES) /* If we couldn't acquire the ESP path, log about access errors (which is the only
* error the find_esp_and_warn() won't log on its own) */ * error the find_esp_and_warn() won't log on its own) */
@ -1490,7 +1433,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
puts(arg_esp_path); puts(arg_esp_path);
} }
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, &xbootldr_uuid, &xbootldr_devid); r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, &xbootldr_uuid);
if (arg_print_dollar_boot_path) { if (arg_print_dollar_boot_path) {
if (r == -EACCES) if (r == -EACCES)
return log_error_errno(r, "Failed to determine XBOOTLDR location: %m"); return log_error_errno(r, "Failed to determine XBOOTLDR location: %m");
@ -1624,14 +1567,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
} }
if (arg_esp_path || arg_xbootldr_path) { if (arg_esp_path || arg_xbootldr_path) {
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */ k = status_entries(arg_esp_path, esp_uuid, arg_xbootldr_path, xbootldr_uuid);
bool same = arg_esp_path && arg_xbootldr_path && devid_set_and_equal(esp_devid, xbootldr_devid);
k = status_entries(
arg_esp_path,
esp_uuid,
same ? NULL : arg_xbootldr_path,
same ? SD_ID128_NULL : xbootldr_uuid);
if (k < 0) if (k < 0)
r = k; r = k;
} }
@ -1642,29 +1578,25 @@ static int verb_status(int argc, char *argv[], void *userdata) {
static int verb_list(int argc, char *argv[], void *userdata) { static int verb_list(int argc, char *argv[], void *userdata) {
_cleanup_(boot_config_free) BootConfig config = {}; _cleanup_(boot_config_free) BootConfig config = {};
_cleanup_strv_free_ char **efi_entries = NULL; _cleanup_strv_free_ char **efi_entries = NULL;
dev_t esp_devid = 0, xbootldr_devid = 0;
int r; int r;
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn /* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
* off logging about access errors and turn off potentially privileged device probing. Here we're interested in * off logging about access errors and turn off potentially privileged device probing. Here we're interested in
* the latter but not the former, hence request the mode, and log about EACCES. */ * the latter but not the former, hence request the mode, and log about EACCES. */
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, NULL, &esp_devid); r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, NULL);
if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */ if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */
return log_error_errno(r, "Failed to determine ESP: %m"); return log_error_errno(r, "Failed to determine ESP: %m");
if (r < 0) if (r < 0)
return r; return r;
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, NULL, &xbootldr_devid); r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, NULL);
if (r == -EACCES) if (r == -EACCES)
return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m"); return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
if (r < 0) if (r < 0)
return r; return r;
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */ r = boot_entries_load_config(arg_esp_path, arg_xbootldr_path, &config);
bool same = arg_esp_path && arg_xbootldr_path && devid_set_and_equal(esp_devid, xbootldr_devid);
r = boot_entries_load_config(arg_esp_path, same ? NULL : arg_xbootldr_path, &config);
if (r < 0) if (r < 0)
return r; return r;
@ -1674,7 +1606,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
else if (r < 0) else if (r < 0)
log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m"); log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
else else
(void) boot_entries_augment_from_loader(&config, efi_entries, /* only_auto= */ false); (void) boot_entries_augment_from_loader(&config, efi_entries);
if (config.n_entries == 0) if (config.n_entries == 0)
log_info("No boot loader entries found."); log_info("No boot loader entries found.");
@ -1684,11 +1616,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
printf("Boot Loader Entries:\n"); printf("Boot Loader Entries:\n");
for (size_t n = 0; n < config.n_entries; n++) { for (size_t n = 0; n < config.n_entries; n++) {
r = boot_entry_show( r = boot_entry_show(config.entries + n, n == (size_t) config.default_entry);
config.entries + n,
/* show_as_default= */ n == (size_t) config.default_entry,
/* show_as_selected= */ n == (size_t) config.selected_entry,
/* show_discovered= */ true);
if (r < 0) if (r < 0)
return r; return r;
@ -1860,7 +1788,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
install = streq(argv[0], "install"); install = streq(argv[0], "install");
graceful = !install && arg_graceful; /* support graceful mode for updates */ graceful = !install && arg_graceful; /* support graceful mode for updates */
r = acquire_esp(/* unprivileged_mode= */ false, graceful, &part, &pstart, &psize, &uuid, NULL); r = acquire_esp(/* unprivileged_mode= */ false, graceful, &part, &pstart, &psize, &uuid);
if (graceful && r == -ENOKEY) if (graceful && r == -ENOKEY)
return 0; /* If --graceful is specified and we can't find an ESP, handle this cleanly */ return 0; /* If --graceful is specified and we can't find an ESP, handle this cleanly */
if (r < 0) if (r < 0)
@ -1877,7 +1805,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
} }
} }
r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL, NULL); r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL);
if (r < 0) if (r < 0)
return r; return r;
@ -1937,11 +1865,11 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
sd_id128_t uuid = SD_ID128_NULL; sd_id128_t uuid = SD_ID128_NULL;
int r, q; int r, q;
r = acquire_esp(/* unprivileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, &uuid, NULL); r = acquire_esp(/* unprivileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, &uuid);
if (r < 0) if (r < 0)
return r; return r;
r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL, NULL); r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL);
if (r < 0) if (r < 0)
return r; return r;
@ -2150,7 +2078,7 @@ static int verb_set_efivar(int argc, char *argv[], void *userdata) {
static int verb_random_seed(int argc, char *argv[], void *userdata) { static int verb_random_seed(int argc, char *argv[], void *userdata) {
int r; int r;
r = find_esp_and_warn(arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL, NULL); r = find_esp_and_warn(arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL);
if (r == -ENOKEY) { if (r == -ENOKEY) {
/* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */ /* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
if (!arg_graceful) if (!arg_graceful)

View File

@ -13,7 +13,6 @@
#include "hashmap.h" #include "hashmap.h"
#include "macro.h" #include "macro.h"
#include "memory-util.h" #include "memory-util.h"
#include "stat-util.h"
#include "string-util.h" #include "string-util.h"
#include "time-util.h" #include "time-util.h"
#include "user-util.h" #include "user-util.h"
@ -168,7 +167,9 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
if (!S_ISREG(st.st_mode)) if (!S_ISREG(st.st_mode))
continue; continue;
if (exclude_fd >= 0 && stat_inode_same(&exclude_st, &st)) if (exclude_fd >= 0 &&
exclude_st.st_dev == st.st_dev &&
exclude_st.st_ino == st.st_ino)
continue; continue;
r = hashmap_ensure_allocated(&h, NULL); r = hashmap_ensure_allocated(&h, NULL);

View File

@ -721,7 +721,7 @@ static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) {
return -errno; return -errno;
/* The process uses system root. */ /* The process uses system root. */
if (stat_inode_same(&proc_root_stat, &root_stat)) { if (proc_root_stat.st_ino == root_stat.st_ino) {
*cmdline = NULL; *cmdline = NULL;
return 0; return 0;
} }

View File

@ -779,16 +779,12 @@ static int add_mounts(void) {
return btrfs_log_dev_root(LOG_ERR, r, "root file system"); return btrfs_log_dev_root(LOG_ERR, r, "root file system");
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to determine block device of root file system: %m"); return log_error_errno(r, "Failed to determine block device of root file system: %m");
if (r == 0) { /* Not backed by a single block device. (Could be NFS or so, or could be multi-device RAID or so) */ if (r == 0) { /* Not backed by block device */
r = get_block_device_harder("/usr", &devno); r = get_block_device_harder("/usr", &devno);
if (r == -EUCLEAN) if (r == -EUCLEAN)
return btrfs_log_dev_root(LOG_ERR, r, "/usr"); return btrfs_log_dev_root(LOG_ERR, r, "/usr");
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to determine block device of /usr/ file system: %m"); return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
if (r == 0) { /* /usr/ not backed by single block device, either. */
log_debug("Neither root nor /usr/ file system are on a (single) block device.");
return 0;
}
} }
} else if (r < 0) } else if (r < 0)
return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m"); return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");

View File

@ -1239,7 +1239,10 @@ static int manager_add_device(Manager *m, sd_device *d) {
return 0; return 0;
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to acquire ID_PART_ENTRY_TYPE device property, ignoring: %m"); return log_error_errno(r, "Failed to acquire ID_PART_ENTRY_TYPE device property, ignoring: %m");
if (id128_equal_string(parttype, GPT_USER_HOME) <= 0) { r = sd_id128_from_string(parttype, &id);
if (r < 0)
return log_debug_errno(r, "Failed to parse ID_PART_ENTRY_TYPE field '%s', ignoring: %m", parttype);
if (!sd_id128_equal(id, GPT_USER_HOME)) {
log_debug("Found partition (%s) we don't care about, ignoring.", sysfs); log_debug("Found partition (%s) we don't care about, ignoring.", sysfs);
return 0; return 0;
} }

View File

@ -28,7 +28,6 @@
#include "filesystems.h" #include "filesystems.h"
#include "fs-util.h" #include "fs-util.h"
#include "fsck-util.h" #include "fsck-util.h"
#include "gpt.h"
#include "home-util.h" #include "home-util.h"
#include "homework-luks.h" #include "homework-luks.h"
#include "homework-mount.h" #include "homework-mount.h"
@ -704,7 +703,7 @@ static int luks_validate(
if (!pp) if (!pp)
return errno > 0 ? -errno : -EIO; return errno > 0 ? -errno : -EIO;
if (id128_equal_string(blkid_partition_get_type_string(pp), GPT_USER_HOME) <= 0) if (!streq_ptr(blkid_partition_get_type_string(pp), "773f91ef-66d4-49b5-bd83-d683bf40ad16"))
continue; continue;
if (!streq_ptr(blkid_partition_get_name(pp), label)) if (!streq_ptr(blkid_partition_get_name(pp), label))
@ -1763,7 +1762,7 @@ static int luks_format(
CRYPT_LUKS2, CRYPT_LUKS2,
user_record_luks_cipher(hr), user_record_luks_cipher(hr),
user_record_luks_cipher_mode(hr), user_record_luks_cipher_mode(hr),
SD_ID128_TO_UUID_STRING(uuid), ID128_TO_UUID_STRING(uuid),
volume_key, volume_key,
volume_key_size, volume_key_size,
&(struct crypt_params_luks2) { &(struct crypt_params_luks2) {
@ -1859,7 +1858,7 @@ static int make_partition_table(
if (!t) if (!t)
return log_oom(); return log_oom();
r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(GPT_USER_HOME)); r = fdisk_parttype_set_typestr(t, "773f91ef-66d4-49b5-bd83-d683bf40ad16");
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to initialize partition type: %m"); return log_error_errno(r, "Failed to initialize partition type: %m");
@ -1918,7 +1917,7 @@ static int make_partition_table(
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to set partition name: %m"); return log_error_errno(r, "Failed to set partition name: %m");
r = fdisk_partition_set_uuid(p, SD_ID128_TO_UUID_STRING(uuid)); r = fdisk_partition_set_uuid(p, ID128_TO_UUID_STRING(uuid));
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to set partition UUID: %m"); return log_error_errno(r, "Failed to set partition UUID: %m");
@ -2746,7 +2745,7 @@ static int ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *userdata
if (!result) if (!result)
return log_oom(); return log_oom();
fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) userdata, result)); fdisk_ask_string_set_result(ask, id128_to_uuid_string(*(sd_id128_t*) userdata, result));
break; break;
default: default:

View File

@ -332,9 +332,9 @@ int user_record_add_binding(
r = json_build(&new_binding_entry, r = json_build(&new_binding_entry,
JSON_BUILD_OBJECT( JSON_BUILD_OBJECT(
JSON_BUILD_PAIR_CONDITION(!!image_path, "imagePath", JSON_BUILD_STRING(image_path)), JSON_BUILD_PAIR_CONDITION(!!image_path, "imagePath", JSON_BUILD_STRING(image_path)),
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(partition_uuid), "partitionUuid", JSON_BUILD_STRING(SD_ID128_TO_UUID_STRING(partition_uuid))), JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(partition_uuid), "partitionUuid", JSON_BUILD_STRING(ID128_TO_UUID_STRING(partition_uuid))),
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(luks_uuid), "luksUuid", JSON_BUILD_STRING(SD_ID128_TO_UUID_STRING(luks_uuid))), JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(luks_uuid), "luksUuid", JSON_BUILD_STRING(ID128_TO_UUID_STRING(luks_uuid))),
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(fs_uuid), "fileSystemUuid", JSON_BUILD_STRING(SD_ID128_TO_UUID_STRING(fs_uuid))), JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(fs_uuid), "fileSystemUuid", JSON_BUILD_STRING(ID128_TO_UUID_STRING(fs_uuid))),
JSON_BUILD_PAIR_CONDITION(!!luks_cipher, "luksCipher", JSON_BUILD_STRING(luks_cipher)), JSON_BUILD_PAIR_CONDITION(!!luks_cipher, "luksCipher", JSON_BUILD_STRING(luks_cipher)),
JSON_BUILD_PAIR_CONDITION(!!luks_cipher_mode, "luksCipherMode", JSON_BUILD_STRING(luks_cipher_mode)), JSON_BUILD_PAIR_CONDITION(!!luks_cipher_mode, "luksCipherMode", JSON_BUILD_STRING(luks_cipher_mode)),
JSON_BUILD_PAIR_CONDITION(luks_volume_key_size != UINT64_MAX, "luksVolumeKeySize", JSON_BUILD_UNSIGNED(luks_volume_key_size)), JSON_BUILD_PAIR_CONDITION(luks_volume_key_size != UINT64_MAX, "luksVolumeKeySize", JSON_BUILD_UNSIGNED(luks_volume_key_size)),

View File

@ -769,8 +769,3 @@ global:
sd_event_add_inotify_fd; sd_event_add_inotify_fd;
sd_event_source_set_ratelimit_expire_callback; sd_event_source_set_ratelimit_expire_callback;
} LIBSYSTEMD_249; } LIBSYSTEMD_249;
LIBSYSTEMD_251 {
global:
sd_id128_to_uuid_string;
} LIBSYSTEMD_250;

View File

@ -23,7 +23,6 @@
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
#include "socket-util.h" #include "socket-util.h"
#include "stat-util.h"
#include "strv.h" #include "strv.h"
#include "time-util.h" #include "time-util.h"
#include "util.h" #include "util.h"
@ -151,7 +150,9 @@ _public_ int sd_is_fifo(int fd, const char *path) {
return -errno; return -errno;
} }
return stat_inode_same(&st_path, &st_fd); return
st_path.st_dev == st_fd.st_dev &&
st_path.st_ino == st_fd.st_ino;
} }
return 1; return 1;
@ -180,7 +181,9 @@ _public_ int sd_is_special(int fd, const char *path) {
} }
if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
return stat_inode_same(&st_path, &st_fd); return
st_path.st_dev == st_fd.st_dev &&
st_path.st_ino == st_fd.st_ino;
else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
return st_path.st_rdev == st_fd.st_rdev; return st_path.st_rdev == st_fd.st_rdev;
else else
@ -412,7 +415,7 @@ _public_ int sd_is_mq(int fd, const char *path) {
} }
if (path) { if (path) {
_cleanup_free_ char *fpath = NULL; char fpath[PATH_MAX];
struct stat a, b; struct stat a, b;
assert_return(path_is_absolute(path), -EINVAL); assert_return(path_is_absolute(path), -EINVAL);
@ -420,14 +423,14 @@ _public_ int sd_is_mq(int fd, const char *path) {
if (fstat(fd, &a) < 0) if (fstat(fd, &a) < 0)
return -errno; return -errno;
fpath = path_join("/dev/mqueue", path); strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
if (!fpath) fpath[sizeof(fpath)-1] = 0;
return -ENOMEM;
if (stat(fpath, &b) < 0) if (stat(fpath, &b) < 0)
return -errno; return -errno;
if (!stat_inode_same(&a, &b)) if (a.st_dev != b.st_dev ||
a.st_ino != b.st_ino)
return 0; return 0;
} }

View File

@ -24,7 +24,6 @@
#include "mountpoint-util.h" #include "mountpoint-util.h"
#include "set.h" #include "set.h"
#include "socket-util.h" #include "socket-util.h"
#include "stat-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
@ -196,7 +195,7 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
else else
log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns, ignoring: %m"); log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns, ignoring: %m");
} else if (!stat_inode_same(&a, &b)) } else if (a.st_dev != b.st_dev || a.st_ino != b.st_ino)
log_debug("sd-device-monitor: Netlink socket we listen on is not from host netns, we won't see device events."); log_debug("sd-device-monitor: Netlink socket we listen on is not from host netns, we won't see device events.");
} }
} }

View File

@ -248,10 +248,6 @@ _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum)
assert_return(ret, -EINVAL); assert_return(ret, -EINVAL);
assert_return(IN_SET(type, 'b', 'c'), -EINVAL); assert_return(IN_SET(type, 'b', 'c'), -EINVAL);
if (devnum == 0)
return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
"sd-device: Attempted to allocate device by zero major/minor, refusing.");
/* use /sys/dev/{block,char}/<maj>:<min> link */ /* use /sys/dev/{block,char}/<maj>:<min> link */
xsprintf(id, "%u:%u", major(devnum), minor(devnum)); xsprintf(id, "%u:%u", major(devnum), minor(devnum));
@ -2198,7 +2194,7 @@ _public_ int sd_device_trigger_with_uuid(
if (r < 0) if (r < 0)
return r; return r;
j = strjoina(s, " ", SD_ID128_TO_UUID_STRING(u)); j = strjoina(s, " ", ID128_TO_UUID_STRING(u));
r = sd_device_set_sysattr_value(device, "uevent", j); r = sd_device_set_sysattr_value(device, "uevent", j);
if (r < 0) if (r < 0)

View File

@ -10,7 +10,6 @@
#include "device-private.h" #include "device-private.h"
#include "device-util.h" #include "device-util.h"
#include "macro.h" #include "macro.h"
#include "stat-util.h"
#include "string-util.h" #include "string-util.h"
#include "tests.h" #include "tests.h"
#include "util.h" #include "util.h"
@ -25,10 +24,11 @@ static int monitor_handler(sd_device_monitor *m, sd_device *d, void *userdata) {
return sd_event_exit(sd_device_monitor_get_event(m), 100); return sd_event_exit(sd_device_monitor_get_event(m), 100);
} }
static void test_receive_device_fail(void) { static int test_receive_device_fail(void) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
_cleanup_(sd_device_unrefp) sd_device *loopback = NULL; _cleanup_(sd_device_unrefp) sd_device *loopback = NULL;
const char *syspath; const char *syspath;
int r;
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
@ -47,8 +47,14 @@ static void test_receive_device_fail(void) {
assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0); assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
assert_se(device_monitor_send_device(monitor_server, monitor_client, loopback) >= 0); /* Do not use assert_se() here. */
r = device_monitor_send_device(monitor_server, monitor_client, loopback);
if (r < 0)
return log_error_errno(r, "Failed to send loopback device: %m");
assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0); assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0);
return 0;
} }
static void test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) { static void test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) {
@ -293,10 +299,11 @@ int main(int argc, char *argv[]) {
if (getuid() != 0) if (getuid() != 0)
return log_tests_skipped("not root"); return log_tests_skipped("not root");
if (path_is_read_only_fs("/sys") > 0) r = test_receive_device_fail();
if (r < 0) {
assert_se(r == -EPERM && detect_container() > 0);
return log_tests_skipped("Running in container"); return log_tests_skipped("Running in container");
}
test_receive_device_fail();
assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0);
assert_se(device_add_property(loopback, "ACTION", "add") >= 0); assert_se(device_add_property(loopback, "ACTION", "add") >= 0);

View File

@ -12,6 +12,29 @@
#include "string-util.h" #include "string-util.h"
#include "sync-util.h" #include "sync-util.h"
char *id128_to_uuid_string(sd_id128_t id, char s[static ID128_UUID_STRING_MAX]) {
unsigned n, k = 0;
assert(s);
/* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
for (n = 0; n < 16; n++) {
if (IN_SET(n, 4, 6, 8, 10))
s[k++] = '-';
s[k++] = hexchar(id.bytes[n] >> 4);
s[k++] = hexchar(id.bytes[n] & 0xF);
}
assert(k == 36);
s[k] = 0;
return s;
}
bool id128_is_valid(const char *s) { bool id128_is_valid(const char *s) {
size_t i, l; size_t i, l;
@ -130,13 +153,13 @@ int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
assert(f < _ID128_FORMAT_MAX); assert(f < _ID128_FORMAT_MAX);
if (f != ID128_UUID) { if (f != ID128_UUID) {
assert_se(sd_id128_to_string(id, buffer)); sd_id128_to_string(id, buffer);
buffer[SD_ID128_STRING_MAX - 1] = '\n'; buffer[32] = '\n';
sz = SD_ID128_STRING_MAX; sz = 33;
} else { } else {
assert_se(sd_id128_to_uuid_string(id, buffer)); id128_to_uuid_string(id, buffer);
buffer[SD_ID128_UUID_STRING_MAX - 1] = '\n'; buffer[36] = '\n';
sz = SD_ID128_UUID_STRING_MAX; sz = 37;
} }
r = loop_write(fd, buffer, sz, false); r = loop_write(fd, buffer, sz, false);
@ -206,19 +229,3 @@ int id128_get_product(sd_id128_t *ret) {
*ret = uuid; *ret = uuid;
return 0; return 0;
} }
int id128_equal_string(const char *s, sd_id128_t id) {
sd_id128_t parsed;
int r;
if (!s)
return false;
/* Checks if the specified string matches a valid string representation of the specified 128 bit ID/uuid */
r = sd_id128_from_string(s, &parsed);
if (r < 0)
return r;
return sd_id128_equal(parsed, id);
}

View File

@ -8,6 +8,12 @@
#include "hash-funcs.h" #include "hash-funcs.h"
#include "macro.h" #include "macro.h"
#define ID128_UUID_STRING_MAX 37
char *id128_to_uuid_string(sd_id128_t id, char s[static ID128_UUID_STRING_MAX]);
#define ID128_TO_UUID_STRING(id) id128_to_uuid_string((id), (char[ID128_UUID_STRING_MAX]) {})
bool id128_is_valid(const char *s) _pure_; bool id128_is_valid(const char *s) _pure_;
typedef enum Id128Format { typedef enum Id128Format {
@ -34,5 +40,3 @@ extern const struct hash_ops id128_hash_ops;
sd_id128_t id128_make_v4_uuid(sd_id128_t id); sd_id128_t id128_make_v4_uuid(sd_id128_t id);
int id128_get_product(sd_id128_t *ret); int id128_get_product(sd_id128_t *ret);
int id128_equal_string(const char *s, sd_id128_t id);

View File

@ -19,36 +19,16 @@
#include "util.h" #include "util.h"
_public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) { _public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) {
unsigned n;
assert_return(s, NULL); assert_return(s, NULL);
for (size_t n = 0; n < 16; n++) { for (n = 0; n < 16; n++) {
s[n*2] = hexchar(id.bytes[n] >> 4); s[n*2] = hexchar(id.bytes[n] >> 4);
s[n*2+1] = hexchar(id.bytes[n] & 0xF); s[n*2+1] = hexchar(id.bytes[n] & 0xF);
} }
s[SD_ID128_STRING_MAX-1] = 0; s[32] = 0;
return s;
}
_public_ char *sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_UUID_STRING_MAX]) {
size_t k = 0;
assert_return(s, NULL);
/* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
for (size_t n = 0; n < 16; n++) {
if (IN_SET(n, 4, 6, 8, 10))
s[k++] = '-';
s[k++] = hexchar(id.bytes[n] >> 4);
s[k++] = hexchar(id.bytes[n] & 0xF);
}
assert(k == SD_ID128_UUID_STRING_MAX - 1);
s[k] = 0;
return s; return s;
} }

View File

@ -1317,7 +1317,8 @@ static int add_any_file(
f = ordered_hashmap_get(j->files, path); f = ordered_hashmap_get(j->files, path);
if (f) { if (f) {
if (stat_inode_same(&f->last_stat, &st)) { if (f->last_stat.st_dev == st.st_dev &&
f->last_stat.st_ino == st.st_ino) {
/* We already track this file, under the same path and with the same device/inode numbers, it's /* We already track this file, under the same path and with the same device/inode numbers, it's
* hence really the same. Mark this file as seen in this generation. This is used to GC old * hence really the same. Mark this file as seen in this generation. This is used to GC old

View File

@ -20,99 +20,101 @@
static const ActionTableItem action_table[_HANDLE_ACTION_MAX] = { static const ActionTableItem action_table[_HANDLE_ACTION_MAX] = {
[HANDLE_POWEROFF] = { [HANDLE_POWEROFF] = {
.handle = HANDLE_POWEROFF, SPECIAL_POWEROFF_TARGET,
.target = SPECIAL_POWEROFF_TARGET, INHIBIT_SHUTDOWN,
.inhibit_what = INHIBIT_SHUTDOWN, "org.freedesktop.login1.power-off",
.polkit_action = "org.freedesktop.login1.power-off", "org.freedesktop.login1.power-off-multiple-sessions",
.polkit_action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions", "org.freedesktop.login1.power-off-ignore-inhibit",
.polkit_action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit", _SLEEP_OPERATION_INVALID,
.sleep_operation = _SLEEP_OPERATION_INVALID, SD_MESSAGE_SHUTDOWN_STR,
.message_id = SD_MESSAGE_SHUTDOWN_STR, "System is powering down",
.message = "System is powering down", "power-off",
.log_message = "power-off", },
},
[HANDLE_REBOOT] = { [HANDLE_REBOOT] = {
.handle = HANDLE_REBOOT, SPECIAL_REBOOT_TARGET,
.target = SPECIAL_REBOOT_TARGET, INHIBIT_SHUTDOWN,
.inhibit_what = INHIBIT_SHUTDOWN, "org.freedesktop.login1.reboot",
.polkit_action = "org.freedesktop.login1.reboot", "org.freedesktop.login1.reboot-multiple-sessions",
.polkit_action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions", "org.freedesktop.login1.reboot-ignore-inhibit",
.polkit_action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit", _SLEEP_OPERATION_INVALID,
.sleep_operation = _SLEEP_OPERATION_INVALID, SD_MESSAGE_SHUTDOWN_STR,
.message_id = SD_MESSAGE_SHUTDOWN_STR, "System is rebooting",
.message = "System is rebooting", "reboot",
.log_message = "reboot", },
}, [HANDLE_HALT] = {
[HANDLE_HALT] = { SPECIAL_HALT_TARGET,
.handle = HANDLE_HALT, INHIBIT_SHUTDOWN,
.target = SPECIAL_HALT_TARGET, "org.freedesktop.login1.halt",
.inhibit_what = INHIBIT_SHUTDOWN, "org.freedesktop.login1.halt-multiple-sessions",
.polkit_action = "org.freedesktop.login1.halt", "org.freedesktop.login1.halt-ignore-inhibit",
.polkit_action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions", _SLEEP_OPERATION_INVALID,
.polkit_action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit", SD_MESSAGE_SHUTDOWN_STR,
.sleep_operation = _SLEEP_OPERATION_INVALID, "System is halting",
.message_id = SD_MESSAGE_SHUTDOWN_STR, "halt",
.message = "System is halting", },
.log_message = "halt", [HANDLE_KEXEC] = {
}, SPECIAL_KEXEC_TARGET,
[HANDLE_KEXEC] = { INHIBIT_SHUTDOWN,
.handle = HANDLE_KEXEC, "org.freedesktop.login1.reboot",
.target = SPECIAL_KEXEC_TARGET, "org.freedesktop.login1.reboot-multiple-sessions",
.inhibit_what = INHIBIT_SHUTDOWN, "org.freedesktop.login1.reboot-ignore-inhibit",
.polkit_action = "org.freedesktop.login1.reboot", _SLEEP_OPERATION_INVALID,
.polkit_action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions", SD_MESSAGE_SHUTDOWN_STR,
.polkit_action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit", "System is rebooting with kexec",
.sleep_operation = _SLEEP_OPERATION_INVALID, "kexec",
.message_id = SD_MESSAGE_SHUTDOWN_STR, },
.message = "System is rebooting with kexec", [HANDLE_SUSPEND] = {
.log_message = "kexec", SPECIAL_SUSPEND_TARGET,
}, INHIBIT_SLEEP,
[HANDLE_SUSPEND] = { "org.freedesktop.login1.suspend",
.handle = HANDLE_SUSPEND, "org.freedesktop.login1.suspend-multiple-sessions",
.target = SPECIAL_SUSPEND_TARGET, "org.freedesktop.login1.suspend-ignore-inhibit",
.inhibit_what = INHIBIT_SLEEP, SLEEP_SUSPEND,
.polkit_action = "org.freedesktop.login1.suspend", },
.polkit_action_multiple_sessions = "org.freedesktop.login1.suspend-multiple-sessions", [HANDLE_HIBERNATE] = {
.polkit_action_ignore_inhibit = "org.freedesktop.login1.suspend-ignore-inhibit", SPECIAL_HIBERNATE_TARGET,
.sleep_operation = SLEEP_SUSPEND, INHIBIT_SLEEP,
}, "org.freedesktop.login1.hibernate",
[HANDLE_HIBERNATE] = { "org.freedesktop.login1.hibernate-multiple-sessions",
.handle = HANDLE_HIBERNATE, "org.freedesktop.login1.hibernate-ignore-inhibit",
.target = SPECIAL_HIBERNATE_TARGET, SLEEP_HIBERNATE,
.inhibit_what = INHIBIT_SLEEP, },
.polkit_action = "org.freedesktop.login1.hibernate", [HANDLE_HYBRID_SLEEP] = {
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions", SPECIAL_HYBRID_SLEEP_TARGET,
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit", INHIBIT_SLEEP,
.sleep_operation = SLEEP_HIBERNATE, "org.freedesktop.login1.hibernate",
}, "org.freedesktop.login1.hibernate-multiple-sessions",
[HANDLE_HYBRID_SLEEP] = { "org.freedesktop.login1.hibernate-ignore-inhibit",
.handle = HANDLE_HYBRID_SLEEP, SLEEP_HYBRID_SLEEP,
.target = SPECIAL_HYBRID_SLEEP_TARGET, },
.inhibit_what = INHIBIT_SLEEP, [HANDLE_SUSPEND_THEN_HIBERNATE] = {
.polkit_action = "org.freedesktop.login1.hibernate", SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions", INHIBIT_SLEEP,
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit", "org.freedesktop.login1.hibernate",
.sleep_operation = SLEEP_HYBRID_SLEEP, "org.freedesktop.login1.hibernate-multiple-sessions",
}, "org.freedesktop.login1.hibernate-ignore-inhibit",
[HANDLE_SUSPEND_THEN_HIBERNATE] = { SLEEP_SUSPEND_THEN_HIBERNATE,
.handle = HANDLE_SUSPEND_THEN_HIBERNATE, },
.target = SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, [HANDLE_FACTORY_RESET] = {
.inhibit_what = INHIBIT_SLEEP, SPECIAL_FACTORY_RESET_TARGET,
.polkit_action = "org.freedesktop.login1.hibernate", _INHIBIT_WHAT_INVALID,
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions", NULL,
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit", NULL,
.sleep_operation = SLEEP_SUSPEND_THEN_HIBERNATE, NULL,
}, _SLEEP_OPERATION_INVALID,
[HANDLE_FACTORY_RESET] = { SD_MESSAGE_FACTORY_RESET_STR,
.handle = HANDLE_FACTORY_RESET, "System is performing factory reset",
.target = SPECIAL_FACTORY_RESET_TARGET, NULL
.inhibit_what = _INHIBIT_WHAT_INVALID, },
.sleep_operation = _SLEEP_OPERATION_INVALID,
.message_id = SD_MESSAGE_FACTORY_RESET_STR,
.message = "System is performing factory reset",
},
}; };
const char* manager_target_for_action(HandleAction handle) {
assert(handle >= 0);
assert(handle < (ssize_t) ELEMENTSOF(action_table));
return action_table[handle].target;
}
const ActionTableItem* manager_item_for_handle(HandleAction handle) { const ActionTableItem* manager_item_for_handle(HandleAction handle) {
assert(handle >= 0); assert(handle >= 0);
assert(handle < (ssize_t) ELEMENTSOF(action_table)); assert(handle < (ssize_t) ELEMENTSOF(action_table));
@ -120,6 +122,12 @@ const ActionTableItem* manager_item_for_handle(HandleAction handle) {
return &action_table[handle]; return &action_table[handle];
} }
HandleAction manager_handle_for_item(const ActionTableItem* a) {
if (a && a < action_table + ELEMENTSOF(action_table))
return a - action_table;
return _HANDLE_ACTION_INVALID;
}
int manager_handle_action( int manager_handle_action(
Manager *m, Manager *m,
InhibitWhat inhibit_key, InhibitWhat inhibit_key,

View File

@ -28,7 +28,6 @@ typedef struct ActionTableItem ActionTableItem;
#include "sleep-config.h" #include "sleep-config.h"
struct ActionTableItem { struct ActionTableItem {
HandleAction handle;
const char *target; const char *target;
InhibitWhat inhibit_what; InhibitWhat inhibit_what;
const char *polkit_action; const char *polkit_action;
@ -37,7 +36,8 @@ struct ActionTableItem {
SleepOperation sleep_operation; SleepOperation sleep_operation;
const char* message_id; const char* message_id;
const char* message; const char* message;
const char* log_message; const char* log_str;
}; };
int manager_handle_action( int manager_handle_action(
@ -50,6 +50,7 @@ int manager_handle_action(
const char* handle_action_to_string(HandleAction h) _const_; const char* handle_action_to_string(HandleAction h) _const_;
HandleAction handle_action_from_string(const char *s) _pure_; HandleAction handle_action_from_string(const char *s) _pure_;
const char* manager_target_for_action(HandleAction handle);
const ActionTableItem* manager_item_for_handle(HandleAction handle); const ActionTableItem* manager_item_for_handle(HandleAction handle);
HandleAction manager_handle_for_item(const ActionTableItem* a); HandleAction manager_handle_for_item(const ActionTableItem* a);

View File

@ -54,15 +54,6 @@
#include "utmp-wtmp.h" #include "utmp-wtmp.h"
#include "virt.h" #include "virt.h"
/* As a random fun fact sysvinit had a 252 (256-(strlen(" \r\n")+1))
* character limit for the wall message.
* https://git.savannah.nongnu.org/cgit/sysvinit.git/tree/src/shutdown.c#n72
* There is no real technical need for that but doesn't make sense
* to store arbitrary amounts either. As we are not stingy here, we
* allow 4k.
*/
#define WALL_MESSAGE_MAX 4096
static void reset_scheduled_shutdown(Manager *m); static void reset_scheduled_shutdown(Manager *m);
static int get_sender_session( static int get_sender_session(
@ -358,7 +349,7 @@ static int property_get_scheduled_shutdown(
return r; return r;
r = sd_bus_message_append(reply, "st", r = sd_bus_message_append(reply, "st",
m->scheduled_shutdown_type ? handle_action_to_string(m->scheduled_shutdown_type->handle) : NULL, handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)),
m->scheduled_shutdown_timeout); m->scheduled_shutdown_timeout);
if (r < 0) if (r < 0)
return r; return r;
@ -1508,13 +1499,13 @@ static int bus_manager_log_shutdown(
Manager *m, Manager *m,
const ActionTableItem *a) { const ActionTableItem *a) {
const char *message, *log_message; const char *message, *log_str;
assert(m); assert(m);
assert(a); assert(a);
message = a->message; message = a->message;
log_message = a->log_message; log_str = a->log_str;
if (message) if (message)
message = strjoina("MESSAGE=", message); message = strjoina("MESSAGE=", message);
@ -1526,13 +1517,13 @@ static int bus_manager_log_shutdown(
else else
message = strjoina(message, " (", m->wall_message, ")."); message = strjoina(message, " (", m->wall_message, ").");
if (log_message) if (log_str)
log_message = strjoina("SHUTDOWN=", log_message); log_str = strjoina("SHUTDOWN=", log_str);
return log_struct(LOG_NOTICE, return log_struct(LOG_NOTICE,
"MESSAGE_ID=%s", a->message_id ? a->message_id : SD_MESSAGE_SHUTDOWN_STR, "MESSAGE_ID=%s", a->message_id ? a->message_id : SD_MESSAGE_SHUTDOWN_STR,
message, message,
log_message); log_str);
} }
static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) { static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
@ -1893,7 +1884,7 @@ static int method_do_shutdown_or_sleep(
return r; return r;
if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0) if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter"); return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
if (a->handle != HANDLE_REBOOT && (flags & SD_LOGIND_REBOOT_VIA_KEXEC)) if (manager_handle_for_item(a) != HANDLE_REBOOT && (flags & SD_LOGIND_REBOOT_VIA_KEXEC))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Reboot via kexec is only applicable with reboot operations"); return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Reboot via kexec is only applicable with reboot operations");
} else { } else {
/* Old style method: no flags parameter, but interactive bool passed as boolean in /* Old style method: no flags parameter, but interactive bool passed as boolean in
@ -2044,7 +2035,6 @@ static int update_schedule_file(Manager *m) {
int r; int r;
assert(m); assert(m);
assert(m->scheduled_shutdown_type);
r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE); r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
if (r < 0) if (r < 0)
@ -2062,7 +2052,7 @@ static int update_schedule_file(Manager *m) {
"MODE=%s\n", "MODE=%s\n",
m->scheduled_shutdown_timeout, m->scheduled_shutdown_timeout,
m->enable_wall_messages, m->enable_wall_messages,
handle_action_to_string(m->scheduled_shutdown_type->handle)); handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)));
if (!isempty(m->wall_message)) { if (!isempty(m->wall_message)) {
_cleanup_free_ char *t = NULL; _cleanup_free_ char *t = NULL;
@ -2250,10 +2240,9 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
assert(m); assert(m);
assert(message); assert(message);
cancelled = m->scheduled_shutdown_type cancelled = !IN_SET(manager_handle_for_item(m->scheduled_shutdown_type), HANDLE_IGNORE, _HANDLE_ACTION_INVALID);
&& !IN_SET(m->scheduled_shutdown_type->handle, HANDLE_IGNORE, _HANDLE_ACTION_INVALID);
if (!cancelled) if (!cancelled)
return sd_bus_reply_method_return(message, "b", false); goto done;
a = m->scheduled_shutdown_type; a = m->scheduled_shutdown_type;
if (!a->polkit_action) if (!a->polkit_action)
@ -2292,7 +2281,8 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
username, tty, logind_wall_tty_filter, m); username, tty, logind_wall_tty_filter, m);
} }
return sd_bus_reply_method_return(message, "b", true); done:
return sd_bus_reply_method_return(message, "b", cancelled);
} }
static int method_can_shutdown_or_sleep( static int method_can_shutdown_or_sleep(
@ -2338,7 +2328,7 @@ static int method_can_shutdown_or_sleep(
if (handle >= 0) { if (handle >= 0) {
const char *target; const char *target;
target = manager_item_for_handle(handle)->target; target = manager_target_for_action(handle);
if (target) { if (target) {
_cleanup_free_ char *load_state = NULL; _cleanup_free_ char *load_state = NULL;
@ -2933,9 +2923,9 @@ static int boot_loader_entry_exists(Manager *m, const char *id) {
r = manager_read_efi_boot_loader_entries(m); r = manager_read_efi_boot_loader_entries(m);
if (r >= 0) if (r >= 0)
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, /* auto_only= */ true); (void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries);
return !!boot_config_find_entry(&config, id); return boot_config_has_entry(&config, id);
} }
static int method_set_reboot_to_boot_loader_entry( static int method_set_reboot_to_boot_loader_entry(
@ -3091,7 +3081,7 @@ static int property_get_boot_loader_entries(
r = manager_read_efi_boot_loader_entries(m); r = manager_read_efi_boot_loader_entries(m);
if (r >= 0) if (r >= 0)
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, /* auto_only= */ true); (void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries);
r = sd_bus_message_open_container(reply, 'a', "s"); r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0) if (r < 0)
@ -3125,10 +3115,14 @@ static int method_set_wall_message(
if (r < 0) if (r < 0)
return r; return r;
if (strlen(wall_message) > WALL_MESSAGE_MAX) /* sysvinit has a 252 (256-(strlen(" \r\n")+1)) character
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, * limit for the wall message. There is no real technical
"Wall message too long, maximum permitted length is %u characters.", * need for that but doesn't make sense to store arbitrary
WALL_MESSAGE_MAX); * amounts either.
* https://git.savannah.nongnu.org/cgit/sysvinit.git/tree/src/shutdown.c#n72)
*/
if (strlen(wall_message) > 252)
return -EMSGSIZE;
/* Short-circuit the operation if the desired state is already in place, to /* Short-circuit the operation if the desired state is already in place, to
* avoid an unnecessary polkit permission check. */ * avoid an unnecessary polkit permission check. */

View File

@ -64,7 +64,7 @@ static int warn_wall(Manager *m, usec_t n) {
assert(m); assert(m);
if (!m->enable_wall_messages || !m->scheduled_shutdown_type) if (!m->enable_wall_messages)
return 0; return 0;
left = m->scheduled_shutdown_timeout > n; left = m->scheduled_shutdown_timeout > n;
@ -72,7 +72,7 @@ static int warn_wall(Manager *m, usec_t n) {
r = asprintf(&l, "%s%sThe system is going down for %s %s%s!", r = asprintf(&l, "%s%sThe system is going down for %s %s%s!",
strempty(m->wall_message), strempty(m->wall_message),
isempty(m->wall_message) ? "" : "\n", isempty(m->wall_message) ? "" : "\n",
handle_action_to_string(m->scheduled_shutdown_type->handle), handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)),
left ? "at " : "NOW", left ? "at " : "NOW",
left ? FORMAT_TIMESTAMP(m->scheduled_shutdown_timeout) : ""); left ? FORMAT_TIMESTAMP(m->scheduled_shutdown_timeout) : "");
if (r < 0) { if (r < 0) {

View File

@ -848,6 +848,10 @@ int link_drop_foreign_addresses(Link *link) {
assert(link); assert(link);
assert(link->network); assert(link->network);
/* Keep all addresses when KeepConfiguration=yes. */
if (link->network->keep_configuration == KEEP_CONFIGURATION_YES)
return 0;
/* First, mark all addresses. */ /* First, mark all addresses. */
SET_FOREACH(address, link->addresses) { SET_FOREACH(address, link->addresses) {
/* We consider IPv6LL addresses to be managed by the kernel, or dropped in link_drop_ipv6ll_addresses() */ /* We consider IPv6LL addresses to be managed by the kernel, or dropped in link_drop_ipv6ll_addresses() */

View File

@ -1240,13 +1240,10 @@ static int link_reconfigure_impl(Link *link, bool force) {
link_drop_requests(link); link_drop_requests(link);
if (network && !force && network->keep_configuration != KEEP_CONFIGURATION_YES) if (network && !force)
/* When a new/updated .network file is assigned, first make all configs (addresses, /* When a new/updated .network file is assigned, first make all configs (addresses,
* routes, and so on) foreign, and then drop unnecessary configs later by * routes, and so on) foreign, and then drop unnecessary configs later by
* link_drop_foreign_config() in link_configure(). * link_drop_foreign_config() in link_configure(). */
* Note, when KeepConfiguration=yes, link_drop_foreign_config() does nothing. Hence,
* here we need to drop the configs such as addresses, routes, and so on configured by
* the previously assigned .network file. */
link_foreignize_config(link); link_foreignize_config(link);
else { else {
/* Remove all managed configs. Note, foreign configs are removed in later by /* Remove all managed configs. Note, foreign configs are removed in later by

View File

@ -3453,7 +3453,7 @@ static int inner_child(
assert(!sd_id128_is_null(arg_uuid)); assert(!sd_id128_is_null(arg_uuid));
if (asprintf(envp + n_env++, "container_uuid=%s", SD_ID128_TO_UUID_STRING(arg_uuid)) < 0) if (asprintf(envp + n_env++, "container_uuid=%s", ID128_TO_UUID_STRING(arg_uuid)) < 0)
return log_oom(); return log_oom();
if (fdset_size(fds) > 0) { if (fdset_size(fds) > 0) {

View File

@ -1512,11 +1512,11 @@ static int fdisk_ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *da
if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_STRING) if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_STRING)
return -EINVAL; return -EINVAL;
ids = new(char, SD_ID128_UUID_STRING_MAX); ids = new(char, ID128_UUID_STRING_MAX);
if (!ids) if (!ids)
return -ENOMEM; return -ENOMEM;
r = fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) data, ids)); r = fdisk_ask_string_set_result(ask, id128_to_uuid_string(*(sd_id128_t*) data, ids));
if (r < 0) if (r < 0)
return r; return r;
@ -2030,7 +2030,7 @@ static int context_dump_partitions(Context *context, const char *node) {
LIST_FOREACH(partitions, p, context->partitions) { LIST_FOREACH(partitions, p, context->partitions) {
_cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL; _cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL;
char uuid_buffer[SD_ID128_UUID_STRING_MAX]; char uuid_buffer[ID128_UUID_STRING_MAX];
const char *label, *activity = NULL; const char *label, *activity = NULL;
if (p->dropped) if (p->dropped)
@ -2176,7 +2176,7 @@ static int partition_hint(const Partition *p, const char *node, char **ret) {
else else
id = p->type_uuid; id = p->type_uuid;
buf = strdup(SD_ID128_TO_UUID_STRING(id)); buf = strdup(ID128_TO_UUID_STRING(id));
done: done:
if (!buf) if (!buf)
@ -2624,7 +2624,7 @@ static int partition_encrypt(
CRYPT_LUKS2, CRYPT_LUKS2,
"aes", "aes",
"xts-plain64", "xts-plain64",
SD_ID128_TO_UUID_STRING(uuid), ID128_TO_UUID_STRING(uuid),
volume_key, volume_key,
volume_key_size, volume_key_size,
&(struct crypt_params_luks2) { &(struct crypt_params_luks2) {
@ -3304,7 +3304,7 @@ static uint64_t partition_merge_flags(Partition *p) {
if (gpt_partition_type_knows_no_auto(p->type_uuid)) if (gpt_partition_type_knows_no_auto(p->type_uuid))
SET_FLAG(f, GPT_FLAG_NO_AUTO, p->no_auto); SET_FLAG(f, GPT_FLAG_NO_AUTO, p->no_auto);
else { else {
char buffer[SD_ID128_UUID_STRING_MAX]; char buffer[ID128_UUID_STRING_MAX];
log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.", log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.",
yes_no(p->no_auto), yes_no(p->no_auto),
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer)); gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
@ -3315,7 +3315,7 @@ static uint64_t partition_merge_flags(Partition *p) {
if (gpt_partition_type_knows_read_only(p->type_uuid)) if (gpt_partition_type_knows_read_only(p->type_uuid))
SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only); SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
else { else {
char buffer[SD_ID128_UUID_STRING_MAX]; char buffer[ID128_UUID_STRING_MAX];
log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.", log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
yes_no(p->read_only), yes_no(p->read_only),
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer)); gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
@ -3326,7 +3326,7 @@ static uint64_t partition_merge_flags(Partition *p) {
if (gpt_partition_type_knows_growfs(p->type_uuid)) if (gpt_partition_type_knows_growfs(p->type_uuid))
SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs); SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs);
else { else {
char buffer[SD_ID128_UUID_STRING_MAX]; char buffer[ID128_UUID_STRING_MAX];
log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.", log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
yes_no(p->growfs), yes_no(p->growfs),
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer)); gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
@ -3374,7 +3374,7 @@ static int context_mangle_partitions(Context *context) {
if (!sd_id128_equal(p->new_uuid, p->current_uuid)) { if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
assert(!sd_id128_is_null(p->new_uuid)); assert(!sd_id128_is_null(p->new_uuid));
r = fdisk_partition_set_uuid(p->current_partition, SD_ID128_TO_UUID_STRING(p->new_uuid)); r = fdisk_partition_set_uuid(p->current_partition, ID128_TO_UUID_STRING(p->new_uuid));
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to set partition UUID: %m"); return log_error_errno(r, "Failed to set partition UUID: %m");
@ -3412,7 +3412,7 @@ static int context_mangle_partitions(Context *context) {
if (!t) if (!t)
return log_oom(); return log_oom();
r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type_uuid)); r = fdisk_parttype_set_typestr(t, ID128_TO_UUID_STRING(p->type_uuid));
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to initialize partition type: %m"); return log_error_errno(r, "Failed to initialize partition type: %m");
@ -3440,7 +3440,7 @@ static int context_mangle_partitions(Context *context) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to set partition number: %m"); return log_error_errno(r, "Failed to set partition number: %m");
r = fdisk_partition_set_uuid(q, SD_ID128_TO_UUID_STRING(p->new_uuid)); r = fdisk_partition_set_uuid(q, ID128_TO_UUID_STRING(p->new_uuid));
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to set partition UUID: %m"); return log_error_errno(r, "Failed to set partition UUID: %m");

View File

@ -41,7 +41,8 @@ int manager_check_resolv_conf(const Manager *m) {
/* Is it symlinked to our own uplink file? */ /* Is it symlinked to our own uplink file? */
if (stat(PRIVATE_STATIC_RESOLV_CONF, &own) >= 0 && if (stat(PRIVATE_STATIC_RESOLV_CONF, &own) >= 0 &&
stat_inode_same(&st, &own)) st.st_dev == own.st_dev &&
st.st_ino == own.st_ino)
return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to " "DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to "
PRIVATE_STATIC_RESOLV_CONF " which expects DNSStubListener= to be enabled."); PRIVATE_STATIC_RESOLV_CONF " which expects DNSStubListener= to be enabled.");
@ -63,7 +64,8 @@ static bool file_is_our_own(const struct stat *st) {
/* Is it symlinked to our own uplink file? */ /* Is it symlinked to our own uplink file? */
if (stat(path, &own) >= 0 && if (stat(path, &own) >= 0 &&
stat_inode_same(st, &own)) st->st_dev == own.st_dev &&
st->st_ino == own.st_ino)
return true; return true;
} }
@ -416,7 +418,8 @@ int resolv_conf_mode(void) {
continue; continue;
} }
if (stat_inode_same(&system_st, &our_st)) if (system_st.st_dev == our_st.st_dev &&
system_st.st_ino == our_st.st_ino)
return m; return m;
} }

View File

@ -22,8 +22,6 @@
#include "errno-util.h" #include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "gpt.h"
#include "id128-util.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "pe-header.h" #include "pe-header.h"
@ -53,7 +51,6 @@ static void boot_entry_free(BootEntry *entry) {
free(entry->efi); free(entry->efi);
strv_free(entry->initrd); strv_free(entry->initrd);
free(entry->device_tree); free(entry->device_tree);
strv_free(entry->device_tree_overlay);
} }
static int boot_entry_load( static int boot_entry_load(
@ -67,28 +64,26 @@ static int boot_entry_load(
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
unsigned line = 1; unsigned line = 1;
char *c; char *b, *c;
int r; int r;
assert(root); assert(root);
assert(path); assert(path);
assert(entry); assert(entry);
r = path_extract_filename(path, &tmp.id); c = endswith_no_case(path, ".conf");
if (r < 0)
return log_error_errno(r, "Failed to extract file name from path '%s': %m", path);
c = endswith_no_case(tmp.id, ".conf");
if (!c) if (!c)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", tmp.id); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", path);
b = basename(path);
tmp.id = strdup(b);
tmp.id_old = strndup(b, c - b);
if (!tmp.id || !tmp.id_old)
return log_oom();
if (!efi_loader_entry_name_valid(tmp.id)) if (!efi_loader_entry_name_valid(tmp.id))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry name: %s", tmp.id); return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry name: %s", tmp.id);
tmp.id_old = strndup(tmp.id, c - tmp.id);
if (!tmp.id_old)
return log_oom();
tmp.path = strdup(path); tmp.path = strdup(path);
if (!tmp.path) if (!tmp.path)
return log_oom(); return log_oom();
@ -147,15 +142,7 @@ static int boot_entry_load(
r = strv_extend(&tmp.initrd, p); r = strv_extend(&tmp.initrd, p);
else if (streq(field, "devicetree")) else if (streq(field, "devicetree"))
r = free_and_strdup(&tmp.device_tree, p); r = free_and_strdup(&tmp.device_tree, p);
else if (streq(field, "devicetree-overlay")) { else {
_cleanup_strv_free_ char **l = NULL;
l = strv_split(p, NULL);
if (!l)
return log_oom();
r = strv_extend_strv(&tmp.device_tree_overlay, l, false);
} else {
log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field); log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field);
continue; continue;
} }
@ -180,11 +167,9 @@ void boot_config_free(BootConfig *config) {
free(config->auto_firmware); free(config->auto_firmware);
free(config->console_mode); free(config->console_mode);
free(config->random_seed_mode); free(config->random_seed_mode);
free(config->beep);
free(config->entry_oneshot); free(config->entry_oneshot);
free(config->entry_default); free(config->entry_default);
free(config->entry_selected);
for (i = 0; i < config->n_entries; i++) for (i = 0; i < config->n_entries; i++)
boot_entry_free(config->entries + i); boot_entry_free(config->entries + i);
@ -249,8 +234,6 @@ static int boot_loader_read_conf(const char *path, BootConfig *config) {
r = free_and_strdup(&config->console_mode, p); r = free_and_strdup(&config->console_mode, p);
else if (streq(field, "random-seed-mode")) else if (streq(field, "random-seed-mode"))
r = free_and_strdup(&config->random_seed_mode, p); r = free_and_strdup(&config->random_seed_mode, p);
else if (streq(field, "beep"))
r = free_and_strdup(&config->beep, p);
else { else {
log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field); log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field);
continue; continue;
@ -563,17 +546,18 @@ static int boot_entries_find_unified(
return 0; return 0;
} }
static bool find_nonunique(const BootEntry *entries, size_t n_entries, bool arr[]) { static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) {
size_t i, j;
bool non_unique = false; bool non_unique = false;
assert(entries || n_entries == 0); assert(entries || n_entries == 0);
assert(arr || n_entries == 0); assert(arr || n_entries == 0);
for (size_t i = 0; i < n_entries; i++) for (i = 0; i < n_entries; i++)
arr[i] = false; arr[i] = false;
for (size_t i = 0; i < n_entries; i++) for (i = 0; i < n_entries; i++)
for (size_t j = 0; j < n_entries; j++) for (j = 0; j < n_entries; j++)
if (i != j && streq(boot_entry_title(entries + i), if (i != j && streq(boot_entry_title(entries + i),
boot_entry_title(entries + j))) boot_entry_title(entries + j)))
non_unique = arr[i] = arr[j] = true; non_unique = arr[i] = arr[j] = true;
@ -582,26 +566,22 @@ static bool find_nonunique(const BootEntry *entries, size_t n_entries, bool arr[
} }
static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) { static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
_cleanup_free_ bool *arr = NULL;
char *s; char *s;
size_t i;
int r;
bool arr[n_entries];
assert(entries || n_entries == 0); assert(entries || n_entries == 0);
if (n_entries == 0)
return 0;
arr = new(bool, n_entries);
if (!arr)
return -ENOMEM;
/* Find _all_ non-unique titles */ /* Find _all_ non-unique titles */
if (!find_nonunique(entries, n_entries, arr)) if (!find_nonunique(entries, n_entries, arr))
return 0; return 0;
/* Add version to non-unique titles */ /* Add version to non-unique titles */
for (size_t i = 0; i < n_entries; i++) for (i = 0; i < n_entries; i++)
if (arr[i] && entries[i].version) { if (arr[i] && entries[i].version) {
if (asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version) < 0) r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version);
if (r < 0)
return -ENOMEM; return -ENOMEM;
free_and_replace(entries[i].show_title, s); free_and_replace(entries[i].show_title, s);
@ -611,9 +591,10 @@ static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
return 0; return 0;
/* Add machine-id to non-unique titles */ /* Add machine-id to non-unique titles */
for (size_t i = 0; i < n_entries; i++) for (i = 0; i < n_entries; i++)
if (arr[i] && entries[i].machine_id) { if (arr[i] && entries[i].machine_id) {
if (asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id) < 0) r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id);
if (r < 0)
return -ENOMEM; return -ENOMEM;
free_and_replace(entries[i].show_title, s); free_and_replace(entries[i].show_title, s);
@ -623,9 +604,10 @@ static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
return 0; return 0;
/* Add file name to non-unique titles */ /* Add file name to non-unique titles */
for (size_t i = 0; i < n_entries; i++) for (i = 0; i < n_entries; i++)
if (arr[i]) { if (arr[i]) {
if (asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].id) < 0) r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].id);
if (r < 0)
return -ENOMEM; return -ENOMEM;
free_and_replace(entries[i].show_title, s); free_and_replace(entries[i].show_title, s);
@ -673,55 +655,6 @@ static int boot_entries_select_default(const BootConfig *config) {
return config->n_entries - 1; return config->n_entries - 1;
} }
static int boot_entries_select_selected(const BootConfig *config) {
assert(config);
assert(config->entries || config->n_entries == 0);
if (!config->entry_selected || config->n_entries == 0)
return -1;
for (int i = config->n_entries - 1; i >= 0; i--)
if (streq(config->entry_selected, config->entries[i].id))
return i;
return -1;
}
static int boot_load_efi_entry_pointers(BootConfig *config) {
int r;
assert(config);
if (!is_efi_boot())
return 0;
/* Loads the three "pointers" to boot loader entries from their EFI variables */
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryOneShot), &config->entry_oneshot);
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m");
if (r == -ENOMEM)
return r;
}
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryDefault), &config->entry_default);
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m");
if (r == -ENOMEM)
return r;
}
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntrySelected), &config->entry_selected);
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntrySelected\": %m");
if (r == -ENOMEM)
return r;
}
return 1;
}
int boot_entries_load_config( int boot_entries_load_config(
const char *esp_path, const char *esp_path,
const char *xbootldr_path, const char *xbootldr_path,
@ -767,13 +700,23 @@ int boot_entries_load_config(
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to uniquify boot entries: %m"); return log_error_errno(r, "Failed to uniquify boot entries: %m");
r = boot_load_efi_entry_pointers(config); if (is_efi_boot()) {
if (r < 0) r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryOneShot), &config->entry_oneshot);
return r; if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m");
if (r == -ENOMEM)
return r;
}
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryDefault), &config->entry_default);
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m");
if (r == -ENOMEM)
return r;
}
}
config->default_entry = boot_entries_select_default(config); config->default_entry = boot_entries_select_default(config);
config->selected_entry = boot_entries_select_selected(config);
return 0; return 0;
} }
@ -783,7 +726,6 @@ int boot_entries_load_config_auto(
BootConfig *config) { BootConfig *config) {
_cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL; _cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL;
dev_t esp_devid = 0, xbootldr_devid = 0;
int r; int r;
assert(config); assert(config);
@ -804,25 +746,20 @@ int boot_entries_load_config_auto(
"Failed to determine whether /run/boot-loader-entries/ exists: %m"); "Failed to determine whether /run/boot-loader-entries/ exists: %m");
} }
r = find_esp_and_warn(override_esp_path, /* unprivileged_mode= */ false, &esp_where, NULL, NULL, NULL, NULL, &esp_devid); r = find_esp_and_warn(override_esp_path, false, &esp_where, NULL, NULL, NULL, NULL);
if (r < 0) /* we don't log about ENOKEY here, but propagate it, leaving it to the caller to log */ if (r < 0) /* we don't log about ENOKEY here, but propagate it, leaving it to the caller to log */
return r; return r;
r = find_xbootldr_and_warn(override_xbootldr_path, /* unprivileged_mode= */ false, &xbootldr_where, NULL, &xbootldr_devid); r = find_xbootldr_and_warn(override_xbootldr_path, false, &xbootldr_where, NULL);
if (r < 0 && r != -ENOKEY) if (r < 0 && r != -ENOKEY)
return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */ return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */
/* If both paths actually refer to the same inode, suppress the xbootldr path */
if (esp_where && xbootldr_where && devid_set_and_equal(esp_devid, xbootldr_devid))
xbootldr_where = mfree(xbootldr_where);
return boot_entries_load_config(esp_where, xbootldr_where, config); return boot_entries_load_config(esp_where, xbootldr_where, config);
} }
int boot_entries_augment_from_loader( int boot_entries_augment_from_loader(
BootConfig *config, BootConfig *config,
char **found_by_loader, char **found_by_loader) {
bool only_auto) {
static const char *const title_table[] = { static const char *const title_table[] = {
/* Pretty names for a few well-known automatically discovered entries. */ /* Pretty names for a few well-known automatically discovered entries. */
@ -841,17 +778,18 @@ int boot_entries_augment_from_loader(
* already included there. */ * already included there. */
STRV_FOREACH(i, found_by_loader) { STRV_FOREACH(i, found_by_loader) {
BootEntry *existing;
_cleanup_free_ char *c = NULL, *t = NULL, *p = NULL; _cleanup_free_ char *c = NULL, *t = NULL, *p = NULL;
char **a, **b; char **a, **b;
existing = boot_config_find_entry(config, *i); if (boot_config_has_entry(config, *i))
if (existing) {
existing->reported_by_loader = true;
continue; continue;
}
if (only_auto && !startswith(*i, "auto-")) /*
* consider the 'auto-' entries only, because the others
* ones are detected scanning the 'esp' and 'xbootldr'
* directories by boot_entries_load_config()
*/
if (!startswith(*i, "auto-"))
continue; continue;
c = strdup(*i); c = strdup(*i);
@ -874,11 +812,10 @@ int boot_entries_augment_from_loader(
return log_oom(); return log_oom();
config->entries[config->n_entries++] = (BootEntry) { config->entries[config->n_entries++] = (BootEntry) {
.type = startswith(*i, "auto-") ? BOOT_ENTRY_LOADER_AUTO : BOOT_ENTRY_LOADER, .type = BOOT_ENTRY_LOADER,
.id = TAKE_PTR(c), .id = TAKE_PTR(c),
.title = TAKE_PTR(t), .title = TAKE_PTR(t),
.path = TAKE_PTR(p), .path = TAKE_PTR(p),
.reported_by_loader = true,
}; };
} }
@ -952,7 +889,7 @@ static int verify_esp_blkid(
r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL); r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
if (r != 0) if (r != 0)
return log_error_errno(errno ?: EIO, "Failed to probe partition type UUID of \"%s\": %m", node); return log_error_errno(errno ?: EIO, "Failed to probe partition type UUID of \"%s\": %m", node);
if (id128_equal_string(v, GPT_ESP) <= 0) if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node); "File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
@ -1045,7 +982,7 @@ static int verify_esp_udev(
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v); r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to get device property: %m"); return log_error_errno(r, "Failed to get device property: %m");
if (id128_equal_string(v, GPT_ESP) <= 0) if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node); "File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
@ -1170,8 +1107,7 @@ static int verify_esp(
uint32_t *ret_part, uint32_t *ret_part,
uint64_t *ret_pstart, uint64_t *ret_pstart,
uint64_t *ret_psize, uint64_t *ret_psize,
sd_id128_t *ret_uuid, sd_id128_t *ret_uuid) {
dev_t *ret_devid) {
bool relax_checks; bool relax_checks;
dev_t devid; dev_t devid;
@ -1221,16 +1157,9 @@ static int verify_esp(
* however blkid can't work if we have no privileges to access block devices directly, which is why * however blkid can't work if we have no privileges to access block devices directly, which is why
* we use udev in that case. */ * we use udev in that case. */
if (unprivileged_mode) if (unprivileged_mode)
r = verify_esp_udev(devid, searching, ret_part, ret_pstart, ret_psize, ret_uuid); return verify_esp_udev(devid, searching, ret_part, ret_pstart, ret_psize, ret_uuid);
else else
r = verify_esp_blkid(devid, searching, ret_part, ret_pstart, ret_psize, ret_uuid); return verify_esp_blkid(devid, searching, ret_part, ret_pstart, ret_psize, ret_uuid);
if (r < 0)
return r;
if (ret_devid)
*ret_devid = devid;
return 0;
finish: finish:
if (ret_part) if (ret_part)
@ -1241,8 +1170,6 @@ finish:
*ret_psize = 0; *ret_psize = 0;
if (ret_uuid) if (ret_uuid)
*ret_uuid = SD_ID128_NULL; *ret_uuid = SD_ID128_NULL;
if (ret_devid)
*ret_devid = 0;
return 0; return 0;
} }
@ -1254,8 +1181,7 @@ int find_esp_and_warn(
uint32_t *ret_part, uint32_t *ret_part,
uint64_t *ret_pstart, uint64_t *ret_pstart,
uint64_t *ret_psize, uint64_t *ret_psize,
sd_id128_t *ret_uuid, sd_id128_t *ret_uuid) {
dev_t *ret_devid) {
int r; int r;
@ -1266,7 +1192,7 @@ int find_esp_and_warn(
*/ */
if (path) { if (path) {
r = verify_esp(path, /* searching= */ false, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid); r = verify_esp(path, false, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid);
if (r < 0) if (r < 0)
return r; return r;
@ -1275,39 +1201,19 @@ int find_esp_and_warn(
path = getenv("SYSTEMD_ESP_PATH"); path = getenv("SYSTEMD_ESP_PATH");
if (path) { if (path) {
struct stat st;
if (!path_is_valid(path) || !path_is_absolute(path)) if (!path_is_valid(path) || !path_is_absolute(path))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"$SYSTEMD_ESP_PATH does not refer to absolute path, refusing to use it: %s", "$SYSTEMD_ESP_PATH does not refer to absolute path, refusing to use it: %s",
path); path);
/* Note: when the user explicitly configured things with an env var we won't validate the /* Note: when the user explicitly configured things with an env var we won't validate the mount
* path beyond checking it refers to a directory. After all we want this to be useful for * point. After all we want this to be useful for testing. */
* testing. */
if (stat(path, &st) < 0)
return log_error_errno(errno, "Failed to stat '%s': %m", path);
if (!S_ISDIR(st.st_mode))
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "ESP path '%s' is not a directory.", path);
if (ret_part)
*ret_part = 0;
if (ret_pstart)
*ret_pstart = 0;
if (ret_psize)
*ret_psize = 0;
if (ret_uuid)
*ret_uuid = SD_ID128_NULL;
if (ret_devid)
*ret_devid = st.st_dev;
goto found; goto found;
} }
FOREACH_STRING(path, "/efi", "/boot", "/boot/efi") { FOREACH_STRING(path, "/efi", "/boot", "/boot/efi") {
r = verify_esp(path, /* searching= */ true, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid); r = verify_esp(path, true, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid);
if (r >= 0) if (r >= 0)
goto found; goto found;
if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */ if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
@ -1374,7 +1280,7 @@ static int verify_xbootldr_blkid(
r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL); r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
if (r != 0) if (r != 0)
return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition type UUID of \"%s\": %m", node); return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition type UUID of \"%s\": %m", node);
if (id128_equal_string(v, GPT_XBOOTLDR) <= 0) if (!streq(v, "bc13c2ff-59e6-4262-a352-b275fd6f7172"))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV), searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV),
"File system \"%s\" has wrong type for extended boot loader partition.", node); "File system \"%s\" has wrong type for extended boot loader partition.", node);
@ -1438,7 +1344,7 @@ static int verify_xbootldr_udev(
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v); r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to get device property: %m"); return log_error_errno(r, "Failed to get device property: %m");
if (id128_equal_string(v, GPT_XBOOTLDR)) if (!streq(v, "bc13c2ff-59e6-4262-a352-b275fd6f7172"))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV), searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV),
"File system \"%s\" has wrong type for extended boot loader partition.", node); "File system \"%s\" has wrong type for extended boot loader partition.", node);
@ -1474,8 +1380,7 @@ static int verify_xbootldr(
const char *p, const char *p,
bool searching, bool searching,
bool unprivileged_mode, bool unprivileged_mode,
sd_id128_t *ret_uuid, sd_id128_t *ret_uuid) {
dev_t *ret_devid) {
bool relax_checks; bool relax_checks;
dev_t devid; dev_t devid;
@ -1493,22 +1398,13 @@ static int verify_xbootldr(
goto finish; goto finish;
if (unprivileged_mode) if (unprivileged_mode)
r = verify_xbootldr_udev(devid, searching, ret_uuid); return verify_xbootldr_udev(devid, searching, ret_uuid);
else else
r = verify_xbootldr_blkid(devid, searching, ret_uuid); return verify_xbootldr_blkid(devid, searching, ret_uuid);
if (r < 0)
return r;
if (ret_devid)
*ret_devid = devid;
return 0;
finish: finish:
if (ret_uuid) if (ret_uuid)
*ret_uuid = SD_ID128_NULL; *ret_uuid = SD_ID128_NULL;
if (ret_devid)
*ret_devid = 0;
return 0; return 0;
} }
@ -1517,15 +1413,14 @@ int find_xbootldr_and_warn(
const char *path, const char *path,
bool unprivileged_mode, bool unprivileged_mode,
char **ret_path, char **ret_path,
sd_id128_t *ret_uuid, sd_id128_t *ret_uuid) {
dev_t *ret_devid) {
int r; int r;
/* Similar to find_esp_and_warn(), but finds the XBOOTLDR partition. Returns the same errors. */ /* Similar to find_esp_and_warn(), but finds the XBOOTLDR partition. Returns the same errors. */
if (path) { if (path) {
r = verify_xbootldr(path, /* searching= */ false, unprivileged_mode, ret_uuid, ret_devid); r = verify_xbootldr(path, false, unprivileged_mode, ret_uuid);
if (r < 0) if (r < 0)
return r; return r;
@ -1534,27 +1429,15 @@ int find_xbootldr_and_warn(
path = getenv("SYSTEMD_XBOOTLDR_PATH"); path = getenv("SYSTEMD_XBOOTLDR_PATH");
if (path) { if (path) {
struct stat st;
if (!path_is_valid(path) || !path_is_absolute(path)) if (!path_is_valid(path) || !path_is_absolute(path))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"$SYSTEMD_XBOOTLDR_PATH does not refer to absolute path, refusing to use it: %s", "$SYSTEMD_XBOOTLDR_PATH does not refer to absolute path, refusing to use it: %s",
path); path);
if (stat(path, &st) < 0)
return log_error_errno(errno, "Failed to stat '%s': %m", path);
if (!S_ISDIR(st.st_mode))
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "XBOOTLDR path '%s' is not a directory.", path);
if (ret_uuid)
*ret_uuid = SD_ID128_NULL;
if (ret_devid)
*ret_devid = st.st_dev;
goto found; goto found;
} }
r = verify_xbootldr("/boot", true, unprivileged_mode, ret_uuid, ret_devid); r = verify_xbootldr("/boot", true, unprivileged_mode, ret_uuid);
if (r >= 0) { if (r >= 0) {
path = "/boot"; path = "/boot";
goto found; goto found;

View File

@ -11,17 +11,15 @@
#include "string-util.h" #include "string-util.h"
typedef enum BootEntryType { typedef enum BootEntryType {
BOOT_ENTRY_CONF, /* Boot Loader Specification Type #1 entries: *.conf files */ BOOT_ENTRY_CONF, /* Type #1 entries: *.conf files */
BOOT_ENTRY_UNIFIED, /* Boot Loader Specification Type #2 entries: *.efi files */ BOOT_ENTRY_UNIFIED, /* Type #2 entries: *.efi files */
BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI variable (regular entries) */ BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI var */
BOOT_ENTRY_LOADER_AUTO, /* Additional entries augmented from LoaderEntries EFI variable (special "automatic" entries) */ _BOOT_ENTRY_MAX,
_BOOT_ENTRY_TYPE_MAX, _BOOT_ENTRY_INVALID = -EINVAL,
_BOOT_ENTRY_TYPE_INVALID = -EINVAL,
} BootEntryType; } BootEntryType;
typedef struct BootEntry { typedef struct BootEntry {
BootEntryType type; BootEntryType type;
bool reported_by_loader;
char *id; /* This is the file basename (including extension!) */ char *id; /* This is the file basename (including extension!) */
char *id_old; /* Old-style ID, for deduplication purposes. */ char *id_old; /* Old-style ID, for deduplication purposes. */
char *path; /* This is the full path to the drop-in file */ char *path; /* This is the full path to the drop-in file */
@ -36,7 +34,6 @@ typedef struct BootEntry {
char *efi; char *efi;
char **initrd; char **initrd;
char *device_tree; char *device_tree;
char **device_tree_overlay;
} BootEntry; } BootEntry;
typedef struct BootConfig { typedef struct BootConfig {
@ -47,33 +44,29 @@ typedef struct BootConfig {
char *auto_firmware; char *auto_firmware;
char *console_mode; char *console_mode;
char *random_seed_mode; char *random_seed_mode;
char *beep;
char *entry_oneshot; char *entry_oneshot;
char *entry_default; char *entry_default;
char *entry_selected;
BootEntry *entries; BootEntry *entries;
size_t n_entries; size_t n_entries;
ssize_t default_entry; ssize_t default_entry;
ssize_t selected_entry;
} BootConfig; } BootConfig;
static inline BootEntry* boot_config_find_entry(BootConfig *config, const char *id) { static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
assert(config); size_t j;
assert(id);
for (size_t j = 0; j < config->n_entries; j++) for (j = 0; j < config->n_entries; j++) {
if (streq_ptr(config->entries[j].id, id) || const char* entry_id_old = config->entries[j].id_old;
streq_ptr(config->entries[j].id_old, id)) if (streq(config->entries[j].id, id) ||
return config->entries + j; (entry_id_old && streq(entry_id_old, id)))
return true;
}
return NULL; return false;
} }
static inline BootEntry* boot_config_default_entry(BootConfig *config) { static inline BootEntry* boot_config_default_entry(BootConfig *config) {
assert(config);
if (config->default_entry < 0) if (config->default_entry < 0)
return NULL; return NULL;
@ -83,13 +76,11 @@ static inline BootEntry* boot_config_default_entry(BootConfig *config) {
void boot_config_free(BootConfig *config); void boot_config_free(BootConfig *config);
int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config); int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
int boot_entries_load_config_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config); int boot_entries_load_config_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config);
int boot_entries_augment_from_loader(BootConfig *config, char **list, bool only_auto); int boot_entries_augment_from_loader(BootConfig *config, char **list);
static inline const char* boot_entry_title(const BootEntry *entry) { static inline const char* boot_entry_title(const BootEntry *entry) {
assert(entry);
return entry->show_title ?: entry->title ?: entry->id; return entry->show_title ?: entry->title ?: entry->id;
} }
int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid); int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid);
int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid, dev_t *ret_devid); int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid);

View File

@ -1699,11 +1699,11 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
case TABLE_UUID: { case TABLE_UUID: {
char *p; char *p;
p = new(char, SD_ID128_UUID_STRING_MAX); p = new(char, ID128_UUID_STRING_MAX);
if (!p) if (!p)
return NULL; return NULL;
d->formatted = sd_id128_to_uuid_string(d->id128, p); d->formatted = id128_to_uuid_string(d->id128, p);
break; break;
} }
@ -2562,7 +2562,7 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) {
return json_variant_new_string(ret, SD_ID128_TO_STRING(d->id128)); return json_variant_new_string(ret, SD_ID128_TO_STRING(d->id128));
case TABLE_UUID: case TABLE_UUID:
return json_variant_new_string(ret, SD_ID128_TO_UUID_STRING(d->id128)); return json_variant_new_string(ret, ID128_TO_UUID_STRING(d->id128));
case TABLE_UID: case TABLE_UID:
if (!uid_is_valid(d->uid)) if (!uid_is_valid(d->uid))

View File

@ -75,7 +75,7 @@ const char *gpt_partition_type_uuid_to_string(sd_id128_t id) {
const char *gpt_partition_type_uuid_to_string_harder( const char *gpt_partition_type_uuid_to_string_harder(
sd_id128_t id, sd_id128_t id,
char buffer[static SD_ID128_UUID_STRING_MAX]) { char buffer[static ID128_UUID_STRING_MAX]) {
const char *s; const char *s;
@ -85,7 +85,7 @@ const char *gpt_partition_type_uuid_to_string_harder(
if (s) if (s)
return s; return s;
return sd_id128_to_uuid_string(id, buffer); return id128_to_uuid_string(id, buffer);
} }
int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret) { int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret) {

View File

@ -286,7 +286,7 @@
const char *gpt_partition_type_uuid_to_string(sd_id128_t id); const char *gpt_partition_type_uuid_to_string(sd_id128_t id);
const char *gpt_partition_type_uuid_to_string_harder( const char *gpt_partition_type_uuid_to_string_harder(
sd_id128_t id, sd_id128_t id,
char buffer[static SD_ID128_UUID_STRING_MAX]); char buffer[static ID128_UUID_STRING_MAX]);
int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret); int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret);
Architecture gpt_partition_type_uuid_to_arch(sd_id128_t id); Architecture gpt_partition_type_uuid_to_arch(sd_id128_t id);

View File

@ -1510,7 +1510,7 @@ int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) { static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
_cleanup_close_pair_ int pair[2] = { -1, -1 }; _cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1; _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
char buf[SD_ID128_UUID_STRING_MAX]; char buf[ID128_UUID_STRING_MAX];
pid_t pid, child; pid_t pid, child;
ssize_t k; ssize_t k;
int r; int r;

View File

@ -94,7 +94,7 @@ int make_filesystem(
bool discard) { bool discard) {
_cleanup_free_ char *mkfs = NULL, *mangled_label = NULL; _cleanup_free_ char *mkfs = NULL, *mangled_label = NULL;
char vol_id[CONST_MAX(SD_ID128_UUID_STRING_MAX, 8U + 1U)] = {}; char vol_id[CONST_MAX(ID128_UUID_STRING_MAX, 8 + 1)] = {};
int r; int r;
assert(node); assert(node);
@ -144,7 +144,7 @@ int make_filesystem(
} }
if (isempty(vol_id)) if (isempty(vol_id))
assert_se(sd_id128_to_uuid_string(uuid, vol_id)); id128_to_uuid_string(uuid, vol_id);
r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL); r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL);
if (r < 0) if (r < 0)

View File

@ -816,7 +816,7 @@ static int mount_in_namespace(
return log_debug_errno(errno, "Failed to fstat mount namespace FD of systemd: %m"); return log_debug_errno(errno, "Failed to fstat mount namespace FD of systemd: %m");
/* We can't add new mounts at runtime if the process wasn't started in a namespace */ /* We can't add new mounts at runtime if the process wasn't started in a namespace */
if (stat_inode_same(&st, &self_mntns_st)) if (st.st_ino == self_mntns_st.st_ino && st.st_dev == self_mntns_st.st_dev)
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to activate bind mount in target, not running in a mount namespace"); return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to activate bind mount in target, not running in a mount namespace");
/* One day, when bind mounting /proc/self/fd/n works across namespace boundaries we should rework /* One day, when bind mounting /proc/self/fd/n works across namespace boundaries we should rework

View File

@ -351,7 +351,7 @@ void log_device_uevent(sd_device *device, const char *str) {
strempty(str), isempty(str) ? "" : " ", strempty(str), isempty(str) ? "" : " ",
seqnum, strna(device_action_to_string(action)), seqnum, strna(device_action_to_string(action)),
sd_id128_is_null(event_id) ? "" : ", UUID=", sd_id128_is_null(event_id) ? "" : ", UUID=",
sd_id128_is_null(event_id) ? "" : SD_ID128_TO_UUID_STRING(event_id)); sd_id128_is_null(event_id) ? "" : id128_to_uuid_string(event_id, (char[ID128_UUID_STRING_MAX]){}));
} }
int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) { int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) {

View File

@ -12,7 +12,6 @@
#include "systemctl-compat-halt.h" #include "systemctl-compat-halt.h"
#include "systemctl-compat-telinit.h" #include "systemctl-compat-telinit.h"
#include "systemctl-logind.h" #include "systemctl-logind.h"
#include "systemctl-start-unit.h"
#include "systemctl-util.h" #include "systemctl-util.h"
#include "systemctl.h" #include "systemctl.h"
#include "terminal-util.h" #include "terminal-util.h"
@ -145,32 +144,30 @@ int halt_parse_argv(int argc, char *argv[]) {
int halt_main(void) { int halt_main(void) {
int r; int r;
if (arg_force == 0) { /* always try logind first */
/* always try logind first */ if (arg_when > 0)
if (arg_when > 0) r = logind_schedule_shutdown();
r = logind_schedule_shutdown(); else {
else { r = logind_check_inhibitors(arg_action);
r = logind_check_inhibitors(arg_action); if (r < 0)
if (r < 0)
return r;
r = logind_reboot(arg_action);
}
if (r >= 0)
return r; return r;
if (IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
/* Requested operation requires auth, is not supported on the local system or already in
* progress */
return r;
/* on all other errors, try low-level operation */
/* In order to minimize the difference between operation with and without logind, we explicitly r = logind_reboot(arg_action);
* enable non-blocking mode for this, as logind's shutdown operations are always non-blocking. */
arg_no_block = true;
if (!arg_dry_run)
return start_with_fallback();
} }
if (r >= 0)
return r;
if (IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
/* Requested operation requires auth, is not supported on the local system or already in
* progress */
return r;
/* on all other errors, try low-level operation */
/* In order to minimize the difference between operation with and without logind, we explicitly
* enable non-blocking mode for this, as logind's shutdown operations are always non-blocking. */
arg_no_block = true;
if (!arg_dry_run && !arg_force)
return start_with_fallback();
if (geteuid() != 0) { if (geteuid() != 0) {
(void) must_be_root(); (void) must_be_root();

View File

@ -35,14 +35,11 @@ union sd_id128 {
}; };
#define SD_ID128_STRING_MAX 33U #define SD_ID128_STRING_MAX 33U
#define SD_ID128_UUID_STRING_MAX 37U
char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]); char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]);
char *sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_UUID_STRING_MAX]);
int sd_id128_from_string(const char *s, sd_id128_t *ret); int sd_id128_from_string(const char *s, sd_id128_t *ret);
#define SD_ID128_TO_STRING(id) sd_id128_to_string((id), (char[SD_ID128_STRING_MAX]) {}) #define SD_ID128_TO_STRING(id) sd_id128_to_string((id), (char[SD_ID128_STRING_MAX]) {})
#define SD_ID128_TO_UUID_STRING(id) sd_id128_to_uuid_string((id), (char[SD_ID128_UUID_STRING_MAX]) {})
int sd_id128_randomize(sd_id128_t *ret); int sd_id128_randomize(sd_id128_t *ret);

View File

@ -21,7 +21,7 @@
TEST(id128) { TEST(id128) {
sd_id128_t id, id2; sd_id128_t id, id2;
char t[SD_ID128_STRING_MAX], q[SD_ID128_UUID_STRING_MAX]; char t[SD_ID128_STRING_MAX], q[ID128_UUID_STRING_MAX];
_cleanup_free_ char *b = NULL; _cleanup_free_ char *b = NULL;
_cleanup_close_ int fd = -1; _cleanup_close_ int fd = -1;
@ -53,7 +53,7 @@ TEST(id128) {
printf("waldi2: %s\n", b); printf("waldi2: %s\n", b);
assert_se(streq(t, b)); assert_se(streq(t, b));
printf("waldi3: %s\n", sd_id128_to_uuid_string(ID128_WALDI, q)); printf("waldi3: %s\n", id128_to_uuid_string(ID128_WALDI, q));
assert_se(streq(q, UUID_WALDI)); assert_se(streq(q, UUID_WALDI));
b = mfree(b); b = mfree(b);
@ -136,7 +136,7 @@ TEST(id128) {
assert_se(ftruncate(fd, 0) >= 0); assert_se(ftruncate(fd, 0) >= 0);
assert_se(sd_id128_randomize(&id) >= 0); assert_se(sd_id128_randomize(&id) >= 0);
assert_se(write(fd, sd_id128_to_uuid_string(id, q), 36) == 36); assert_se(write(fd, id128_to_uuid_string(id, q), 36) == 36);
assert_se(lseek(fd, 0, SEEK_SET) == 0); assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL); assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL);

View File

@ -213,7 +213,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
return log_oom(); return log_oom();
} else if (proc_cmdline_key_streq(key, "usrhash")) { } else if (proc_cmdline_key_streq(key, "usrhash")) {
if (proc_cmdline_value_missing(key, value)) if (proc_cmdline_value_missing(key, value))
return 0; return 0;
@ -285,7 +285,7 @@ static int determine_device(
if (!*data_what) { if (!*data_what) {
memcpy(&data_uuid, m, sizeof(data_uuid)); memcpy(&data_uuid, m, sizeof(data_uuid));
*data_what = path_join("/dev/disk/by-partuuid", SD_ID128_TO_UUID_STRING(data_uuid)); *data_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(data_uuid));
if (!*data_what) if (!*data_what)
return log_oom(); return log_oom();
} }
@ -293,7 +293,7 @@ static int determine_device(
if (!*hash_what) { if (!*hash_what) {
memcpy(&verity_uuid, (uint8_t*) m + l - sizeof(verity_uuid), sizeof(verity_uuid)); memcpy(&verity_uuid, (uint8_t*) m + l - sizeof(verity_uuid), sizeof(verity_uuid));
*hash_what = path_join("/dev/disk/by-partuuid", SD_ID128_TO_UUID_STRING(verity_uuid)); *hash_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(verity_uuid));
if (!*hash_what) if (!*hash_what)
return log_oom(); return log_oom();
} }

View File

@ -1070,9 +1070,6 @@ install_compiled_systemd() {
if get_bool "$IS_BUILT_WITH_COVERAGE"; then if get_bool "$IS_BUILT_WITH_COVERAGE"; then
mkdir -p "${initdir}/${BUILD_DIR:?}/" mkdir -p "${initdir}/${BUILD_DIR:?}/"
rsync -am --include='*/' --include='*.gcno' --exclude='*' "${BUILD_DIR:?}/" "${initdir}/${BUILD_DIR:?}/" rsync -am --include='*/' --include='*.gcno' --exclude='*' "${BUILD_DIR:?}/" "${initdir}/${BUILD_DIR:?}/"
# Set effective & default ACLs for the build dir so unprivileged
# processes can write gcda files with coverage stats
setfacl -R -m 'd:o:rwX' -m 'o:rwX' "${initdir}/${BUILD_DIR:?}/"
fi fi
} }
@ -1387,20 +1384,6 @@ check_coverage_reports() {
lcov --remove "${dest}" -o "${dest}" '/usr/include/*' '/usr/lib/*' lcov --remove "${dest}" -o "${dest}" '/usr/include/*' '/usr/lib/*'
fi fi
# If the test logs contain lines like:
#
# ...systemd-resolved[735885]: profiling:/systemd-meson-build/src/shared/libsystemd-shared-250.a.p/base-filesystem.c.gcda:Cannot open
#
# it means we're possibly missing some coverage since gcov can't write the stats,
# usually due to the sandbox being too restrictive (e.g. ProtectSystem=yes,
# ProtectHome=yes) or the $BUILD_DIR being inaccessible to non-root users - see
# `setfacl` stuff in install_compiled_systemd().
if "${JOURNALCTL:?}" -q --no-pager -D "${root:?}/var/log/journal" --grep "profiling:.+?gcda:[Cc]annot open"; then
derror "Detected possibly missing coverage, check the journal"
return 1
fi
return 0 return 0
} }