mirror of
https://github.com/systemd/systemd
synced 2026-04-20 22:14:52 +02:00
Compare commits
40 Commits
1b46eb23bc
...
f3376ee8fa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3376ee8fa | ||
|
|
88586e5d32 | ||
|
|
d1e7fa02ca | ||
|
|
1d7150ec7f | ||
|
|
d6b218e742 | ||
|
|
c20c77eff8 | ||
|
|
675e7fc22c | ||
|
|
a9dac7a6dd | ||
|
|
38db6211b5 | ||
|
|
d74da762a3 | ||
|
|
bfba9946a1 | ||
|
|
d5ac1d4e10 | ||
|
|
f63b5ad935 | ||
|
|
5635040091 | ||
|
|
bb68205768 | ||
|
|
a78e472dfd | ||
|
|
d403d8f0d6 | ||
|
|
fdc5c04299 | ||
|
|
4cddc18d0a | ||
|
|
736783d420 | ||
|
|
9951736b7f | ||
|
|
93e0d3204c | ||
|
|
fe9bd5ad36 | ||
|
|
e46433bb92 | ||
|
|
75a505c600 | ||
|
|
b74163607b | ||
|
|
fdf9de694f | ||
|
|
42672c80dc | ||
|
|
d0ebe2a835 | ||
|
|
d5cb053cd9 | ||
|
|
f1ad2c9238 | ||
|
|
d282e57e2a | ||
|
|
e4c822e9ac | ||
|
|
2a3a5288cb | ||
|
|
54141d8ddd | ||
|
|
1831759a70 | ||
|
|
d2fc0ecf9a | ||
|
|
138224fc80 | ||
|
|
81db4f3dd8 | ||
|
|
07c160a65c |
2
TODO
2
TODO
@ -78,6 +78,8 @@ Janitorial Clean-ups:
|
||||
|
||||
Features:
|
||||
|
||||
* bootspec: remove tries counter from boot entry ids
|
||||
|
||||
* automatically ignore threaded cgroups in cg_xyz().
|
||||
|
||||
* add linker script that implicitly adds symbol for build ID and new coredump
|
||||
|
||||
@ -266,6 +266,15 @@ 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
|
||||
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
|
||||
|
||||
Let's say you write a container manager, and you wonder what to do regarding
|
||||
|
||||
@ -641,7 +641,12 @@ manpages = [
|
||||
['sd_id128_randomize', '3', [], ''],
|
||||
['sd_id128_to_string',
|
||||
'3',
|
||||
['SD_ID128_STRING_MAX', 'SD_ID128_TO_STRING', 'sd_id128_from_string'],
|
||||
['SD_ID128_STRING_MAX',
|
||||
'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',
|
||||
'3',
|
||||
|
||||
@ -18,8 +18,11 @@
|
||||
<refnamediv>
|
||||
<refname>sd_id128_to_string</refname>
|
||||
<refname>SD_ID128_TO_STRING</refname>
|
||||
<refname>sd_id128_from_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>
|
||||
<refpurpose>Format or parse 128-bit IDs as strings</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
@ -29,13 +32,22 @@
|
||||
|
||||
<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_UUID_STRING(id) …</funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<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>
|
||||
</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>
|
||||
<funcdef>int <function>sd_id128_from_string</function></funcdef>
|
||||
<paramdef>const char *<parameter>s</parameter>, sd_id128_t *<parameter>ret</parameter></paramdef>
|
||||
@ -58,6 +70,10 @@
|
||||
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>
|
||||
|
||||
<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
|
||||
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
|
||||
@ -65,7 +81,7 @@
|
||||
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>
|
||||
|
||||
<para>Note that when parsing 37 character UUIDs this is done strictly in Big Endian byte order,
|
||||
<para>Note that when formatting and parsing 36 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
|
||||
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>
|
||||
|
||||
@ -417,14 +417,11 @@ int same_fd(int a, int b) {
|
||||
assert(a >= 0);
|
||||
assert(b >= 0);
|
||||
|
||||
/* Compares two file descriptors. Note that semantics are
|
||||
* quite different depending on whether we have kcmp() or we
|
||||
* don't. If we have kcmp() this will only return true for
|
||||
* dup()ed file descriptors, but not otherwise. If we don't
|
||||
* 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. */
|
||||
/* Compares two file descriptors. Note that semantics are quite different depending on whether we
|
||||
* have kcmp() or we don't. If we have kcmp() this will only return true for dup()ed file
|
||||
* descriptors, but not otherwise. If we don't 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)
|
||||
return true;
|
||||
@ -436,7 +433,7 @@ int same_fd(int a, int b) {
|
||||
return true;
|
||||
if (r > 0)
|
||||
return false;
|
||||
if (!IN_SET(errno, ENOSYS, EACCES, EPERM))
|
||||
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
|
||||
return -errno;
|
||||
|
||||
/* We don't have kcmp(), use fstat() instead. */
|
||||
@ -446,23 +443,17 @@ int same_fd(int a, int b) {
|
||||
if (fstat(b, &stb) < 0)
|
||||
return -errno;
|
||||
|
||||
if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
|
||||
if (!stat_inode_same(&sta, &stb))
|
||||
return false;
|
||||
|
||||
/* We consider all device fds different, since two device fds
|
||||
* might refer to quite different device contexts even though
|
||||
* they share the same inode and backing dev_t. */
|
||||
/* We consider all device fds different, since two device fds 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))
|
||||
return false;
|
||||
|
||||
if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
|
||||
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(). */
|
||||
/* 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);
|
||||
if (fa < 0)
|
||||
return -errno;
|
||||
|
||||
@ -856,8 +856,7 @@ int conservative_renameat(
|
||||
if (fstat(new_fd, &new_stat) < 0)
|
||||
goto do_rename;
|
||||
|
||||
if (new_stat.st_ino == old_stat.st_ino &&
|
||||
new_stat.st_dev == old_stat.st_dev)
|
||||
if (stat_inode_same(&new_stat, &old_stat))
|
||||
goto is_same;
|
||||
|
||||
if (old_stat.st_mode != new_stat.st_mode ||
|
||||
|
||||
@ -298,10 +298,8 @@ fallback_fstat:
|
||||
if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
|
||||
return -errno;
|
||||
|
||||
/* A directory with same device and inode as its parent? Must
|
||||
* be the root directory */
|
||||
if (a.st_dev == b.st_dev &&
|
||||
a.st_ino == b.st_ino)
|
||||
/* A directory with same device and inode as its parent? Must be the root directory */
|
||||
if (stat_inode_same(&a, &b))
|
||||
return 1;
|
||||
|
||||
return check_st_dev && (a.st_dev != b.st_dev);
|
||||
|
||||
@ -185,8 +185,7 @@ int files_same(const char *filea, const char *fileb, int flags) {
|
||||
if (fstatat(AT_FDCWD, fileb, &b, flags) < 0)
|
||||
return -errno;
|
||||
|
||||
return a.st_dev == b.st_dev &&
|
||||
a.st_ino == b.st_ino;
|
||||
return stat_inode_same(&a, &b);
|
||||
}
|
||||
|
||||
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
|
||||
@ -417,6 +416,18 @@ int proc_mounted(void) {
|
||||
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) {
|
||||
|
||||
/* Returns if the specified stat structures reference the same, unmodified inode. This check tries to
|
||||
@ -428,14 +439,10 @@ 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
|
||||
* else. */
|
||||
|
||||
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 */
|
||||
return stat_inode_same(a, b) &&
|
||||
a->st_mtim.tv_sec == b->st_mtim.tv_sec &&
|
||||
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 */
|
||||
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 */
|
||||
}
|
||||
|
||||
|
||||
@ -92,6 +92,7 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret
|
||||
|
||||
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);
|
||||
|
||||
int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx);
|
||||
@ -114,3 +115,9 @@ int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct s
|
||||
struct new_statx nsx; \
|
||||
} var
|
||||
#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;
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "stat-util.h"
|
||||
#include "sync-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "util.h"
|
||||
@ -98,17 +99,18 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
static int acquire_path(void) {
|
||||
_cleanup_free_ char *esp_path = NULL, *xbootldr_path = NULL;
|
||||
dev_t esp_devid = 0, xbootldr_devid = 0;
|
||||
char **a;
|
||||
int r;
|
||||
|
||||
if (!strv_isempty(arg_path))
|
||||
return 0;
|
||||
|
||||
r = find_esp_and_warn(NULL, false, &esp_path, NULL, NULL, NULL, NULL);
|
||||
r = find_esp_and_warn(NULL, /* unprivileged_mode= */ false, &esp_path, NULL, NULL, NULL, NULL, &esp_devid);
|
||||
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;
|
||||
|
||||
r = find_xbootldr_and_warn(NULL, false, &xbootldr_path, NULL);
|
||||
r = find_xbootldr_and_warn(NULL, /* unprivileged_mode= */ false, &xbootldr_path, NULL, &xbootldr_devid);
|
||||
if (r < 0 && r != -ENOKEY)
|
||||
return r;
|
||||
|
||||
@ -117,8 +119,10 @@ static int acquire_path(void) {
|
||||
"Couldn't find $BOOT partition. It is recommended to mount it to /boot.\n"
|
||||
"Alternatively, use --path= to specify path to mount point.");
|
||||
|
||||
if (esp_path)
|
||||
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 */
|
||||
a = strv_new(esp_path, xbootldr_path);
|
||||
else if (esp_path)
|
||||
a = strv_new(esp_path);
|
||||
else
|
||||
a = strv_new(xbootldr_path);
|
||||
if (!a)
|
||||
@ -130,7 +134,7 @@ static int acquire_path(void) {
|
||||
_cleanup_free_ char *j = NULL;
|
||||
|
||||
j = strv_join(arg_path, ":");
|
||||
log_debug("Using %s as boot loader drop-in search path.", j);
|
||||
log_debug("Using %s as boot loader drop-in search path.", strna(j));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#include "rm-rf.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "sync-util.h"
|
||||
@ -74,7 +75,8 @@ static int acquire_esp(
|
||||
uint32_t *ret_part,
|
||||
uint64_t *ret_pstart,
|
||||
uint64_t *ret_psize,
|
||||
sd_id128_t *ret_uuid) {
|
||||
sd_id128_t *ret_uuid,
|
||||
dev_t *ret_devid) {
|
||||
|
||||
char *np;
|
||||
int r;
|
||||
@ -85,7 +87,7 @@ static int acquire_esp(
|
||||
* we simply eat up the error here, so that --list and --status work too, without noise about
|
||||
* this). */
|
||||
|
||||
r = find_esp_and_warn(arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid);
|
||||
r = find_esp_and_warn(arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid);
|
||||
if (r == -ENOKEY) {
|
||||
if (graceful)
|
||||
return log_info_errno(r, "Couldn't find EFI system partition, skipping.");
|
||||
@ -103,16 +105,23 @@ static int acquire_esp(
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int acquire_xbootldr(bool unprivileged_mode, sd_id128_t *ret_uuid) {
|
||||
static int acquire_xbootldr(
|
||||
bool unprivileged_mode,
|
||||
sd_id128_t *ret_uuid,
|
||||
dev_t *ret_devid) {
|
||||
|
||||
char *np;
|
||||
int r;
|
||||
|
||||
r = find_xbootldr_and_warn(arg_xbootldr_path, unprivileged_mode, &np, ret_uuid);
|
||||
r = find_xbootldr_and_warn(arg_xbootldr_path, unprivileged_mode, &np, ret_uuid, ret_devid);
|
||||
if (r == -ENOKEY) {
|
||||
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)
|
||||
*ret_uuid = SD_ID128_NULL;
|
||||
arg_xbootldr_path = mfree(arg_xbootldr_path);
|
||||
if (ret_devid)
|
||||
*ret_devid = 0;
|
||||
return 0;
|
||||
}
|
||||
if (r < 0)
|
||||
@ -411,7 +420,21 @@ static void boot_entry_file_list(const char *field, const char *root, const char
|
||||
*ret_status = status;
|
||||
}
|
||||
|
||||
static int boot_entry_show(const BootEntry *e, bool show_as_default) {
|
||||
static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = {
|
||||
[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;
|
||||
|
||||
/* Returns 0 on success, negative on processing error, and positive if something is wrong with the
|
||||
@ -419,9 +442,30 @@ static int boot_entry_show(const BootEntry *e, bool show_as_default) {
|
||||
|
||||
assert(e);
|
||||
|
||||
printf(" title: %s%s%s" "%s%s%s\n",
|
||||
ansi_highlight(), boot_entry_title(e), ansi_normal(),
|
||||
ansi_highlight_green(), show_as_default ? " (default)" : "", ansi_normal());
|
||||
printf(" type: %s\n",
|
||||
boot_entry_type_to_string(e->type));
|
||||
|
||||
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)
|
||||
printf(" id: %s\n", e->id);
|
||||
@ -450,6 +494,7 @@ static int boot_entry_show(const BootEntry *e, bool show_as_default) {
|
||||
e->root,
|
||||
*s,
|
||||
&status);
|
||||
|
||||
if (!strv_isempty(e->options)) {
|
||||
_cleanup_free_ char *t = NULL, *t2 = NULL;
|
||||
_cleanup_strv_free_ char **ts = NULL;
|
||||
@ -468,9 +513,16 @@ static int boot_entry_show(const BootEntry *e, bool show_as_default) {
|
||||
|
||||
printf(" options: %s\n", t2);
|
||||
}
|
||||
|
||||
if (e->device_tree)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -511,7 +563,11 @@ static int status_entries(
|
||||
else {
|
||||
printf("Default Boot Loader Entry:\n");
|
||||
|
||||
r = boot_entry_show(config.entries + config.default_entry, false);
|
||||
r = boot_entry_show(
|
||||
config.entries + config.default_entry,
|
||||
/* show_as_default= */ false,
|
||||
/* show_as_selected= */ false,
|
||||
/* show_discovered= */ false);
|
||||
if (r > 0)
|
||||
/* < 0 is already logged by the function itself, let's just emit an extra warning if
|
||||
the default entry is broken */
|
||||
@ -1388,7 +1444,7 @@ static void print_yes_no_line(bool first, bool good, const char *name) {
|
||||
static int are_we_installed(void) {
|
||||
int r;
|
||||
|
||||
r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL);
|
||||
r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1420,9 +1476,10 @@ static int are_we_installed(void) {
|
||||
|
||||
static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
sd_id128_t esp_uuid = SD_ID128_NULL, xbootldr_uuid = SD_ID128_NULL;
|
||||
dev_t esp_devid = 0, xbootldr_devid = 0;
|
||||
int r, k;
|
||||
|
||||
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, &esp_uuid);
|
||||
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, &esp_uuid, &esp_devid);
|
||||
if (arg_print_esp_path) {
|
||||
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) */
|
||||
@ -1433,7 +1490,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
puts(arg_esp_path);
|
||||
}
|
||||
|
||||
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, &xbootldr_uuid);
|
||||
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, &xbootldr_uuid, &xbootldr_devid);
|
||||
if (arg_print_dollar_boot_path) {
|
||||
if (r == -EACCES)
|
||||
return log_error_errno(r, "Failed to determine XBOOTLDR location: %m");
|
||||
@ -1567,7 +1624,14 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
|
||||
if (arg_esp_path || arg_xbootldr_path) {
|
||||
k = status_entries(arg_esp_path, esp_uuid, arg_xbootldr_path, xbootldr_uuid);
|
||||
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */
|
||||
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)
|
||||
r = k;
|
||||
}
|
||||
@ -1578,25 +1642,29 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
static int verb_list(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(boot_config_free) BootConfig config = {};
|
||||
_cleanup_strv_free_ char **efi_entries = NULL;
|
||||
dev_t esp_devid = 0, xbootldr_devid = 0;
|
||||
int r;
|
||||
|
||||
/* 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
|
||||
* 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);
|
||||
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, NULL, &esp_devid);
|
||||
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");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, NULL);
|
||||
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, NULL, &xbootldr_devid);
|
||||
if (r == -EACCES)
|
||||
return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = boot_entries_load_config(arg_esp_path, arg_xbootldr_path, &config);
|
||||
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */
|
||||
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)
|
||||
return r;
|
||||
|
||||
@ -1606,7 +1674,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
||||
else if (r < 0)
|
||||
log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
|
||||
else
|
||||
(void) boot_entries_augment_from_loader(&config, efi_entries);
|
||||
(void) boot_entries_augment_from_loader(&config, efi_entries, /* only_auto= */ false);
|
||||
|
||||
if (config.n_entries == 0)
|
||||
log_info("No boot loader entries found.");
|
||||
@ -1616,7 +1684,11 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
||||
printf("Boot Loader Entries:\n");
|
||||
|
||||
for (size_t n = 0; n < config.n_entries; n++) {
|
||||
r = boot_entry_show(config.entries + n, n == (size_t) config.default_entry);
|
||||
r = boot_entry_show(
|
||||
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)
|
||||
return r;
|
||||
|
||||
@ -1788,7 +1860,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
|
||||
install = streq(argv[0], "install");
|
||||
graceful = !install && arg_graceful; /* support graceful mode for updates */
|
||||
|
||||
r = acquire_esp(/* unprivileged_mode= */ false, graceful, &part, &pstart, &psize, &uuid);
|
||||
r = acquire_esp(/* unprivileged_mode= */ false, graceful, &part, &pstart, &psize, &uuid, NULL);
|
||||
if (graceful && r == -ENOKEY)
|
||||
return 0; /* If --graceful is specified and we can't find an ESP, handle this cleanly */
|
||||
if (r < 0)
|
||||
@ -1805,7 +1877,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
}
|
||||
|
||||
r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL);
|
||||
r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1865,11 +1937,11 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
|
||||
sd_id128_t uuid = SD_ID128_NULL;
|
||||
int r, q;
|
||||
|
||||
r = acquire_esp(/* unprivileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, &uuid);
|
||||
r = acquire_esp(/* unprivileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, &uuid, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL);
|
||||
r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -2078,7 +2150,7 @@ static int verb_set_efivar(int argc, char *argv[], void *userdata) {
|
||||
static int verb_random_seed(int argc, char *argv[], void *userdata) {
|
||||
int r;
|
||||
|
||||
r = find_esp_and_warn(arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL);
|
||||
r = find_esp_and_warn(arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL, NULL);
|
||||
if (r == -ENOKEY) {
|
||||
/* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
|
||||
if (!arg_graceful)
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "hashmap.h"
|
||||
#include "macro.h"
|
||||
#include "memory-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "time-util.h"
|
||||
#include "user-util.h"
|
||||
@ -167,9 +168,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
|
||||
if (!S_ISREG(st.st_mode))
|
||||
continue;
|
||||
|
||||
if (exclude_fd >= 0 &&
|
||||
exclude_st.st_dev == st.st_dev &&
|
||||
exclude_st.st_ino == st.st_ino)
|
||||
if (exclude_fd >= 0 && stat_inode_same(&exclude_st, &st))
|
||||
continue;
|
||||
|
||||
r = hashmap_ensure_allocated(&h, NULL);
|
||||
|
||||
@ -721,7 +721,7 @@ static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) {
|
||||
return -errno;
|
||||
|
||||
/* The process uses system root. */
|
||||
if (proc_root_stat.st_ino == root_stat.st_ino) {
|
||||
if (stat_inode_same(&proc_root_stat, &root_stat)) {
|
||||
*cmdline = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -779,12 +779,16 @@ static int add_mounts(void) {
|
||||
return btrfs_log_dev_root(LOG_ERR, r, "root file system");
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine block device of root file system: %m");
|
||||
if (r == 0) { /* Not backed by block device */
|
||||
if (r == 0) { /* Not backed by a single block device. (Could be NFS or so, or could be multi-device RAID or so) */
|
||||
r = get_block_device_harder("/usr", &devno);
|
||||
if (r == -EUCLEAN)
|
||||
return btrfs_log_dev_root(LOG_ERR, r, "/usr");
|
||||
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)
|
||||
return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
|
||||
|
||||
@ -1239,10 +1239,7 @@ static int manager_add_device(Manager *m, sd_device *d) {
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire ID_PART_ENTRY_TYPE device property, ignoring: %m");
|
||||
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)) {
|
||||
if (id128_equal_string(parttype, GPT_USER_HOME) <= 0) {
|
||||
log_debug("Found partition (%s) we don't care about, ignoring.", sysfs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "filesystems.h"
|
||||
#include "fs-util.h"
|
||||
#include "fsck-util.h"
|
||||
#include "gpt.h"
|
||||
#include "home-util.h"
|
||||
#include "homework-luks.h"
|
||||
#include "homework-mount.h"
|
||||
@ -703,7 +704,7 @@ static int luks_validate(
|
||||
if (!pp)
|
||||
return errno > 0 ? -errno : -EIO;
|
||||
|
||||
if (!streq_ptr(blkid_partition_get_type_string(pp), "773f91ef-66d4-49b5-bd83-d683bf40ad16"))
|
||||
if (id128_equal_string(blkid_partition_get_type_string(pp), GPT_USER_HOME) <= 0)
|
||||
continue;
|
||||
|
||||
if (!streq_ptr(blkid_partition_get_name(pp), label))
|
||||
@ -1762,7 +1763,7 @@ static int luks_format(
|
||||
CRYPT_LUKS2,
|
||||
user_record_luks_cipher(hr),
|
||||
user_record_luks_cipher_mode(hr),
|
||||
ID128_TO_UUID_STRING(uuid),
|
||||
SD_ID128_TO_UUID_STRING(uuid),
|
||||
volume_key,
|
||||
volume_key_size,
|
||||
&(struct crypt_params_luks2) {
|
||||
@ -1858,7 +1859,7 @@ static int make_partition_table(
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
r = fdisk_parttype_set_typestr(t, "773f91ef-66d4-49b5-bd83-d683bf40ad16");
|
||||
r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(GPT_USER_HOME));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to initialize partition type: %m");
|
||||
|
||||
@ -1917,7 +1918,7 @@ static int make_partition_table(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set partition name: %m");
|
||||
|
||||
r = fdisk_partition_set_uuid(p, ID128_TO_UUID_STRING(uuid));
|
||||
r = fdisk_partition_set_uuid(p, SD_ID128_TO_UUID_STRING(uuid));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set partition UUID: %m");
|
||||
|
||||
@ -2745,7 +2746,7 @@ static int ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *userdata
|
||||
if (!result)
|
||||
return log_oom();
|
||||
|
||||
fdisk_ask_string_set_result(ask, id128_to_uuid_string(*(sd_id128_t*) userdata, result));
|
||||
fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) userdata, result));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@ -332,9 +332,9 @@ int user_record_add_binding(
|
||||
r = json_build(&new_binding_entry,
|
||||
JSON_BUILD_OBJECT(
|
||||
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(ID128_TO_UUID_STRING(partition_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(ID128_TO_UUID_STRING(fs_uuid))),
|
||||
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(luks_uuid), "luksUuid", JSON_BUILD_STRING(SD_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(!!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_volume_key_size != UINT64_MAX, "luksVolumeKeySize", JSON_BUILD_UNSIGNED(luks_volume_key_size)),
|
||||
|
||||
@ -769,3 +769,8 @@ global:
|
||||
sd_event_add_inotify_fd;
|
||||
sd_event_source_set_ratelimit_expire_callback;
|
||||
} LIBSYSTEMD_249;
|
||||
|
||||
LIBSYSTEMD_251 {
|
||||
global:
|
||||
sd_id128_to_uuid_string;
|
||||
} LIBSYSTEMD_250;
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
#include "util.h"
|
||||
@ -150,9 +151,7 @@ _public_ int sd_is_fifo(int fd, const char *path) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return
|
||||
st_path.st_dev == st_fd.st_dev &&
|
||||
st_path.st_ino == st_fd.st_ino;
|
||||
return stat_inode_same(&st_path, &st_fd);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -181,9 +180,7 @@ _public_ int sd_is_special(int fd, const char *path) {
|
||||
}
|
||||
|
||||
if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
|
||||
return
|
||||
st_path.st_dev == st_fd.st_dev &&
|
||||
st_path.st_ino == st_fd.st_ino;
|
||||
return stat_inode_same(&st_path, &st_fd);
|
||||
else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
|
||||
return st_path.st_rdev == st_fd.st_rdev;
|
||||
else
|
||||
@ -415,7 +412,7 @@ _public_ int sd_is_mq(int fd, const char *path) {
|
||||
}
|
||||
|
||||
if (path) {
|
||||
char fpath[PATH_MAX];
|
||||
_cleanup_free_ char *fpath = NULL;
|
||||
struct stat a, b;
|
||||
|
||||
assert_return(path_is_absolute(path), -EINVAL);
|
||||
@ -423,14 +420,14 @@ _public_ int sd_is_mq(int fd, const char *path) {
|
||||
if (fstat(fd, &a) < 0)
|
||||
return -errno;
|
||||
|
||||
strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
|
||||
fpath[sizeof(fpath)-1] = 0;
|
||||
fpath = path_join("/dev/mqueue", path);
|
||||
if (!fpath)
|
||||
return -ENOMEM;
|
||||
|
||||
if (stat(fpath, &b) < 0)
|
||||
return -errno;
|
||||
|
||||
if (a.st_dev != b.st_dev ||
|
||||
a.st_ino != b.st_ino)
|
||||
if (!stat_inode_same(&a, &b))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "mountpoint-util.h"
|
||||
#include "set.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
@ -195,7 +196,7 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
|
||||
else
|
||||
log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns, ignoring: %m");
|
||||
|
||||
} else if (a.st_dev != b.st_dev || a.st_ino != b.st_ino)
|
||||
} else if (!stat_inode_same(&a, &b))
|
||||
log_debug("sd-device-monitor: Netlink socket we listen on is not from host netns, we won't see device events.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,6 +248,10 @@ _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum)
|
||||
assert_return(ret, -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 */
|
||||
xsprintf(id, "%u:%u", major(devnum), minor(devnum));
|
||||
|
||||
@ -2194,7 +2198,7 @@ _public_ int sd_device_trigger_with_uuid(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
j = strjoina(s, " ", ID128_TO_UUID_STRING(u));
|
||||
j = strjoina(s, " ", SD_ID128_TO_UUID_STRING(u));
|
||||
|
||||
r = sd_device_set_sysattr_value(device, "uevent", j);
|
||||
if (r < 0)
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "device-private.h"
|
||||
#include "device-util.h"
|
||||
#include "macro.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
#include "util.h"
|
||||
@ -24,11 +25,10 @@ static int monitor_handler(sd_device_monitor *m, sd_device *d, void *userdata) {
|
||||
return sd_event_exit(sd_device_monitor_get_event(m), 100);
|
||||
}
|
||||
|
||||
static int test_receive_device_fail(void) {
|
||||
static void test_receive_device_fail(void) {
|
||||
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
|
||||
_cleanup_(sd_device_unrefp) sd_device *loopback = NULL;
|
||||
const char *syspath;
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
@ -47,14 +47,8 @@ static int test_receive_device_fail(void) {
|
||||
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);
|
||||
|
||||
/* 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(device_monitor_send_device(monitor_server, monitor_client, loopback) >= 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) {
|
||||
@ -299,11 +293,10 @@ int main(int argc, char *argv[]) {
|
||||
if (getuid() != 0)
|
||||
return log_tests_skipped("not root");
|
||||
|
||||
r = test_receive_device_fail();
|
||||
if (r < 0) {
|
||||
assert_se(r == -EPERM && detect_container() > 0);
|
||||
if (path_is_read_only_fs("/sys") > 0)
|
||||
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(device_add_property(loopback, "ACTION", "add") >= 0);
|
||||
|
||||
@ -12,29 +12,6 @@
|
||||
#include "string-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) {
|
||||
size_t i, l;
|
||||
|
||||
@ -153,13 +130,13 @@ int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
|
||||
assert(f < _ID128_FORMAT_MAX);
|
||||
|
||||
if (f != ID128_UUID) {
|
||||
sd_id128_to_string(id, buffer);
|
||||
buffer[32] = '\n';
|
||||
sz = 33;
|
||||
assert_se(sd_id128_to_string(id, buffer));
|
||||
buffer[SD_ID128_STRING_MAX - 1] = '\n';
|
||||
sz = SD_ID128_STRING_MAX;
|
||||
} else {
|
||||
id128_to_uuid_string(id, buffer);
|
||||
buffer[36] = '\n';
|
||||
sz = 37;
|
||||
assert_se(sd_id128_to_uuid_string(id, buffer));
|
||||
buffer[SD_ID128_UUID_STRING_MAX - 1] = '\n';
|
||||
sz = SD_ID128_UUID_STRING_MAX;
|
||||
}
|
||||
|
||||
r = loop_write(fd, buffer, sz, false);
|
||||
@ -229,3 +206,19 @@ int id128_get_product(sd_id128_t *ret) {
|
||||
*ret = uuid;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -8,12 +8,6 @@
|
||||
#include "hash-funcs.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_;
|
||||
|
||||
typedef enum Id128Format {
|
||||
@ -40,3 +34,5 @@ extern const struct hash_ops id128_hash_ops;
|
||||
sd_id128_t id128_make_v4_uuid(sd_id128_t id);
|
||||
|
||||
int id128_get_product(sd_id128_t *ret);
|
||||
|
||||
int id128_equal_string(const char *s, sd_id128_t id);
|
||||
|
||||
@ -19,16 +19,36 @@
|
||||
#include "util.h"
|
||||
|
||||
_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);
|
||||
|
||||
for (n = 0; n < 16; n++) {
|
||||
for (size_t n = 0; n < 16; n++) {
|
||||
s[n*2] = hexchar(id.bytes[n] >> 4);
|
||||
s[n*2+1] = hexchar(id.bytes[n] & 0xF);
|
||||
}
|
||||
|
||||
s[32] = 0;
|
||||
s[SD_ID128_STRING_MAX-1] = 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;
|
||||
}
|
||||
|
||||
@ -1317,8 +1317,7 @@ static int add_any_file(
|
||||
|
||||
f = ordered_hashmap_get(j->files, path);
|
||||
if (f) {
|
||||
if (f->last_stat.st_dev == st.st_dev &&
|
||||
f->last_stat.st_ino == st.st_ino) {
|
||||
if (stat_inode_same(&f->last_stat, &st)) {
|
||||
|
||||
/* 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
|
||||
|
||||
@ -20,101 +20,99 @@
|
||||
|
||||
static const ActionTableItem action_table[_HANDLE_ACTION_MAX] = {
|
||||
[HANDLE_POWEROFF] = {
|
||||
SPECIAL_POWEROFF_TARGET,
|
||||
INHIBIT_SHUTDOWN,
|
||||
"org.freedesktop.login1.power-off",
|
||||
"org.freedesktop.login1.power-off-multiple-sessions",
|
||||
"org.freedesktop.login1.power-off-ignore-inhibit",
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_SHUTDOWN_STR,
|
||||
"System is powering down",
|
||||
"power-off",
|
||||
},
|
||||
.handle = HANDLE_POWEROFF,
|
||||
.target = SPECIAL_POWEROFF_TARGET,
|
||||
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||
.polkit_action = "org.freedesktop.login1.power-off",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit",
|
||||
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||
.message = "System is powering down",
|
||||
.log_message = "power-off",
|
||||
},
|
||||
[HANDLE_REBOOT] = {
|
||||
SPECIAL_REBOOT_TARGET,
|
||||
INHIBIT_SHUTDOWN,
|
||||
"org.freedesktop.login1.reboot",
|
||||
"org.freedesktop.login1.reboot-multiple-sessions",
|
||||
"org.freedesktop.login1.reboot-ignore-inhibit",
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_SHUTDOWN_STR,
|
||||
"System is rebooting",
|
||||
"reboot",
|
||||
},
|
||||
[HANDLE_HALT] = {
|
||||
SPECIAL_HALT_TARGET,
|
||||
INHIBIT_SHUTDOWN,
|
||||
"org.freedesktop.login1.halt",
|
||||
"org.freedesktop.login1.halt-multiple-sessions",
|
||||
"org.freedesktop.login1.halt-ignore-inhibit",
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_SHUTDOWN_STR,
|
||||
"System is halting",
|
||||
"halt",
|
||||
},
|
||||
[HANDLE_KEXEC] = {
|
||||
SPECIAL_KEXEC_TARGET,
|
||||
INHIBIT_SHUTDOWN,
|
||||
"org.freedesktop.login1.reboot",
|
||||
"org.freedesktop.login1.reboot-multiple-sessions",
|
||||
"org.freedesktop.login1.reboot-ignore-inhibit",
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_SHUTDOWN_STR,
|
||||
"System is rebooting with kexec",
|
||||
"kexec",
|
||||
},
|
||||
[HANDLE_SUSPEND] = {
|
||||
SPECIAL_SUSPEND_TARGET,
|
||||
INHIBIT_SLEEP,
|
||||
"org.freedesktop.login1.suspend",
|
||||
"org.freedesktop.login1.suspend-multiple-sessions",
|
||||
"org.freedesktop.login1.suspend-ignore-inhibit",
|
||||
SLEEP_SUSPEND,
|
||||
},
|
||||
[HANDLE_HIBERNATE] = {
|
||||
SPECIAL_HIBERNATE_TARGET,
|
||||
INHIBIT_SLEEP,
|
||||
"org.freedesktop.login1.hibernate",
|
||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
SLEEP_HIBERNATE,
|
||||
},
|
||||
[HANDLE_HYBRID_SLEEP] = {
|
||||
SPECIAL_HYBRID_SLEEP_TARGET,
|
||||
INHIBIT_SLEEP,
|
||||
"org.freedesktop.login1.hibernate",
|
||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
SLEEP_HYBRID_SLEEP,
|
||||
},
|
||||
[HANDLE_SUSPEND_THEN_HIBERNATE] = {
|
||||
SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
|
||||
INHIBIT_SLEEP,
|
||||
"org.freedesktop.login1.hibernate",
|
||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
SLEEP_SUSPEND_THEN_HIBERNATE,
|
||||
},
|
||||
[HANDLE_FACTORY_RESET] = {
|
||||
SPECIAL_FACTORY_RESET_TARGET,
|
||||
_INHIBIT_WHAT_INVALID,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
_SLEEP_OPERATION_INVALID,
|
||||
SD_MESSAGE_FACTORY_RESET_STR,
|
||||
"System is performing factory reset",
|
||||
NULL
|
||||
},
|
||||
.handle = HANDLE_REBOOT,
|
||||
.target = SPECIAL_REBOOT_TARGET,
|
||||
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||
.polkit_action = "org.freedesktop.login1.reboot",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit",
|
||||
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||
.message = "System is rebooting",
|
||||
.log_message = "reboot",
|
||||
},
|
||||
[HANDLE_HALT] = {
|
||||
.handle = HANDLE_HALT,
|
||||
.target = SPECIAL_HALT_TARGET,
|
||||
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||
.polkit_action = "org.freedesktop.login1.halt",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit",
|
||||
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||
.message = "System is halting",
|
||||
.log_message = "halt",
|
||||
},
|
||||
[HANDLE_KEXEC] = {
|
||||
.handle = HANDLE_KEXEC,
|
||||
.target = SPECIAL_KEXEC_TARGET,
|
||||
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||
.polkit_action = "org.freedesktop.login1.reboot",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit",
|
||||
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||
.message = "System is rebooting with kexec",
|
||||
.log_message = "kexec",
|
||||
},
|
||||
[HANDLE_SUSPEND] = {
|
||||
.handle = HANDLE_SUSPEND,
|
||||
.target = SPECIAL_SUSPEND_TARGET,
|
||||
.inhibit_what = INHIBIT_SLEEP,
|
||||
.polkit_action = "org.freedesktop.login1.suspend",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.suspend-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.suspend-ignore-inhibit",
|
||||
.sleep_operation = SLEEP_SUSPEND,
|
||||
},
|
||||
[HANDLE_HIBERNATE] = {
|
||||
.handle = HANDLE_HIBERNATE,
|
||||
.target = SPECIAL_HIBERNATE_TARGET,
|
||||
.inhibit_what = INHIBIT_SLEEP,
|
||||
.polkit_action = "org.freedesktop.login1.hibernate",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
.sleep_operation = SLEEP_HIBERNATE,
|
||||
},
|
||||
[HANDLE_HYBRID_SLEEP] = {
|
||||
.handle = HANDLE_HYBRID_SLEEP,
|
||||
.target = SPECIAL_HYBRID_SLEEP_TARGET,
|
||||
.inhibit_what = INHIBIT_SLEEP,
|
||||
.polkit_action = "org.freedesktop.login1.hibernate",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
.sleep_operation = SLEEP_HYBRID_SLEEP,
|
||||
},
|
||||
[HANDLE_SUSPEND_THEN_HIBERNATE] = {
|
||||
.handle = HANDLE_SUSPEND_THEN_HIBERNATE,
|
||||
.target = SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
|
||||
.inhibit_what = INHIBIT_SLEEP,
|
||||
.polkit_action = "org.freedesktop.login1.hibernate",
|
||||
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions",
|
||||
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||
.sleep_operation = SLEEP_SUSPEND_THEN_HIBERNATE,
|
||||
},
|
||||
[HANDLE_FACTORY_RESET] = {
|
||||
.handle = HANDLE_FACTORY_RESET,
|
||||
.target = SPECIAL_FACTORY_RESET_TARGET,
|
||||
.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) {
|
||||
assert(handle >= 0);
|
||||
assert(handle < (ssize_t) ELEMENTSOF(action_table));
|
||||
@ -122,12 +120,6 @@ const ActionTableItem* manager_item_for_handle(HandleAction 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(
|
||||
Manager *m,
|
||||
InhibitWhat inhibit_key,
|
||||
|
||||
@ -28,6 +28,7 @@ typedef struct ActionTableItem ActionTableItem;
|
||||
#include "sleep-config.h"
|
||||
|
||||
struct ActionTableItem {
|
||||
HandleAction handle;
|
||||
const char *target;
|
||||
InhibitWhat inhibit_what;
|
||||
const char *polkit_action;
|
||||
@ -36,8 +37,7 @@ struct ActionTableItem {
|
||||
SleepOperation sleep_operation;
|
||||
const char* message_id;
|
||||
const char* message;
|
||||
const char* log_str;
|
||||
|
||||
const char* log_message;
|
||||
};
|
||||
|
||||
int manager_handle_action(
|
||||
@ -50,7 +50,6 @@ int manager_handle_action(
|
||||
const char* handle_action_to_string(HandleAction h) _const_;
|
||||
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);
|
||||
HandleAction manager_handle_for_item(const ActionTableItem* a);
|
||||
|
||||
|
||||
@ -54,6 +54,15 @@
|
||||
#include "utmp-wtmp.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 int get_sender_session(
|
||||
@ -349,7 +358,7 @@ static int property_get_scheduled_shutdown(
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(reply, "st",
|
||||
handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)),
|
||||
m->scheduled_shutdown_type ? handle_action_to_string(m->scheduled_shutdown_type->handle) : NULL,
|
||||
m->scheduled_shutdown_timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1499,13 +1508,13 @@ static int bus_manager_log_shutdown(
|
||||
Manager *m,
|
||||
const ActionTableItem *a) {
|
||||
|
||||
const char *message, *log_str;
|
||||
const char *message, *log_message;
|
||||
|
||||
assert(m);
|
||||
assert(a);
|
||||
|
||||
message = a->message;
|
||||
log_str = a->log_str;
|
||||
log_message = a->log_message;
|
||||
|
||||
if (message)
|
||||
message = strjoina("MESSAGE=", message);
|
||||
@ -1517,13 +1526,13 @@ static int bus_manager_log_shutdown(
|
||||
else
|
||||
message = strjoina(message, " (", m->wall_message, ").");
|
||||
|
||||
if (log_str)
|
||||
log_str = strjoina("SHUTDOWN=", log_str);
|
||||
if (log_message)
|
||||
log_message = strjoina("SHUTDOWN=", log_message);
|
||||
|
||||
return log_struct(LOG_NOTICE,
|
||||
"MESSAGE_ID=%s", a->message_id ? a->message_id : SD_MESSAGE_SHUTDOWN_STR,
|
||||
message,
|
||||
log_str);
|
||||
log_message);
|
||||
}
|
||||
|
||||
static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
|
||||
@ -1884,7 +1893,7 @@ static int method_do_shutdown_or_sleep(
|
||||
return r;
|
||||
if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
|
||||
if (manager_handle_for_item(a) != HANDLE_REBOOT && (flags & SD_LOGIND_REBOOT_VIA_KEXEC))
|
||||
if (a->handle != 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");
|
||||
} else {
|
||||
/* Old style method: no flags parameter, but interactive bool passed as boolean in
|
||||
@ -2035,6 +2044,7 @@ static int update_schedule_file(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->scheduled_shutdown_type);
|
||||
|
||||
r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
|
||||
if (r < 0)
|
||||
@ -2052,7 +2062,7 @@ static int update_schedule_file(Manager *m) {
|
||||
"MODE=%s\n",
|
||||
m->scheduled_shutdown_timeout,
|
||||
m->enable_wall_messages,
|
||||
handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)));
|
||||
handle_action_to_string(m->scheduled_shutdown_type->handle));
|
||||
|
||||
if (!isempty(m->wall_message)) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
@ -2240,9 +2250,10 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
|
||||
assert(m);
|
||||
assert(message);
|
||||
|
||||
cancelled = !IN_SET(manager_handle_for_item(m->scheduled_shutdown_type), HANDLE_IGNORE, _HANDLE_ACTION_INVALID);
|
||||
cancelled = m->scheduled_shutdown_type
|
||||
&& !IN_SET(m->scheduled_shutdown_type->handle, HANDLE_IGNORE, _HANDLE_ACTION_INVALID);
|
||||
if (!cancelled)
|
||||
goto done;
|
||||
return sd_bus_reply_method_return(message, "b", false);
|
||||
|
||||
a = m->scheduled_shutdown_type;
|
||||
if (!a->polkit_action)
|
||||
@ -2281,8 +2292,7 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
|
||||
username, tty, logind_wall_tty_filter, m);
|
||||
}
|
||||
|
||||
done:
|
||||
return sd_bus_reply_method_return(message, "b", cancelled);
|
||||
return sd_bus_reply_method_return(message, "b", true);
|
||||
}
|
||||
|
||||
static int method_can_shutdown_or_sleep(
|
||||
@ -2328,7 +2338,7 @@ static int method_can_shutdown_or_sleep(
|
||||
if (handle >= 0) {
|
||||
const char *target;
|
||||
|
||||
target = manager_target_for_action(handle);
|
||||
target = manager_item_for_handle(handle)->target;
|
||||
if (target) {
|
||||
_cleanup_free_ char *load_state = NULL;
|
||||
|
||||
@ -2923,9 +2933,9 @@ static int boot_loader_entry_exists(Manager *m, const char *id) {
|
||||
|
||||
r = manager_read_efi_boot_loader_entries(m);
|
||||
if (r >= 0)
|
||||
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries);
|
||||
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, /* auto_only= */ true);
|
||||
|
||||
return boot_config_has_entry(&config, id);
|
||||
return !!boot_config_find_entry(&config, id);
|
||||
}
|
||||
|
||||
static int method_set_reboot_to_boot_loader_entry(
|
||||
@ -3081,7 +3091,7 @@ static int property_get_boot_loader_entries(
|
||||
|
||||
r = manager_read_efi_boot_loader_entries(m);
|
||||
if (r >= 0)
|
||||
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries);
|
||||
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, /* auto_only= */ true);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "s");
|
||||
if (r < 0)
|
||||
@ -3115,14 +3125,10 @@ static int method_set_wall_message(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* sysvinit has a 252 (256-(strlen(" \r\n")+1)) character
|
||||
* limit for the wall message. There is no real technical
|
||||
* need for that but doesn't make sense to store arbitrary
|
||||
* amounts either.
|
||||
* https://git.savannah.nongnu.org/cgit/sysvinit.git/tree/src/shutdown.c#n72)
|
||||
*/
|
||||
if (strlen(wall_message) > 252)
|
||||
return -EMSGSIZE;
|
||||
if (strlen(wall_message) > WALL_MESSAGE_MAX)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Wall message too long, maximum permitted length is %u characters.",
|
||||
WALL_MESSAGE_MAX);
|
||||
|
||||
/* Short-circuit the operation if the desired state is already in place, to
|
||||
* avoid an unnecessary polkit permission check. */
|
||||
|
||||
@ -64,7 +64,7 @@ static int warn_wall(Manager *m, usec_t n) {
|
||||
|
||||
assert(m);
|
||||
|
||||
if (!m->enable_wall_messages)
|
||||
if (!m->enable_wall_messages || !m->scheduled_shutdown_type)
|
||||
return 0;
|
||||
|
||||
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!",
|
||||
strempty(m->wall_message),
|
||||
isempty(m->wall_message) ? "" : "\n",
|
||||
handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)),
|
||||
handle_action_to_string(m->scheduled_shutdown_type->handle),
|
||||
left ? "at " : "NOW",
|
||||
left ? FORMAT_TIMESTAMP(m->scheduled_shutdown_timeout) : "");
|
||||
if (r < 0) {
|
||||
|
||||
@ -848,10 +848,6 @@ int link_drop_foreign_addresses(Link *link) {
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
|
||||
/* Keep all addresses when KeepConfiguration=yes. */
|
||||
if (link->network->keep_configuration == KEEP_CONFIGURATION_YES)
|
||||
return 0;
|
||||
|
||||
/* First, mark all addresses. */
|
||||
SET_FOREACH(address, link->addresses) {
|
||||
/* We consider IPv6LL addresses to be managed by the kernel, or dropped in link_drop_ipv6ll_addresses() */
|
||||
|
||||
@ -1240,10 +1240,13 @@ static int link_reconfigure_impl(Link *link, bool force) {
|
||||
|
||||
link_drop_requests(link);
|
||||
|
||||
if (network && !force)
|
||||
if (network && !force && network->keep_configuration != KEEP_CONFIGURATION_YES)
|
||||
/* 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
|
||||
* 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);
|
||||
else {
|
||||
/* Remove all managed configs. Note, foreign configs are removed in later by
|
||||
|
||||
@ -3453,7 +3453,7 @@ static int inner_child(
|
||||
|
||||
assert(!sd_id128_is_null(arg_uuid));
|
||||
|
||||
if (asprintf(envp + n_env++, "container_uuid=%s", ID128_TO_UUID_STRING(arg_uuid)) < 0)
|
||||
if (asprintf(envp + n_env++, "container_uuid=%s", SD_ID128_TO_UUID_STRING(arg_uuid)) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (fdset_size(fds) > 0) {
|
||||
|
||||
@ -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)
|
||||
return -EINVAL;
|
||||
|
||||
ids = new(char, ID128_UUID_STRING_MAX);
|
||||
ids = new(char, SD_ID128_UUID_STRING_MAX);
|
||||
if (!ids)
|
||||
return -ENOMEM;
|
||||
|
||||
r = fdisk_ask_string_set_result(ask, id128_to_uuid_string(*(sd_id128_t*) data, ids));
|
||||
r = fdisk_ask_string_set_result(ask, sd_id128_to_uuid_string(*(sd_id128_t*) data, ids));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -2030,7 +2030,7 @@ static int context_dump_partitions(Context *context, const char *node) {
|
||||
|
||||
LIST_FOREACH(partitions, p, context->partitions) {
|
||||
_cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL;
|
||||
char uuid_buffer[ID128_UUID_STRING_MAX];
|
||||
char uuid_buffer[SD_ID128_UUID_STRING_MAX];
|
||||
const char *label, *activity = NULL;
|
||||
|
||||
if (p->dropped)
|
||||
@ -2176,7 +2176,7 @@ static int partition_hint(const Partition *p, const char *node, char **ret) {
|
||||
else
|
||||
id = p->type_uuid;
|
||||
|
||||
buf = strdup(ID128_TO_UUID_STRING(id));
|
||||
buf = strdup(SD_ID128_TO_UUID_STRING(id));
|
||||
|
||||
done:
|
||||
if (!buf)
|
||||
@ -2624,7 +2624,7 @@ static int partition_encrypt(
|
||||
CRYPT_LUKS2,
|
||||
"aes",
|
||||
"xts-plain64",
|
||||
ID128_TO_UUID_STRING(uuid),
|
||||
SD_ID128_TO_UUID_STRING(uuid),
|
||||
volume_key,
|
||||
volume_key_size,
|
||||
&(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))
|
||||
SET_FLAG(f, GPT_FLAG_NO_AUTO, p->no_auto);
|
||||
else {
|
||||
char buffer[ID128_UUID_STRING_MAX];
|
||||
char buffer[SD_ID128_UUID_STRING_MAX];
|
||||
log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.",
|
||||
yes_no(p->no_auto),
|
||||
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))
|
||||
SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
|
||||
else {
|
||||
char buffer[ID128_UUID_STRING_MAX];
|
||||
char buffer[SD_ID128_UUID_STRING_MAX];
|
||||
log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
|
||||
yes_no(p->read_only),
|
||||
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))
|
||||
SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs);
|
||||
else {
|
||||
char buffer[ID128_UUID_STRING_MAX];
|
||||
char buffer[SD_ID128_UUID_STRING_MAX];
|
||||
log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
|
||||
yes_no(p->growfs),
|
||||
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)) {
|
||||
assert(!sd_id128_is_null(p->new_uuid));
|
||||
|
||||
r = fdisk_partition_set_uuid(p->current_partition, ID128_TO_UUID_STRING(p->new_uuid));
|
||||
r = fdisk_partition_set_uuid(p->current_partition, SD_ID128_TO_UUID_STRING(p->new_uuid));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set partition UUID: %m");
|
||||
|
||||
@ -3412,7 +3412,7 @@ static int context_mangle_partitions(Context *context) {
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
r = fdisk_parttype_set_typestr(t, ID128_TO_UUID_STRING(p->type_uuid));
|
||||
r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type_uuid));
|
||||
if (r < 0)
|
||||
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)
|
||||
return log_error_errno(r, "Failed to set partition number: %m");
|
||||
|
||||
r = fdisk_partition_set_uuid(q, ID128_TO_UUID_STRING(p->new_uuid));
|
||||
r = fdisk_partition_set_uuid(q, SD_ID128_TO_UUID_STRING(p->new_uuid));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set partition UUID: %m");
|
||||
|
||||
|
||||
@ -41,8 +41,7 @@ int manager_check_resolv_conf(const Manager *m) {
|
||||
|
||||
/* Is it symlinked to our own uplink file? */
|
||||
if (stat(PRIVATE_STATIC_RESOLV_CONF, &own) >= 0 &&
|
||||
st.st_dev == own.st_dev &&
|
||||
st.st_ino == own.st_ino)
|
||||
stat_inode_same(&st, &own))
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to "
|
||||
PRIVATE_STATIC_RESOLV_CONF " which expects DNSStubListener= to be enabled.");
|
||||
@ -64,8 +63,7 @@ static bool file_is_our_own(const struct stat *st) {
|
||||
|
||||
/* Is it symlinked to our own uplink file? */
|
||||
if (stat(path, &own) >= 0 &&
|
||||
st->st_dev == own.st_dev &&
|
||||
st->st_ino == own.st_ino)
|
||||
stat_inode_same(st, &own))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -418,8 +416,7 @@ int resolv_conf_mode(void) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (system_st.st_dev == our_st.st_dev &&
|
||||
system_st.st_ino == our_st.st_ino)
|
||||
if (stat_inode_same(&system_st, &our_st))
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "gpt.h"
|
||||
#include "id128-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pe-header.h"
|
||||
@ -51,6 +53,7 @@ static void boot_entry_free(BootEntry *entry) {
|
||||
free(entry->efi);
|
||||
strv_free(entry->initrd);
|
||||
free(entry->device_tree);
|
||||
strv_free(entry->device_tree_overlay);
|
||||
}
|
||||
|
||||
static int boot_entry_load(
|
||||
@ -64,26 +67,28 @@ static int boot_entry_load(
|
||||
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
unsigned line = 1;
|
||||
char *b, *c;
|
||||
char *c;
|
||||
int r;
|
||||
|
||||
assert(root);
|
||||
assert(path);
|
||||
assert(entry);
|
||||
|
||||
c = endswith_no_case(path, ".conf");
|
||||
if (!c)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", path);
|
||||
r = path_extract_filename(path, &tmp.id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract file name from path '%s': %m", path);
|
||||
|
||||
b = basename(path);
|
||||
tmp.id = strdup(b);
|
||||
tmp.id_old = strndup(b, c - b);
|
||||
if (!tmp.id || !tmp.id_old)
|
||||
return log_oom();
|
||||
c = endswith_no_case(tmp.id, ".conf");
|
||||
if (!c)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", tmp.id);
|
||||
|
||||
if (!efi_loader_entry_name_valid(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);
|
||||
if (!tmp.path)
|
||||
return log_oom();
|
||||
@ -142,7 +147,15 @@ static int boot_entry_load(
|
||||
r = strv_extend(&tmp.initrd, p);
|
||||
else if (streq(field, "devicetree"))
|
||||
r = free_and_strdup(&tmp.device_tree, p);
|
||||
else {
|
||||
else if (streq(field, "devicetree-overlay")) {
|
||||
_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);
|
||||
continue;
|
||||
}
|
||||
@ -167,9 +180,11 @@ void boot_config_free(BootConfig *config) {
|
||||
free(config->auto_firmware);
|
||||
free(config->console_mode);
|
||||
free(config->random_seed_mode);
|
||||
free(config->beep);
|
||||
|
||||
free(config->entry_oneshot);
|
||||
free(config->entry_default);
|
||||
free(config->entry_selected);
|
||||
|
||||
for (i = 0; i < config->n_entries; i++)
|
||||
boot_entry_free(config->entries + i);
|
||||
@ -234,6 +249,8 @@ static int boot_loader_read_conf(const char *path, BootConfig *config) {
|
||||
r = free_and_strdup(&config->console_mode, p);
|
||||
else if (streq(field, "random-seed-mode"))
|
||||
r = free_and_strdup(&config->random_seed_mode, p);
|
||||
else if (streq(field, "beep"))
|
||||
r = free_and_strdup(&config->beep, p);
|
||||
else {
|
||||
log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field);
|
||||
continue;
|
||||
@ -546,18 +563,17 @@ static int boot_entries_find_unified(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) {
|
||||
size_t i, j;
|
||||
static bool find_nonunique(const BootEntry *entries, size_t n_entries, bool arr[]) {
|
||||
bool non_unique = false;
|
||||
|
||||
assert(entries || n_entries == 0);
|
||||
assert(arr || n_entries == 0);
|
||||
|
||||
for (i = 0; i < n_entries; i++)
|
||||
for (size_t i = 0; i < n_entries; i++)
|
||||
arr[i] = false;
|
||||
|
||||
for (i = 0; i < n_entries; i++)
|
||||
for (j = 0; j < n_entries; j++)
|
||||
for (size_t i = 0; i < n_entries; i++)
|
||||
for (size_t j = 0; j < n_entries; j++)
|
||||
if (i != j && streq(boot_entry_title(entries + i),
|
||||
boot_entry_title(entries + j)))
|
||||
non_unique = arr[i] = arr[j] = true;
|
||||
@ -566,22 +582,26 @@ static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) {
|
||||
}
|
||||
|
||||
static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
|
||||
_cleanup_free_ bool *arr = NULL;
|
||||
char *s;
|
||||
size_t i;
|
||||
int r;
|
||||
bool arr[n_entries];
|
||||
|
||||
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 */
|
||||
if (!find_nonunique(entries, n_entries, arr))
|
||||
return 0;
|
||||
|
||||
/* Add version to non-unique titles */
|
||||
for (i = 0; i < n_entries; i++)
|
||||
for (size_t i = 0; i < n_entries; i++)
|
||||
if (arr[i] && entries[i].version) {
|
||||
r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version);
|
||||
if (r < 0)
|
||||
if (asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
free_and_replace(entries[i].show_title, s);
|
||||
@ -591,10 +611,9 @@ static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
|
||||
return 0;
|
||||
|
||||
/* Add machine-id to non-unique titles */
|
||||
for (i = 0; i < n_entries; i++)
|
||||
for (size_t i = 0; i < n_entries; i++)
|
||||
if (arr[i] && entries[i].machine_id) {
|
||||
r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id);
|
||||
if (r < 0)
|
||||
if (asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
free_and_replace(entries[i].show_title, s);
|
||||
@ -604,10 +623,9 @@ static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
|
||||
return 0;
|
||||
|
||||
/* Add file name to non-unique titles */
|
||||
for (i = 0; i < n_entries; i++)
|
||||
for (size_t i = 0; i < n_entries; i++)
|
||||
if (arr[i]) {
|
||||
r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].id);
|
||||
if (r < 0)
|
||||
if (asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].id) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
free_and_replace(entries[i].show_title, s);
|
||||
@ -655,6 +673,55 @@ static int boot_entries_select_default(const BootConfig *config) {
|
||||
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(
|
||||
const char *esp_path,
|
||||
const char *xbootldr_path,
|
||||
@ -700,23 +767,13 @@ int boot_entries_load_config(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to uniquify boot entries: %m");
|
||||
|
||||
if (is_efi_boot()) {
|
||||
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 = boot_load_efi_entry_pointers(config);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
config->default_entry = boot_entries_select_default(config);
|
||||
config->selected_entry = boot_entries_select_selected(config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -726,6 +783,7 @@ int boot_entries_load_config_auto(
|
||||
BootConfig *config) {
|
||||
|
||||
_cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL;
|
||||
dev_t esp_devid = 0, xbootldr_devid = 0;
|
||||
int r;
|
||||
|
||||
assert(config);
|
||||
@ -746,20 +804,25 @@ int boot_entries_load_config_auto(
|
||||
"Failed to determine whether /run/boot-loader-entries/ exists: %m");
|
||||
}
|
||||
|
||||
r = find_esp_and_warn(override_esp_path, false, &esp_where, NULL, NULL, NULL, NULL);
|
||||
r = find_esp_and_warn(override_esp_path, /* unprivileged_mode= */ false, &esp_where, NULL, NULL, NULL, NULL, &esp_devid);
|
||||
if (r < 0) /* we don't log about ENOKEY here, but propagate it, leaving it to the caller to log */
|
||||
return r;
|
||||
|
||||
r = find_xbootldr_and_warn(override_xbootldr_path, false, &xbootldr_where, NULL);
|
||||
r = find_xbootldr_and_warn(override_xbootldr_path, /* unprivileged_mode= */ false, &xbootldr_where, NULL, &xbootldr_devid);
|
||||
if (r < 0 && r != -ENOKEY)
|
||||
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);
|
||||
}
|
||||
|
||||
int boot_entries_augment_from_loader(
|
||||
BootConfig *config,
|
||||
char **found_by_loader) {
|
||||
char **found_by_loader,
|
||||
bool only_auto) {
|
||||
|
||||
static const char *const title_table[] = {
|
||||
/* Pretty names for a few well-known automatically discovered entries. */
|
||||
@ -778,18 +841,17 @@ int boot_entries_augment_from_loader(
|
||||
* already included there. */
|
||||
|
||||
STRV_FOREACH(i, found_by_loader) {
|
||||
BootEntry *existing;
|
||||
_cleanup_free_ char *c = NULL, *t = NULL, *p = NULL;
|
||||
char **a, **b;
|
||||
|
||||
if (boot_config_has_entry(config, *i))
|
||||
existing = boot_config_find_entry(config, *i);
|
||||
if (existing) {
|
||||
existing->reported_by_loader = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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-"))
|
||||
if (only_auto && !startswith(*i, "auto-"))
|
||||
continue;
|
||||
|
||||
c = strdup(*i);
|
||||
@ -812,10 +874,11 @@ int boot_entries_augment_from_loader(
|
||||
return log_oom();
|
||||
|
||||
config->entries[config->n_entries++] = (BootEntry) {
|
||||
.type = BOOT_ENTRY_LOADER,
|
||||
.type = startswith(*i, "auto-") ? BOOT_ENTRY_LOADER_AUTO : BOOT_ENTRY_LOADER,
|
||||
.id = TAKE_PTR(c),
|
||||
.title = TAKE_PTR(t),
|
||||
.path = TAKE_PTR(p),
|
||||
.reported_by_loader = true,
|
||||
};
|
||||
}
|
||||
|
||||
@ -889,7 +952,7 @@ static int verify_esp_blkid(
|
||||
r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
|
||||
if (r != 0)
|
||||
return log_error_errno(errno ?: EIO, "Failed to probe partition type UUID of \"%s\": %m", node);
|
||||
if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"))
|
||||
if (id128_equal_string(v, GPT_ESP) <= 0)
|
||||
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
||||
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
|
||||
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
|
||||
@ -982,7 +1045,7 @@ static int verify_esp_udev(
|
||||
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get device property: %m");
|
||||
if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"))
|
||||
if (id128_equal_string(v, GPT_ESP) <= 0)
|
||||
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
||||
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
|
||||
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
|
||||
@ -1107,7 +1170,8 @@ static int verify_esp(
|
||||
uint32_t *ret_part,
|
||||
uint64_t *ret_pstart,
|
||||
uint64_t *ret_psize,
|
||||
sd_id128_t *ret_uuid) {
|
||||
sd_id128_t *ret_uuid,
|
||||
dev_t *ret_devid) {
|
||||
|
||||
bool relax_checks;
|
||||
dev_t devid;
|
||||
@ -1157,9 +1221,16 @@ static int verify_esp(
|
||||
* however blkid can't work if we have no privileges to access block devices directly, which is why
|
||||
* we use udev in that case. */
|
||||
if (unprivileged_mode)
|
||||
return verify_esp_udev(devid, searching, ret_part, ret_pstart, ret_psize, ret_uuid);
|
||||
r = verify_esp_udev(devid, searching, ret_part, ret_pstart, ret_psize, ret_uuid);
|
||||
else
|
||||
return verify_esp_blkid(devid, searching, ret_part, ret_pstart, ret_psize, ret_uuid);
|
||||
r = 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:
|
||||
if (ret_part)
|
||||
@ -1170,6 +1241,8 @@ finish:
|
||||
*ret_psize = 0;
|
||||
if (ret_uuid)
|
||||
*ret_uuid = SD_ID128_NULL;
|
||||
if (ret_devid)
|
||||
*ret_devid = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1181,7 +1254,8 @@ int find_esp_and_warn(
|
||||
uint32_t *ret_part,
|
||||
uint64_t *ret_pstart,
|
||||
uint64_t *ret_psize,
|
||||
sd_id128_t *ret_uuid) {
|
||||
sd_id128_t *ret_uuid,
|
||||
dev_t *ret_devid) {
|
||||
|
||||
int r;
|
||||
|
||||
@ -1192,7 +1266,7 @@ int find_esp_and_warn(
|
||||
*/
|
||||
|
||||
if (path) {
|
||||
r = verify_esp(path, false, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid);
|
||||
r = verify_esp(path, /* searching= */ false, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1201,19 +1275,39 @@ int find_esp_and_warn(
|
||||
|
||||
path = getenv("SYSTEMD_ESP_PATH");
|
||||
if (path) {
|
||||
struct stat st;
|
||||
|
||||
if (!path_is_valid(path) || !path_is_absolute(path))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"$SYSTEMD_ESP_PATH does not refer to absolute path, refusing to use it: %s",
|
||||
path);
|
||||
|
||||
/* Note: when the user explicitly configured things with an env var we won't validate the mount
|
||||
* point. After all we want this to be useful for testing. */
|
||||
/* Note: when the user explicitly configured things with an env var we won't validate the
|
||||
* path beyond checking it refers to a directory. After all we want this to be useful for
|
||||
* 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;
|
||||
}
|
||||
|
||||
FOREACH_STRING(path, "/efi", "/boot", "/boot/efi") {
|
||||
|
||||
r = verify_esp(path, true, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid);
|
||||
r = verify_esp(path, /* searching= */ true, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid);
|
||||
if (r >= 0)
|
||||
goto found;
|
||||
if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
|
||||
@ -1280,7 +1374,7 @@ static int verify_xbootldr_blkid(
|
||||
r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
|
||||
if (r != 0)
|
||||
return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition type UUID of \"%s\": %m", node);
|
||||
if (!streq(v, "bc13c2ff-59e6-4262-a352-b275fd6f7172"))
|
||||
if (id128_equal_string(v, GPT_XBOOTLDR) <= 0)
|
||||
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
||||
searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV),
|
||||
"File system \"%s\" has wrong type for extended boot loader partition.", node);
|
||||
@ -1344,7 +1438,7 @@ static int verify_xbootldr_udev(
|
||||
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get device property: %m");
|
||||
if (!streq(v, "bc13c2ff-59e6-4262-a352-b275fd6f7172"))
|
||||
if (id128_equal_string(v, GPT_XBOOTLDR))
|
||||
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
||||
searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV),
|
||||
"File system \"%s\" has wrong type for extended boot loader partition.", node);
|
||||
@ -1380,7 +1474,8 @@ static int verify_xbootldr(
|
||||
const char *p,
|
||||
bool searching,
|
||||
bool unprivileged_mode,
|
||||
sd_id128_t *ret_uuid) {
|
||||
sd_id128_t *ret_uuid,
|
||||
dev_t *ret_devid) {
|
||||
|
||||
bool relax_checks;
|
||||
dev_t devid;
|
||||
@ -1398,13 +1493,22 @@ static int verify_xbootldr(
|
||||
goto finish;
|
||||
|
||||
if (unprivileged_mode)
|
||||
return verify_xbootldr_udev(devid, searching, ret_uuid);
|
||||
r = verify_xbootldr_udev(devid, searching, ret_uuid);
|
||||
else
|
||||
return verify_xbootldr_blkid(devid, searching, ret_uuid);
|
||||
r = verify_xbootldr_blkid(devid, searching, ret_uuid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_devid)
|
||||
*ret_devid = devid;
|
||||
|
||||
return 0;
|
||||
|
||||
finish:
|
||||
if (ret_uuid)
|
||||
*ret_uuid = SD_ID128_NULL;
|
||||
if (ret_devid)
|
||||
*ret_devid = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1413,14 +1517,15 @@ int find_xbootldr_and_warn(
|
||||
const char *path,
|
||||
bool unprivileged_mode,
|
||||
char **ret_path,
|
||||
sd_id128_t *ret_uuid) {
|
||||
sd_id128_t *ret_uuid,
|
||||
dev_t *ret_devid) {
|
||||
|
||||
int r;
|
||||
|
||||
/* Similar to find_esp_and_warn(), but finds the XBOOTLDR partition. Returns the same errors. */
|
||||
|
||||
if (path) {
|
||||
r = verify_xbootldr(path, false, unprivileged_mode, ret_uuid);
|
||||
r = verify_xbootldr(path, /* searching= */ false, unprivileged_mode, ret_uuid, ret_devid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1429,15 +1534,27 @@ int find_xbootldr_and_warn(
|
||||
|
||||
path = getenv("SYSTEMD_XBOOTLDR_PATH");
|
||||
if (path) {
|
||||
struct stat st;
|
||||
|
||||
if (!path_is_valid(path) || !path_is_absolute(path))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"$SYSTEMD_XBOOTLDR_PATH does not refer to absolute path, refusing to use it: %s",
|
||||
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;
|
||||
}
|
||||
|
||||
r = verify_xbootldr("/boot", true, unprivileged_mode, ret_uuid);
|
||||
r = verify_xbootldr("/boot", true, unprivileged_mode, ret_uuid, ret_devid);
|
||||
if (r >= 0) {
|
||||
path = "/boot";
|
||||
goto found;
|
||||
|
||||
@ -11,15 +11,17 @@
|
||||
#include "string-util.h"
|
||||
|
||||
typedef enum BootEntryType {
|
||||
BOOT_ENTRY_CONF, /* Type #1 entries: *.conf files */
|
||||
BOOT_ENTRY_UNIFIED, /* Type #2 entries: *.efi files */
|
||||
BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI var */
|
||||
_BOOT_ENTRY_MAX,
|
||||
_BOOT_ENTRY_INVALID = -EINVAL,
|
||||
BOOT_ENTRY_CONF, /* Boot Loader Specification Type #1 entries: *.conf files */
|
||||
BOOT_ENTRY_UNIFIED, /* Boot Loader Specification Type #2 entries: *.efi files */
|
||||
BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI variable (regular entries) */
|
||||
BOOT_ENTRY_LOADER_AUTO, /* Additional entries augmented from LoaderEntries EFI variable (special "automatic" entries) */
|
||||
_BOOT_ENTRY_TYPE_MAX,
|
||||
_BOOT_ENTRY_TYPE_INVALID = -EINVAL,
|
||||
} BootEntryType;
|
||||
|
||||
typedef struct BootEntry {
|
||||
BootEntryType type;
|
||||
bool reported_by_loader;
|
||||
char *id; /* This is the file basename (including extension!) */
|
||||
char *id_old; /* Old-style ID, for deduplication purposes. */
|
||||
char *path; /* This is the full path to the drop-in file */
|
||||
@ -34,6 +36,7 @@ typedef struct BootEntry {
|
||||
char *efi;
|
||||
char **initrd;
|
||||
char *device_tree;
|
||||
char **device_tree_overlay;
|
||||
} BootEntry;
|
||||
|
||||
typedef struct BootConfig {
|
||||
@ -44,29 +47,33 @@ typedef struct BootConfig {
|
||||
char *auto_firmware;
|
||||
char *console_mode;
|
||||
char *random_seed_mode;
|
||||
char *beep;
|
||||
|
||||
char *entry_oneshot;
|
||||
char *entry_default;
|
||||
char *entry_selected;
|
||||
|
||||
BootEntry *entries;
|
||||
size_t n_entries;
|
||||
ssize_t default_entry;
|
||||
ssize_t selected_entry;
|
||||
} BootConfig;
|
||||
|
||||
static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
|
||||
size_t j;
|
||||
static inline BootEntry* boot_config_find_entry(BootConfig *config, const char *id) {
|
||||
assert(config);
|
||||
assert(id);
|
||||
|
||||
for (j = 0; j < config->n_entries; j++) {
|
||||
const char* entry_id_old = config->entries[j].id_old;
|
||||
if (streq(config->entries[j].id, id) ||
|
||||
(entry_id_old && streq(entry_id_old, id)))
|
||||
return true;
|
||||
}
|
||||
for (size_t j = 0; j < config->n_entries; j++)
|
||||
if (streq_ptr(config->entries[j].id, id) ||
|
||||
streq_ptr(config->entries[j].id_old, id))
|
||||
return config->entries + j;
|
||||
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline BootEntry* boot_config_default_entry(BootConfig *config) {
|
||||
assert(config);
|
||||
|
||||
if (config->default_entry < 0)
|
||||
return NULL;
|
||||
|
||||
@ -76,11 +83,13 @@ static inline BootEntry* boot_config_default_entry(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_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config);
|
||||
int boot_entries_augment_from_loader(BootConfig *config, char **list);
|
||||
int boot_entries_augment_from_loader(BootConfig *config, char **list, bool only_auto);
|
||||
|
||||
static inline const char* boot_entry_title(const BootEntry *entry) {
|
||||
assert(entry);
|
||||
|
||||
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);
|
||||
int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid);
|
||||
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_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid, dev_t *ret_devid);
|
||||
|
||||
@ -1699,11 +1699,11 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
|
||||
case TABLE_UUID: {
|
||||
char *p;
|
||||
|
||||
p = new(char, ID128_UUID_STRING_MAX);
|
||||
p = new(char, SD_ID128_UUID_STRING_MAX);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
d->formatted = id128_to_uuid_string(d->id128, p);
|
||||
d->formatted = sd_id128_to_uuid_string(d->id128, p);
|
||||
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));
|
||||
|
||||
case TABLE_UUID:
|
||||
return json_variant_new_string(ret, ID128_TO_UUID_STRING(d->id128));
|
||||
return json_variant_new_string(ret, SD_ID128_TO_UUID_STRING(d->id128));
|
||||
|
||||
case TABLE_UID:
|
||||
if (!uid_is_valid(d->uid))
|
||||
|
||||
@ -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(
|
||||
sd_id128_t id,
|
||||
char buffer[static ID128_UUID_STRING_MAX]) {
|
||||
char buffer[static SD_ID128_UUID_STRING_MAX]) {
|
||||
|
||||
const char *s;
|
||||
|
||||
@ -85,7 +85,7 @@ const char *gpt_partition_type_uuid_to_string_harder(
|
||||
if (s)
|
||||
return s;
|
||||
|
||||
return id128_to_uuid_string(id, buffer);
|
||||
return sd_id128_to_uuid_string(id, buffer);
|
||||
}
|
||||
|
||||
int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret) {
|
||||
|
||||
@ -286,7 +286,7 @@
|
||||
const char *gpt_partition_type_uuid_to_string(sd_id128_t id);
|
||||
const char *gpt_partition_type_uuid_to_string_harder(
|
||||
sd_id128_t id,
|
||||
char buffer[static ID128_UUID_STRING_MAX]);
|
||||
char buffer[static SD_ID128_UUID_STRING_MAX]);
|
||||
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);
|
||||
|
||||
@ -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) {
|
||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
|
||||
char buf[ID128_UUID_STRING_MAX];
|
||||
char buf[SD_ID128_UUID_STRING_MAX];
|
||||
pid_t pid, child;
|
||||
ssize_t k;
|
||||
int r;
|
||||
|
||||
@ -94,7 +94,7 @@ int make_filesystem(
|
||||
bool discard) {
|
||||
|
||||
_cleanup_free_ char *mkfs = NULL, *mangled_label = NULL;
|
||||
char vol_id[CONST_MAX(ID128_UUID_STRING_MAX, 8 + 1)] = {};
|
||||
char vol_id[CONST_MAX(SD_ID128_UUID_STRING_MAX, 8U + 1U)] = {};
|
||||
int r;
|
||||
|
||||
assert(node);
|
||||
@ -144,7 +144,7 @@ int make_filesystem(
|
||||
}
|
||||
|
||||
if (isempty(vol_id))
|
||||
id128_to_uuid_string(uuid, vol_id);
|
||||
assert_se(sd_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);
|
||||
if (r < 0)
|
||||
|
||||
@ -816,7 +816,7 @@ static int mount_in_namespace(
|
||||
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 */
|
||||
if (st.st_ino == self_mntns_st.st_ino && st.st_dev == self_mntns_st.st_dev)
|
||||
if (stat_inode_same(&st, &self_mntns_st))
|
||||
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
|
||||
|
||||
@ -351,7 +351,7 @@ void log_device_uevent(sd_device *device, const char *str) {
|
||||
strempty(str), isempty(str) ? "" : " ",
|
||||
seqnum, strna(device_action_to_string(action)),
|
||||
sd_id128_is_null(event_id) ? "" : ", UUID=",
|
||||
sd_id128_is_null(event_id) ? "" : id128_to_uuid_string(event_id, (char[ID128_UUID_STRING_MAX]){}));
|
||||
sd_id128_is_null(event_id) ? "" : SD_ID128_TO_UUID_STRING(event_id));
|
||||
}
|
||||
|
||||
int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) {
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "systemctl-compat-halt.h"
|
||||
#include "systemctl-compat-telinit.h"
|
||||
#include "systemctl-logind.h"
|
||||
#include "systemctl-start-unit.h"
|
||||
#include "systemctl-util.h"
|
||||
#include "systemctl.h"
|
||||
#include "terminal-util.h"
|
||||
@ -144,30 +145,32 @@ int halt_parse_argv(int argc, char *argv[]) {
|
||||
int halt_main(void) {
|
||||
int r;
|
||||
|
||||
/* always try logind first */
|
||||
if (arg_when > 0)
|
||||
r = logind_schedule_shutdown();
|
||||
else {
|
||||
r = logind_check_inhibitors(arg_action);
|
||||
if (r < 0)
|
||||
if (arg_force == 0) {
|
||||
/* always try logind first */
|
||||
if (arg_when > 0)
|
||||
r = logind_schedule_shutdown();
|
||||
else {
|
||||
r = logind_check_inhibitors(arg_action);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = logind_reboot(arg_action);
|
||||
}
|
||||
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 */
|
||||
|
||||
r = logind_reboot(arg_action);
|
||||
/* 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)
|
||||
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) {
|
||||
(void) must_be_root();
|
||||
|
||||
@ -35,11 +35,14 @@ union sd_id128 {
|
||||
};
|
||||
|
||||
#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_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);
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
TEST(id128) {
|
||||
sd_id128_t id, id2;
|
||||
char t[SD_ID128_STRING_MAX], q[ID128_UUID_STRING_MAX];
|
||||
char t[SD_ID128_STRING_MAX], q[SD_ID128_UUID_STRING_MAX];
|
||||
_cleanup_free_ char *b = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
@ -53,7 +53,7 @@ TEST(id128) {
|
||||
printf("waldi2: %s\n", b);
|
||||
assert_se(streq(t, b));
|
||||
|
||||
printf("waldi3: %s\n", id128_to_uuid_string(ID128_WALDI, q));
|
||||
printf("waldi3: %s\n", sd_id128_to_uuid_string(ID128_WALDI, q));
|
||||
assert_se(streq(q, UUID_WALDI));
|
||||
|
||||
b = mfree(b);
|
||||
@ -136,7 +136,7 @@ TEST(id128) {
|
||||
assert_se(ftruncate(fd, 0) >= 0);
|
||||
|
||||
assert_se(sd_id128_randomize(&id) >= 0);
|
||||
assert_se(write(fd, id128_to_uuid_string(id, q), 36) == 36);
|
||||
assert_se(write(fd, sd_id128_to_uuid_string(id, q), 36) == 36);
|
||||
|
||||
assert_se(lseek(fd, 0, SEEK_SET) == 0);
|
||||
assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL);
|
||||
|
||||
@ -213,7 +213,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
return log_oom();
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "usrhash")) {
|
||||
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
@ -285,7 +285,7 @@ static int determine_device(
|
||||
if (!*data_what) {
|
||||
memcpy(&data_uuid, m, sizeof(data_uuid));
|
||||
|
||||
*data_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(data_uuid));
|
||||
*data_what = path_join("/dev/disk/by-partuuid", SD_ID128_TO_UUID_STRING(data_uuid));
|
||||
if (!*data_what)
|
||||
return log_oom();
|
||||
}
|
||||
@ -293,7 +293,7 @@ static int determine_device(
|
||||
if (!*hash_what) {
|
||||
memcpy(&verity_uuid, (uint8_t*) m + l - sizeof(verity_uuid), sizeof(verity_uuid));
|
||||
|
||||
*hash_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(verity_uuid));
|
||||
*hash_what = path_join("/dev/disk/by-partuuid", SD_ID128_TO_UUID_STRING(verity_uuid));
|
||||
if (!*hash_what)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
@ -1070,6 +1070,9 @@ install_compiled_systemd() {
|
||||
if get_bool "$IS_BUILT_WITH_COVERAGE"; then
|
||||
mkdir -p "${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
|
||||
}
|
||||
|
||||
@ -1384,6 +1387,20 @@ check_coverage_reports() {
|
||||
lcov --remove "${dest}" -o "${dest}" '/usr/include/*' '/usr/lib/*'
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user