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:
|
Features:
|
||||||
|
|
||||||
|
* bootspec: remove tries counter from boot entry ids
|
||||||
|
|
||||||
* automatically ignore threaded cgroups in cg_xyz().
|
* automatically ignore threaded cgroups in cg_xyz().
|
||||||
|
|
||||||
* add linker script that implicitly adds symbol for build ID and new coredump
|
* add linker script that implicitly adds symbol for build ID and new coredump
|
||||||
|
|||||||
@ -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
|
that the service's main cgroup is definitely an inner node by the time the
|
||||||
service manager might start `ExecStartPost=`.)
|
service manager might start `ExecStartPost=`.)
|
||||||
|
|
||||||
|
(Also note, if you intend to use "threaded" cgroups — as added in Linux 4.14 —,
|
||||||
|
then you should do that *two* levels down from the main service cgroup your
|
||||||
|
turned delegation on for. Why that? You need one level so that systemd can
|
||||||
|
properly create the `.control` subgroup, as described above. But that one
|
||||||
|
cannot be threaded, since that would mean `.control` has to be threaded too —
|
||||||
|
this is a requirement of threaded cgroups: either a cgroup and all its siblings
|
||||||
|
are threaded or none –, but systemd expects it to be a regular cgroup. Thus you
|
||||||
|
have to nest a second cgroup beneath it which then can be threaded.)
|
||||||
|
|
||||||
## Three Scenarios
|
## Three Scenarios
|
||||||
|
|
||||||
Let's say you write a container manager, and you wonder what to do regarding
|
Let's say you write a container manager, and you wonder what to do regarding
|
||||||
|
|||||||
@ -641,7 +641,12 @@ manpages = [
|
|||||||
['sd_id128_randomize', '3', [], ''],
|
['sd_id128_randomize', '3', [], ''],
|
||||||
['sd_id128_to_string',
|
['sd_id128_to_string',
|
||||||
'3',
|
'3',
|
||||||
['SD_ID128_STRING_MAX', 'SD_ID128_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',
|
['sd_is_fifo',
|
||||||
'3',
|
'3',
|
||||||
|
|||||||
@ -18,8 +18,11 @@
|
|||||||
<refnamediv>
|
<refnamediv>
|
||||||
<refname>sd_id128_to_string</refname>
|
<refname>sd_id128_to_string</refname>
|
||||||
<refname>SD_ID128_TO_STRING</refname>
|
<refname>SD_ID128_TO_STRING</refname>
|
||||||
<refname>sd_id128_from_string</refname>
|
|
||||||
<refname>SD_ID128_STRING_MAX</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>
|
<refpurpose>Format or parse 128-bit IDs as strings</refpurpose>
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
|
|
||||||
@ -29,13 +32,22 @@
|
|||||||
|
|
||||||
<funcsynopsisinfo>#define SD_ID128_STRING_MAX 33U</funcsynopsisinfo>
|
<funcsynopsisinfo>#define SD_ID128_STRING_MAX 33U</funcsynopsisinfo>
|
||||||
|
|
||||||
|
<funcsynopsisinfo>#define SD_ID128_UUID_STRING_MAX 37U</funcsynopsisinfo>
|
||||||
|
|
||||||
<funcsynopsisinfo>#define SD_ID128_TO_STRING(id) …</funcsynopsisinfo>
|
<funcsynopsisinfo>#define SD_ID128_TO_STRING(id) …</funcsynopsisinfo>
|
||||||
|
|
||||||
|
<funcsynopsisinfo>#define SD_ID128_TO_UUID_STRING(id) …</funcsynopsisinfo>
|
||||||
|
|
||||||
<funcprototype>
|
<funcprototype>
|
||||||
<funcdef>char *<function>sd_id128_to_string</function></funcdef>
|
<funcdef>char *<function>sd_id128_to_string</function></funcdef>
|
||||||
<paramdef>sd_id128_t <parameter>id</parameter>, char <parameter>s</parameter>[static SD_ID128_STRING_MAX]</paramdef>
|
<paramdef>sd_id128_t <parameter>id</parameter>, char <parameter>s</parameter>[static SD_ID128_STRING_MAX]</paramdef>
|
||||||
</funcprototype>
|
</funcprototype>
|
||||||
|
|
||||||
|
<funcprototype>
|
||||||
|
<funcdef>char *<function>sd_id128_uuid_string</function></funcdef>
|
||||||
|
<paramdef>sd_id128_t <parameter>id</parameter>, char <parameter>s</parameter>[static SD_ID128_UUID_STRING_MAX]</paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
|
||||||
<funcprototype>
|
<funcprototype>
|
||||||
<funcdef>int <function>sd_id128_from_string</function></funcdef>
|
<funcdef>int <function>sd_id128_from_string</function></funcdef>
|
||||||
<paramdef>const char *<parameter>s</parameter>, sd_id128_t *<parameter>ret</parameter></paramdef>
|
<paramdef>const char *<parameter>s</parameter>, sd_id128_t *<parameter>ret</parameter></paramdef>
|
||||||
@ -58,6 +70,10 @@
|
|||||||
which remains valid until the end of the current code block. This is usually the simplest way to acquire
|
which remains valid until the end of the current code block. This is usually the simplest way to acquire
|
||||||
a string representation of a 128-bit ID in a buffer that is valid in the current code block.</para>
|
a string representation of a 128-bit ID in a buffer that is valid in the current code block.</para>
|
||||||
|
|
||||||
|
<para><function>sd_id128_to_uuid_string()</function> and <function>SD_ID128_TO_UUID_STRING()</function>
|
||||||
|
are similar to these two functions/macros, but format the 128bit values as RFC4122 UUIDs, i.e. a series
|
||||||
|
of 36 lowercase hexadeciaml digits and dashes, terminated by a <constant>NUL</constant> byte.</para>
|
||||||
|
|
||||||
<para><function>sd_id128_from_string()</function> implements the reverse operation: it takes a 33
|
<para><function>sd_id128_from_string()</function> implements the reverse operation: it takes a 33
|
||||||
character string with 32 hexadecimal digits (either lowercase or uppercase, terminated by
|
character string with 32 hexadecimal digits (either lowercase or uppercase, terminated by
|
||||||
<constant>NUL</constant>) and parses them back into a 128-bit ID returned in
|
<constant>NUL</constant>) and parses them back into a 128-bit ID returned in
|
||||||
@ -65,7 +81,7 @@
|
|||||||
ID formatted as RFC UUID. If <parameter>ret</parameter> is passed as <constant>NULL</constant> the
|
ID formatted as RFC UUID. If <parameter>ret</parameter> is passed as <constant>NULL</constant> the
|
||||||
function will validate the passed ID string, but not actually return it in parsed form.</para>
|
function will validate the passed ID string, but not actually return it in parsed form.</para>
|
||||||
|
|
||||||
<para>Note that when 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
|
i.e. according to <ulink url="https://tools.ietf.org/html/rfc4122">RFC4122</ulink> Variant 1 rules, even
|
||||||
if the UUID encodes a different variant. This matches behaviour in various other Linux userspace
|
if the UUID encodes a different variant. This matches behaviour in various other Linux userspace
|
||||||
tools. It's probably wise to avoid UUIDs of other variant types.</para>
|
tools. It's probably wise to avoid UUIDs of other variant types.</para>
|
||||||
|
|||||||
@ -417,14 +417,11 @@ int same_fd(int a, int b) {
|
|||||||
assert(a >= 0);
|
assert(a >= 0);
|
||||||
assert(b >= 0);
|
assert(b >= 0);
|
||||||
|
|
||||||
/* Compares two file descriptors. Note that semantics are
|
/* Compares two file descriptors. Note that semantics are quite different depending on whether we
|
||||||
* quite different depending on whether we have kcmp() or we
|
* have kcmp() or we don't. If we have kcmp() this will only return true for dup()ed file
|
||||||
* don't. If we have kcmp() this will only return true for
|
* descriptors, but not otherwise. If we don't have kcmp() this will also return true for two fds of
|
||||||
* dup()ed file descriptors, but not otherwise. If we don't
|
* the same file, created by separate open() calls. Since we use this call mostly for filtering out
|
||||||
* have kcmp() this will also return true for two fds of the same
|
* duplicates in the fd store this difference hopefully doesn't matter too much. */
|
||||||
* file, created by separate open() calls. Since we use this
|
|
||||||
* call mostly for filtering out duplicates in the fd store
|
|
||||||
* this difference hopefully doesn't matter too much. */
|
|
||||||
|
|
||||||
if (a == b)
|
if (a == b)
|
||||||
return true;
|
return true;
|
||||||
@ -436,7 +433,7 @@ int same_fd(int a, int b) {
|
|||||||
return true;
|
return true;
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
return false;
|
return false;
|
||||||
if (!IN_SET(errno, ENOSYS, EACCES, EPERM))
|
if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
/* We don't have kcmp(), use fstat() instead. */
|
/* We don't have kcmp(), use fstat() instead. */
|
||||||
@ -446,23 +443,17 @@ int same_fd(int a, int b) {
|
|||||||
if (fstat(b, &stb) < 0)
|
if (fstat(b, &stb) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
|
if (!stat_inode_same(&sta, &stb))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* We consider all device fds different, since two device fds
|
/* We consider all device fds different, since two device fds might refer to quite different device
|
||||||
* might refer to quite different device contexts even though
|
* contexts even though they share the same inode and backing dev_t. */
|
||||||
* they share the same inode and backing dev_t. */
|
|
||||||
|
|
||||||
if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
|
if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
|
/* The fds refer to the same inode on disk, let's also check if they have the same fd flags. This is
|
||||||
return false;
|
* 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);
|
fa = fcntl(a, F_GETFL);
|
||||||
if (fa < 0)
|
if (fa < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|||||||
@ -856,8 +856,7 @@ int conservative_renameat(
|
|||||||
if (fstat(new_fd, &new_stat) < 0)
|
if (fstat(new_fd, &new_stat) < 0)
|
||||||
goto do_rename;
|
goto do_rename;
|
||||||
|
|
||||||
if (new_stat.st_ino == old_stat.st_ino &&
|
if (stat_inode_same(&new_stat, &old_stat))
|
||||||
new_stat.st_dev == old_stat.st_dev)
|
|
||||||
goto is_same;
|
goto is_same;
|
||||||
|
|
||||||
if (old_stat.st_mode != new_stat.st_mode ||
|
if (old_stat.st_mode != new_stat.st_mode ||
|
||||||
|
|||||||
@ -298,10 +298,8 @@ fallback_fstat:
|
|||||||
if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
|
if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
/* A directory with same device and inode as its parent? Must
|
/* A directory with same device and inode as its parent? Must be the root directory */
|
||||||
* be the root directory */
|
if (stat_inode_same(&a, &b))
|
||||||
if (a.st_dev == b.st_dev &&
|
|
||||||
a.st_ino == b.st_ino)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return check_st_dev && (a.st_dev != b.st_dev);
|
return check_st_dev && (a.st_dev != b.st_dev);
|
||||||
|
|||||||
@ -185,8 +185,7 @@ int files_same(const char *filea, const char *fileb, int flags) {
|
|||||||
if (fstatat(AT_FDCWD, fileb, &b, flags) < 0)
|
if (fstatat(AT_FDCWD, fileb, &b, flags) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
return a.st_dev == b.st_dev &&
|
return stat_inode_same(&a, &b);
|
||||||
a.st_ino == b.st_ino;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
|
bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) {
|
||||||
@ -417,6 +416,18 @@ int proc_mounted(void) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool stat_inode_same(const struct stat *a, const struct stat *b) {
|
||||||
|
|
||||||
|
/* Returns if the specified stat structure references the same (though possibly modified) inode. Does
|
||||||
|
* a thorough check, comparing inode nr, backing device and if the inode is still of the same type. */
|
||||||
|
|
||||||
|
return a && b &&
|
||||||
|
(a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */
|
||||||
|
((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */
|
||||||
|
a->st_dev == b->st_dev &&
|
||||||
|
a->st_ino == b->st_ino;
|
||||||
|
}
|
||||||
|
|
||||||
bool stat_inode_unmodified(const struct stat *a, const struct stat *b) {
|
bool stat_inode_unmodified(const struct stat *a, const struct stat *b) {
|
||||||
|
|
||||||
/* Returns if the specified stat structures reference the same, unmodified inode. This check tries to
|
/* Returns if the specified stat structures reference the same, unmodified inode. This check tries to
|
||||||
@ -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
|
* about contents of the file. The purpose here is to detect file contents changes, and nothing
|
||||||
* else. */
|
* else. */
|
||||||
|
|
||||||
return a && b &&
|
return stat_inode_same(a, b) &&
|
||||||
(a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */
|
|
||||||
((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */
|
|
||||||
a->st_mtim.tv_sec == b->st_mtim.tv_sec &&
|
a->st_mtim.tv_sec == b->st_mtim.tv_sec &&
|
||||||
a->st_mtim.tv_nsec == b->st_mtim.tv_nsec &&
|
a->st_mtim.tv_nsec == b->st_mtim.tv_nsec &&
|
||||||
(!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */
|
(!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */
|
||||||
a->st_dev == b->st_dev &&
|
|
||||||
a->st_ino == b->st_ino &&
|
|
||||||
(!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */
|
(!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -92,6 +92,7 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret
|
|||||||
|
|
||||||
int proc_mounted(void);
|
int proc_mounted(void);
|
||||||
|
|
||||||
|
bool stat_inode_same(const struct stat *a, const struct stat *b);
|
||||||
bool stat_inode_unmodified(const struct stat *a, const struct stat *b);
|
bool stat_inode_unmodified(const struct stat *a, const struct stat *b);
|
||||||
|
|
||||||
int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx);
|
int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx);
|
||||||
@ -114,3 +115,9 @@ int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct s
|
|||||||
struct new_statx nsx; \
|
struct new_statx nsx; \
|
||||||
} var
|
} var
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline bool devid_set_and_equal(dev_t a, dev_t b) {
|
||||||
|
/* Returns true if a and b definitely refer to the same device. If either is zero, this means "don't
|
||||||
|
* know" and we'll return false */
|
||||||
|
return a == b && a != 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
|
#include "stat-util.h"
|
||||||
#include "sync-util.h"
|
#include "sync-util.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -98,17 +99,18 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
|
|
||||||
static int acquire_path(void) {
|
static int acquire_path(void) {
|
||||||
_cleanup_free_ char *esp_path = NULL, *xbootldr_path = NULL;
|
_cleanup_free_ char *esp_path = NULL, *xbootldr_path = NULL;
|
||||||
|
dev_t esp_devid = 0, xbootldr_devid = 0;
|
||||||
char **a;
|
char **a;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!strv_isempty(arg_path))
|
if (!strv_isempty(arg_path))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = find_esp_and_warn(NULL, 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 */
|
if (r < 0 && r != -ENOKEY) /* ENOKEY means not found, and is the only error the function won't log about on its own */
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = find_xbootldr_and_warn(NULL, false, &xbootldr_path, NULL);
|
r = find_xbootldr_and_warn(NULL, /* unprivileged_mode= */ false, &xbootldr_path, NULL, &xbootldr_devid);
|
||||||
if (r < 0 && r != -ENOKEY)
|
if (r < 0 && r != -ENOKEY)
|
||||||
return r;
|
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"
|
"Couldn't find $BOOT partition. It is recommended to mount it to /boot.\n"
|
||||||
"Alternatively, use --path= to specify path to mount point.");
|
"Alternatively, use --path= to specify path to mount point.");
|
||||||
|
|
||||||
if (esp_path)
|
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);
|
a = strv_new(esp_path, xbootldr_path);
|
||||||
|
else if (esp_path)
|
||||||
|
a = strv_new(esp_path);
|
||||||
else
|
else
|
||||||
a = strv_new(xbootldr_path);
|
a = strv_new(xbootldr_path);
|
||||||
if (!a)
|
if (!a)
|
||||||
@ -130,7 +134,7 @@ static int acquire_path(void) {
|
|||||||
_cleanup_free_ char *j = NULL;
|
_cleanup_free_ char *j = NULL;
|
||||||
|
|
||||||
j = strv_join(arg_path, ":");
|
j = strv_join(arg_path, ":");
|
||||||
log_debug("Using %s as boot loader drop-in search path.", j);
|
log_debug("Using %s as boot loader drop-in search path.", strna(j));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
#include "rm-rf.h"
|
#include "rm-rf.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "stdio-util.h"
|
#include "stdio-util.h"
|
||||||
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "sync-util.h"
|
#include "sync-util.h"
|
||||||
@ -74,7 +75,8 @@ static int acquire_esp(
|
|||||||
uint32_t *ret_part,
|
uint32_t *ret_part,
|
||||||
uint64_t *ret_pstart,
|
uint64_t *ret_pstart,
|
||||||
uint64_t *ret_psize,
|
uint64_t *ret_psize,
|
||||||
sd_id128_t *ret_uuid) {
|
sd_id128_t *ret_uuid,
|
||||||
|
dev_t *ret_devid) {
|
||||||
|
|
||||||
char *np;
|
char *np;
|
||||||
int r;
|
int r;
|
||||||
@ -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
|
* we simply eat up the error here, so that --list and --status work too, without noise about
|
||||||
* this). */
|
* this). */
|
||||||
|
|
||||||
r = find_esp_and_warn(arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid);
|
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 (r == -ENOKEY) {
|
||||||
if (graceful)
|
if (graceful)
|
||||||
return log_info_errno(r, "Couldn't find EFI system partition, skipping.");
|
return log_info_errno(r, "Couldn't find EFI system partition, skipping.");
|
||||||
@ -103,16 +105,23 @@ static int acquire_esp(
|
|||||||
return 1;
|
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;
|
char *np;
|
||||||
int r;
|
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) {
|
if (r == -ENOKEY) {
|
||||||
log_debug_errno(r, "Didn't find an XBOOTLDR partition, using the ESP as $BOOT.");
|
log_debug_errno(r, "Didn't find an XBOOTLDR partition, using the ESP as $BOOT.");
|
||||||
|
arg_xbootldr_path = mfree(arg_xbootldr_path);
|
||||||
|
|
||||||
if (ret_uuid)
|
if (ret_uuid)
|
||||||
*ret_uuid = SD_ID128_NULL;
|
*ret_uuid = SD_ID128_NULL;
|
||||||
arg_xbootldr_path = mfree(arg_xbootldr_path);
|
if (ret_devid)
|
||||||
|
*ret_devid = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (r < 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;
|
*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;
|
int status = 0;
|
||||||
|
|
||||||
/* Returns 0 on success, negative on processing error, and positive if something is wrong with the
|
/* Returns 0 on success, negative on processing error, and positive if something is wrong with the
|
||||||
@ -419,9 +442,30 @@ static int boot_entry_show(const BootEntry *e, bool show_as_default) {
|
|||||||
|
|
||||||
assert(e);
|
assert(e);
|
||||||
|
|
||||||
printf(" title: %s%s%s" "%s%s%s\n",
|
printf(" type: %s\n",
|
||||||
ansi_highlight(), boot_entry_title(e), ansi_normal(),
|
boot_entry_type_to_string(e->type));
|
||||||
ansi_highlight_green(), show_as_default ? " (default)" : "", ansi_normal());
|
|
||||||
|
printf(" title: %s%s%s",
|
||||||
|
ansi_highlight(), boot_entry_title(e), ansi_normal());
|
||||||
|
|
||||||
|
if (show_as_default)
|
||||||
|
printf(" %s(default)%s",
|
||||||
|
ansi_highlight_green(), ansi_normal());
|
||||||
|
|
||||||
|
if (show_as_selected)
|
||||||
|
printf(" %s(selected)%s",
|
||||||
|
ansi_highlight_magenta(), ansi_normal());
|
||||||
|
|
||||||
|
if (show_reported) {
|
||||||
|
if (e->type == BOOT_ENTRY_LOADER)
|
||||||
|
printf(" %s(reported/absent)%s",
|
||||||
|
ansi_highlight_red(), ansi_normal());
|
||||||
|
else if (!e->reported_by_loader && e->type != BOOT_ENTRY_LOADER_AUTO)
|
||||||
|
printf(" %s(not reported/new)%s",
|
||||||
|
ansi_highlight_green(), ansi_normal());
|
||||||
|
}
|
||||||
|
|
||||||
|
putchar('\n');
|
||||||
|
|
||||||
if (e->id)
|
if (e->id)
|
||||||
printf(" id: %s\n", e->id);
|
printf(" id: %s\n", e->id);
|
||||||
@ -450,6 +494,7 @@ static int boot_entry_show(const BootEntry *e, bool show_as_default) {
|
|||||||
e->root,
|
e->root,
|
||||||
*s,
|
*s,
|
||||||
&status);
|
&status);
|
||||||
|
|
||||||
if (!strv_isempty(e->options)) {
|
if (!strv_isempty(e->options)) {
|
||||||
_cleanup_free_ char *t = NULL, *t2 = NULL;
|
_cleanup_free_ char *t = NULL, *t2 = NULL;
|
||||||
_cleanup_strv_free_ char **ts = NULL;
|
_cleanup_strv_free_ char **ts = NULL;
|
||||||
@ -468,9 +513,16 @@ static int boot_entry_show(const BootEntry *e, bool show_as_default) {
|
|||||||
|
|
||||||
printf(" options: %s\n", t2);
|
printf(" options: %s\n", t2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->device_tree)
|
if (e->device_tree)
|
||||||
boot_entry_file_list("devicetree", e->root, e->device_tree, &status);
|
boot_entry_file_list("devicetree", e->root, e->device_tree, &status);
|
||||||
|
|
||||||
|
STRV_FOREACH(s, e->device_tree_overlay)
|
||||||
|
boot_entry_file_list(s == e->device_tree_overlay ? "devicetree-overlay" : NULL,
|
||||||
|
e->root,
|
||||||
|
*s,
|
||||||
|
&status);
|
||||||
|
|
||||||
return -status;
|
return -status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,7 +563,11 @@ static int status_entries(
|
|||||||
else {
|
else {
|
||||||
printf("Default Boot Loader Entry:\n");
|
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)
|
if (r > 0)
|
||||||
/* < 0 is already logged by the function itself, let's just emit an extra warning if
|
/* < 0 is already logged by the function itself, let's just emit an extra warning if
|
||||||
the default entry is broken */
|
the default entry is broken */
|
||||||
@ -1388,7 +1444,7 @@ static void print_yes_no_line(bool first, bool good, const char *name) {
|
|||||||
static int are_we_installed(void) {
|
static int are_we_installed(void) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL);
|
r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1420,9 +1476,10 @@ static int are_we_installed(void) {
|
|||||||
|
|
||||||
static int verb_status(int argc, char *argv[], void *userdata) {
|
static int verb_status(int argc, char *argv[], void *userdata) {
|
||||||
sd_id128_t esp_uuid = SD_ID128_NULL, xbootldr_uuid = SD_ID128_NULL;
|
sd_id128_t esp_uuid = SD_ID128_NULL, xbootldr_uuid = SD_ID128_NULL;
|
||||||
|
dev_t esp_devid = 0, xbootldr_devid = 0;
|
||||||
int r, k;
|
int r, k;
|
||||||
|
|
||||||
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, &esp_uuid);
|
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, &esp_uuid, &esp_devid);
|
||||||
if (arg_print_esp_path) {
|
if (arg_print_esp_path) {
|
||||||
if (r == -EACCES) /* If we couldn't acquire the ESP path, log about access errors (which is the only
|
if (r == -EACCES) /* If we couldn't acquire the ESP path, log about access errors (which is the only
|
||||||
* error the find_esp_and_warn() won't log on its own) */
|
* error the find_esp_and_warn() won't log on its own) */
|
||||||
@ -1433,7 +1490,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
puts(arg_esp_path);
|
puts(arg_esp_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, &xbootldr_uuid);
|
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, &xbootldr_uuid, &xbootldr_devid);
|
||||||
if (arg_print_dollar_boot_path) {
|
if (arg_print_dollar_boot_path) {
|
||||||
if (r == -EACCES)
|
if (r == -EACCES)
|
||||||
return log_error_errno(r, "Failed to determine XBOOTLDR location: %m");
|
return log_error_errno(r, "Failed to determine XBOOTLDR location: %m");
|
||||||
@ -1567,7 +1624,14 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arg_esp_path || arg_xbootldr_path) {
|
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)
|
if (k < 0)
|
||||||
r = k;
|
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) {
|
static int verb_list(int argc, char *argv[], void *userdata) {
|
||||||
_cleanup_(boot_config_free) BootConfig config = {};
|
_cleanup_(boot_config_free) BootConfig config = {};
|
||||||
_cleanup_strv_free_ char **efi_entries = NULL;
|
_cleanup_strv_free_ char **efi_entries = NULL;
|
||||||
|
dev_t esp_devid = 0, xbootldr_devid = 0;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
|
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
|
||||||
* off logging about access errors and turn off potentially privileged device probing. Here we're interested in
|
* off logging about access errors and turn off potentially privileged device probing. Here we're interested in
|
||||||
* the latter but not the former, hence request the mode, and log about EACCES. */
|
* the latter but not the former, hence request the mode, and log about EACCES. */
|
||||||
|
|
||||||
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, NULL);
|
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 */
|
if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */
|
||||||
return log_error_errno(r, "Failed to determine ESP: %m");
|
return log_error_errno(r, "Failed to determine ESP: %m");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, NULL);
|
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, NULL, &xbootldr_devid);
|
||||||
if (r == -EACCES)
|
if (r == -EACCES)
|
||||||
return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
|
return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1606,7 +1674,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
|||||||
else if (r < 0)
|
else if (r < 0)
|
||||||
log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
|
log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
|
||||||
else
|
else
|
||||||
(void) boot_entries_augment_from_loader(&config, efi_entries);
|
(void) boot_entries_augment_from_loader(&config, efi_entries, /* only_auto= */ false);
|
||||||
|
|
||||||
if (config.n_entries == 0)
|
if (config.n_entries == 0)
|
||||||
log_info("No boot loader entries found.");
|
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");
|
printf("Boot Loader Entries:\n");
|
||||||
|
|
||||||
for (size_t n = 0; n < config.n_entries; n++) {
|
for (size_t n = 0; n < config.n_entries; n++) {
|
||||||
r = boot_entry_show(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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1788,7 +1860,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
|
|||||||
install = streq(argv[0], "install");
|
install = streq(argv[0], "install");
|
||||||
graceful = !install && arg_graceful; /* support graceful mode for updates */
|
graceful = !install && arg_graceful; /* support graceful mode for updates */
|
||||||
|
|
||||||
r = acquire_esp(/* unprivileged_mode= */ false, graceful, &part, &pstart, &psize, &uuid);
|
r = acquire_esp(/* unprivileged_mode= */ false, graceful, &part, &pstart, &psize, &uuid, NULL);
|
||||||
if (graceful && r == -ENOKEY)
|
if (graceful && r == -ENOKEY)
|
||||||
return 0; /* If --graceful is specified and we can't find an ESP, handle this cleanly */
|
return 0; /* If --graceful is specified and we can't find an ESP, handle this cleanly */
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1865,11 +1937,11 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
|
|||||||
sd_id128_t uuid = SD_ID128_NULL;
|
sd_id128_t uuid = SD_ID128_NULL;
|
||||||
int r, q;
|
int r, q;
|
||||||
|
|
||||||
r = acquire_esp(/* unprivileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, &uuid);
|
r = acquire_esp(/* unprivileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, &uuid, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL);
|
r = acquire_xbootldr(/* unprivileged_mode= */ false, NULL, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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) {
|
static int verb_random_seed(int argc, char *argv[], void *userdata) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = find_esp_and_warn(arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL);
|
r = find_esp_and_warn(arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (r == -ENOKEY) {
|
if (r == -ENOKEY) {
|
||||||
/* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
|
/* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
|
||||||
if (!arg_graceful)
|
if (!arg_graceful)
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "memory-util.h"
|
#include "memory-util.h"
|
||||||
|
#include "stat-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
@ -167,9 +168,7 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
|
|||||||
if (!S_ISREG(st.st_mode))
|
if (!S_ISREG(st.st_mode))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (exclude_fd >= 0 &&
|
if (exclude_fd >= 0 && stat_inode_same(&exclude_st, &st))
|
||||||
exclude_st.st_dev == st.st_dev &&
|
|
||||||
exclude_st.st_ino == st.st_ino)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = hashmap_ensure_allocated(&h, NULL);
|
r = hashmap_ensure_allocated(&h, NULL);
|
||||||
|
|||||||
@ -721,7 +721,7 @@ static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) {
|
|||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
/* The process uses system root. */
|
/* The process uses system root. */
|
||||||
if (proc_root_stat.st_ino == root_stat.st_ino) {
|
if (stat_inode_same(&proc_root_stat, &root_stat)) {
|
||||||
*cmdline = NULL;
|
*cmdline = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -779,12 +779,16 @@ static int add_mounts(void) {
|
|||||||
return btrfs_log_dev_root(LOG_ERR, r, "root file system");
|
return btrfs_log_dev_root(LOG_ERR, r, "root file system");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to determine block device of root file system: %m");
|
return log_error_errno(r, "Failed to determine block device of root file system: %m");
|
||||||
if (r == 0) { /* Not backed by 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);
|
r = get_block_device_harder("/usr", &devno);
|
||||||
if (r == -EUCLEAN)
|
if (r == -EUCLEAN)
|
||||||
return btrfs_log_dev_root(LOG_ERR, r, "/usr");
|
return btrfs_log_dev_root(LOG_ERR, r, "/usr");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
|
return log_error_errno(r, "Failed to determine block device of /usr/ file system: %m");
|
||||||
|
if (r == 0) { /* /usr/ not backed by single block device, either. */
|
||||||
|
log_debug("Neither root nor /usr/ file system are on a (single) block device.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (r < 0)
|
} else if (r < 0)
|
||||||
return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
|
return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m");
|
||||||
|
|||||||
@ -1239,10 +1239,7 @@ static int manager_add_device(Manager *m, sd_device *d) {
|
|||||||
return 0;
|
return 0;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to acquire ID_PART_ENTRY_TYPE device property, ignoring: %m");
|
return log_error_errno(r, "Failed to acquire ID_PART_ENTRY_TYPE device property, ignoring: %m");
|
||||||
r = sd_id128_from_string(parttype, &id);
|
if (id128_equal_string(parttype, GPT_USER_HOME) <= 0) {
|
||||||
if (r < 0)
|
|
||||||
return log_debug_errno(r, "Failed to parse ID_PART_ENTRY_TYPE field '%s', ignoring: %m", parttype);
|
|
||||||
if (!sd_id128_equal(id, GPT_USER_HOME)) {
|
|
||||||
log_debug("Found partition (%s) we don't care about, ignoring.", sysfs);
|
log_debug("Found partition (%s) we don't care about, ignoring.", sysfs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
#include "filesystems.h"
|
#include "filesystems.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "fsck-util.h"
|
#include "fsck-util.h"
|
||||||
|
#include "gpt.h"
|
||||||
#include "home-util.h"
|
#include "home-util.h"
|
||||||
#include "homework-luks.h"
|
#include "homework-luks.h"
|
||||||
#include "homework-mount.h"
|
#include "homework-mount.h"
|
||||||
@ -703,7 +704,7 @@ static int luks_validate(
|
|||||||
if (!pp)
|
if (!pp)
|
||||||
return errno > 0 ? -errno : -EIO;
|
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;
|
continue;
|
||||||
|
|
||||||
if (!streq_ptr(blkid_partition_get_name(pp), label))
|
if (!streq_ptr(blkid_partition_get_name(pp), label))
|
||||||
@ -1762,7 +1763,7 @@ static int luks_format(
|
|||||||
CRYPT_LUKS2,
|
CRYPT_LUKS2,
|
||||||
user_record_luks_cipher(hr),
|
user_record_luks_cipher(hr),
|
||||||
user_record_luks_cipher_mode(hr),
|
user_record_luks_cipher_mode(hr),
|
||||||
ID128_TO_UUID_STRING(uuid),
|
SD_ID128_TO_UUID_STRING(uuid),
|
||||||
volume_key,
|
volume_key,
|
||||||
volume_key_size,
|
volume_key_size,
|
||||||
&(struct crypt_params_luks2) {
|
&(struct crypt_params_luks2) {
|
||||||
@ -1858,7 +1859,7 @@ static int make_partition_table(
|
|||||||
if (!t)
|
if (!t)
|
||||||
return log_oom();
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to initialize partition type: %m");
|
return log_error_errno(r, "Failed to initialize partition type: %m");
|
||||||
|
|
||||||
@ -1917,7 +1918,7 @@ static int make_partition_table(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set partition name: %m");
|
return log_error_errno(r, "Failed to set partition name: %m");
|
||||||
|
|
||||||
r = fdisk_partition_set_uuid(p, ID128_TO_UUID_STRING(uuid));
|
r = fdisk_partition_set_uuid(p, SD_ID128_TO_UUID_STRING(uuid));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set partition UUID: %m");
|
return log_error_errno(r, "Failed to set partition UUID: %m");
|
||||||
|
|
||||||
@ -2745,7 +2746,7 @@ static int ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *userdata
|
|||||||
if (!result)
|
if (!result)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
fdisk_ask_string_set_result(ask, 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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -332,9 +332,9 @@ int user_record_add_binding(
|
|||||||
r = json_build(&new_binding_entry,
|
r = json_build(&new_binding_entry,
|
||||||
JSON_BUILD_OBJECT(
|
JSON_BUILD_OBJECT(
|
||||||
JSON_BUILD_PAIR_CONDITION(!!image_path, "imagePath", JSON_BUILD_STRING(image_path)),
|
JSON_BUILD_PAIR_CONDITION(!!image_path, "imagePath", JSON_BUILD_STRING(image_path)),
|
||||||
JSON_BUILD_PAIR_CONDITION(!sd_id128_is_null(partition_uuid), "partitionUuid", JSON_BUILD_STRING(ID128_TO_UUID_STRING(partition_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(ID128_TO_UUID_STRING(luks_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(ID128_TO_UUID_STRING(fs_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, "luksCipher", JSON_BUILD_STRING(luks_cipher)),
|
||||||
JSON_BUILD_PAIR_CONDITION(!!luks_cipher_mode, "luksCipherMode", JSON_BUILD_STRING(luks_cipher_mode)),
|
JSON_BUILD_PAIR_CONDITION(!!luks_cipher_mode, "luksCipherMode", JSON_BUILD_STRING(luks_cipher_mode)),
|
||||||
JSON_BUILD_PAIR_CONDITION(luks_volume_key_size != UINT64_MAX, "luksVolumeKeySize", JSON_BUILD_UNSIGNED(luks_volume_key_size)),
|
JSON_BUILD_PAIR_CONDITION(luks_volume_key_size != UINT64_MAX, "luksVolumeKeySize", JSON_BUILD_UNSIGNED(luks_volume_key_size)),
|
||||||
|
|||||||
@ -769,3 +769,8 @@ global:
|
|||||||
sd_event_add_inotify_fd;
|
sd_event_add_inotify_fd;
|
||||||
sd_event_source_set_ratelimit_expire_callback;
|
sd_event_source_set_ratelimit_expire_callback;
|
||||||
} LIBSYSTEMD_249;
|
} LIBSYSTEMD_249;
|
||||||
|
|
||||||
|
LIBSYSTEMD_251 {
|
||||||
|
global:
|
||||||
|
sd_id128_to_uuid_string;
|
||||||
|
} LIBSYSTEMD_250;
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
|
#include "stat-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "time-util.h"
|
#include "time-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -150,9 +151,7 @@ _public_ int sd_is_fifo(int fd, const char *path) {
|
|||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return stat_inode_same(&st_path, &st_fd);
|
||||||
st_path.st_dev == st_fd.st_dev &&
|
|
||||||
st_path.st_ino == st_fd.st_ino;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
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))
|
if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
|
||||||
return
|
return stat_inode_same(&st_path, &st_fd);
|
||||||
st_path.st_dev == st_fd.st_dev &&
|
|
||||||
st_path.st_ino == st_fd.st_ino;
|
|
||||||
else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
|
else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
|
||||||
return st_path.st_rdev == st_fd.st_rdev;
|
return st_path.st_rdev == st_fd.st_rdev;
|
||||||
else
|
else
|
||||||
@ -415,7 +412,7 @@ _public_ int sd_is_mq(int fd, const char *path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
char fpath[PATH_MAX];
|
_cleanup_free_ char *fpath = NULL;
|
||||||
struct stat a, b;
|
struct stat a, b;
|
||||||
|
|
||||||
assert_return(path_is_absolute(path), -EINVAL);
|
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)
|
if (fstat(fd, &a) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
|
fpath = path_join("/dev/mqueue", path);
|
||||||
fpath[sizeof(fpath)-1] = 0;
|
if (!fpath)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
if (stat(fpath, &b) < 0)
|
if (stat(fpath, &b) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (a.st_dev != b.st_dev ||
|
if (!stat_inode_same(&a, &b))
|
||||||
a.st_ino != b.st_ino)
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "mountpoint-util.h"
|
#include "mountpoint-util.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
|
#include "stat-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
|
|
||||||
@ -195,7 +196,7 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group,
|
|||||||
else
|
else
|
||||||
log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns, ignoring: %m");
|
log_debug_errno(errno, "sd-device-monitor: Failed to stat PID1's netns, ignoring: %m");
|
||||||
|
|
||||||
} else if (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.");
|
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(ret, -EINVAL);
|
||||||
assert_return(IN_SET(type, 'b', 'c'), -EINVAL);
|
assert_return(IN_SET(type, 'b', 'c'), -EINVAL);
|
||||||
|
|
||||||
|
if (devnum == 0)
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(ENODEV),
|
||||||
|
"sd-device: Attempted to allocate device by zero major/minor, refusing.");
|
||||||
|
|
||||||
/* use /sys/dev/{block,char}/<maj>:<min> link */
|
/* use /sys/dev/{block,char}/<maj>:<min> link */
|
||||||
xsprintf(id, "%u:%u", major(devnum), minor(devnum));
|
xsprintf(id, "%u:%u", major(devnum), minor(devnum));
|
||||||
|
|
||||||
@ -2194,7 +2198,7 @@ _public_ int sd_device_trigger_with_uuid(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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);
|
r = sd_device_set_sysattr_value(device, "uevent", j);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include "device-private.h"
|
#include "device-private.h"
|
||||||
#include "device-util.h"
|
#include "device-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
#include "stat-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -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);
|
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_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL;
|
||||||
_cleanup_(sd_device_unrefp) sd_device *loopback = NULL;
|
_cleanup_(sd_device_unrefp) sd_device *loopback = NULL;
|
||||||
const char *syspath;
|
const char *syspath;
|
||||||
int r;
|
|
||||||
|
|
||||||
log_info("/* %s */", __func__);
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
@ -47,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_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0);
|
||||||
assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
|
assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0);
|
||||||
|
|
||||||
/* Do not use assert_se() here. */
|
assert_se(device_monitor_send_device(monitor_server, monitor_client, loopback) >= 0);
|
||||||
r = device_monitor_send_device(monitor_server, monitor_client, loopback);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to send loopback device: %m");
|
|
||||||
|
|
||||||
assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0);
|
assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) {
|
static void test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) {
|
||||||
@ -299,11 +293,10 @@ int main(int argc, char *argv[]) {
|
|||||||
if (getuid() != 0)
|
if (getuid() != 0)
|
||||||
return log_tests_skipped("not root");
|
return log_tests_skipped("not root");
|
||||||
|
|
||||||
r = test_receive_device_fail();
|
if (path_is_read_only_fs("/sys") > 0)
|
||||||
if (r < 0) {
|
|
||||||
assert_se(r == -EPERM && detect_container() > 0);
|
|
||||||
return log_tests_skipped("Running in container");
|
return log_tests_skipped("Running in container");
|
||||||
}
|
|
||||||
|
test_receive_device_fail();
|
||||||
|
|
||||||
assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0);
|
assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0);
|
||||||
assert_se(device_add_property(loopback, "ACTION", "add") >= 0);
|
assert_se(device_add_property(loopback, "ACTION", "add") >= 0);
|
||||||
|
|||||||
@ -12,29 +12,6 @@
|
|||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "sync-util.h"
|
#include "sync-util.h"
|
||||||
|
|
||||||
char *id128_to_uuid_string(sd_id128_t id, char s[static ID128_UUID_STRING_MAX]) {
|
|
||||||
unsigned n, k = 0;
|
|
||||||
|
|
||||||
assert(s);
|
|
||||||
|
|
||||||
/* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
|
|
||||||
|
|
||||||
for (n = 0; n < 16; n++) {
|
|
||||||
|
|
||||||
if (IN_SET(n, 4, 6, 8, 10))
|
|
||||||
s[k++] = '-';
|
|
||||||
|
|
||||||
s[k++] = hexchar(id.bytes[n] >> 4);
|
|
||||||
s[k++] = hexchar(id.bytes[n] & 0xF);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(k == 36);
|
|
||||||
|
|
||||||
s[k] = 0;
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool id128_is_valid(const char *s) {
|
bool id128_is_valid(const char *s) {
|
||||||
size_t i, l;
|
size_t i, l;
|
||||||
|
|
||||||
@ -153,13 +130,13 @@ int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
|
|||||||
assert(f < _ID128_FORMAT_MAX);
|
assert(f < _ID128_FORMAT_MAX);
|
||||||
|
|
||||||
if (f != ID128_UUID) {
|
if (f != ID128_UUID) {
|
||||||
sd_id128_to_string(id, buffer);
|
assert_se(sd_id128_to_string(id, buffer));
|
||||||
buffer[32] = '\n';
|
buffer[SD_ID128_STRING_MAX - 1] = '\n';
|
||||||
sz = 33;
|
sz = SD_ID128_STRING_MAX;
|
||||||
} else {
|
} else {
|
||||||
id128_to_uuid_string(id, buffer);
|
assert_se(sd_id128_to_uuid_string(id, buffer));
|
||||||
buffer[36] = '\n';
|
buffer[SD_ID128_UUID_STRING_MAX - 1] = '\n';
|
||||||
sz = 37;
|
sz = SD_ID128_UUID_STRING_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = loop_write(fd, buffer, sz, false);
|
r = loop_write(fd, buffer, sz, false);
|
||||||
@ -229,3 +206,19 @@ int id128_get_product(sd_id128_t *ret) {
|
|||||||
*ret = uuid;
|
*ret = uuid;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int id128_equal_string(const char *s, sd_id128_t id) {
|
||||||
|
sd_id128_t parsed;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Checks if the specified string matches a valid string representation of the specified 128 bit ID/uuid */
|
||||||
|
|
||||||
|
r = sd_id128_from_string(s, &parsed);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return sd_id128_equal(parsed, id);
|
||||||
|
}
|
||||||
|
|||||||
@ -8,12 +8,6 @@
|
|||||||
#include "hash-funcs.h"
|
#include "hash-funcs.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
|
||||||
#define ID128_UUID_STRING_MAX 37
|
|
||||||
|
|
||||||
char *id128_to_uuid_string(sd_id128_t id, char s[static ID128_UUID_STRING_MAX]);
|
|
||||||
|
|
||||||
#define ID128_TO_UUID_STRING(id) id128_to_uuid_string((id), (char[ID128_UUID_STRING_MAX]) {})
|
|
||||||
|
|
||||||
bool id128_is_valid(const char *s) _pure_;
|
bool id128_is_valid(const char *s) _pure_;
|
||||||
|
|
||||||
typedef enum Id128Format {
|
typedef enum Id128Format {
|
||||||
@ -40,3 +34,5 @@ extern const struct hash_ops id128_hash_ops;
|
|||||||
sd_id128_t id128_make_v4_uuid(sd_id128_t id);
|
sd_id128_t id128_make_v4_uuid(sd_id128_t id);
|
||||||
|
|
||||||
int id128_get_product(sd_id128_t *ret);
|
int id128_get_product(sd_id128_t *ret);
|
||||||
|
|
||||||
|
int id128_equal_string(const char *s, sd_id128_t id);
|
||||||
|
|||||||
@ -19,16 +19,36 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
_public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) {
|
_public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) {
|
||||||
unsigned n;
|
|
||||||
|
|
||||||
assert_return(s, NULL);
|
assert_return(s, NULL);
|
||||||
|
|
||||||
for (n = 0; n < 16; n++) {
|
for (size_t n = 0; n < 16; n++) {
|
||||||
s[n*2] = hexchar(id.bytes[n] >> 4);
|
s[n*2] = hexchar(id.bytes[n] >> 4);
|
||||||
s[n*2+1] = hexchar(id.bytes[n] & 0xF);
|
s[n*2+1] = hexchar(id.bytes[n] & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
s[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;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1317,8 +1317,7 @@ static int add_any_file(
|
|||||||
|
|
||||||
f = ordered_hashmap_get(j->files, path);
|
f = ordered_hashmap_get(j->files, path);
|
||||||
if (f) {
|
if (f) {
|
||||||
if (f->last_stat.st_dev == st.st_dev &&
|
if (stat_inode_same(&f->last_stat, &st)) {
|
||||||
f->last_stat.st_ino == st.st_ino) {
|
|
||||||
|
|
||||||
/* We already track this file, under the same path and with the same device/inode numbers, it's
|
/* We already track this file, under the same path and with the same device/inode numbers, it's
|
||||||
* hence really the same. Mark this file as seen in this generation. This is used to GC old
|
* hence really the same. Mark this file as seen in this generation. This is used to GC old
|
||||||
|
|||||||
@ -20,101 +20,99 @@
|
|||||||
|
|
||||||
static const ActionTableItem action_table[_HANDLE_ACTION_MAX] = {
|
static const ActionTableItem action_table[_HANDLE_ACTION_MAX] = {
|
||||||
[HANDLE_POWEROFF] = {
|
[HANDLE_POWEROFF] = {
|
||||||
SPECIAL_POWEROFF_TARGET,
|
.handle = HANDLE_POWEROFF,
|
||||||
INHIBIT_SHUTDOWN,
|
.target = SPECIAL_POWEROFF_TARGET,
|
||||||
"org.freedesktop.login1.power-off",
|
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||||
"org.freedesktop.login1.power-off-multiple-sessions",
|
.polkit_action = "org.freedesktop.login1.power-off",
|
||||||
"org.freedesktop.login1.power-off-ignore-inhibit",
|
.polkit_action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions",
|
||||||
_SLEEP_OPERATION_INVALID,
|
.polkit_action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit",
|
||||||
SD_MESSAGE_SHUTDOWN_STR,
|
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||||
"System is powering down",
|
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||||
"power-off",
|
.message = "System is powering down",
|
||||||
},
|
.log_message = "power-off",
|
||||||
|
},
|
||||||
[HANDLE_REBOOT] = {
|
[HANDLE_REBOOT] = {
|
||||||
SPECIAL_REBOOT_TARGET,
|
.handle = HANDLE_REBOOT,
|
||||||
INHIBIT_SHUTDOWN,
|
.target = SPECIAL_REBOOT_TARGET,
|
||||||
"org.freedesktop.login1.reboot",
|
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||||
"org.freedesktop.login1.reboot-multiple-sessions",
|
.polkit_action = "org.freedesktop.login1.reboot",
|
||||||
"org.freedesktop.login1.reboot-ignore-inhibit",
|
.polkit_action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions",
|
||||||
_SLEEP_OPERATION_INVALID,
|
.polkit_action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit",
|
||||||
SD_MESSAGE_SHUTDOWN_STR,
|
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||||
"System is rebooting",
|
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||||
"reboot",
|
.message = "System is rebooting",
|
||||||
},
|
.log_message = "reboot",
|
||||||
[HANDLE_HALT] = {
|
},
|
||||||
SPECIAL_HALT_TARGET,
|
[HANDLE_HALT] = {
|
||||||
INHIBIT_SHUTDOWN,
|
.handle = HANDLE_HALT,
|
||||||
"org.freedesktop.login1.halt",
|
.target = SPECIAL_HALT_TARGET,
|
||||||
"org.freedesktop.login1.halt-multiple-sessions",
|
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||||
"org.freedesktop.login1.halt-ignore-inhibit",
|
.polkit_action = "org.freedesktop.login1.halt",
|
||||||
_SLEEP_OPERATION_INVALID,
|
.polkit_action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions",
|
||||||
SD_MESSAGE_SHUTDOWN_STR,
|
.polkit_action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit",
|
||||||
"System is halting",
|
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||||
"halt",
|
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||||
},
|
.message = "System is halting",
|
||||||
[HANDLE_KEXEC] = {
|
.log_message = "halt",
|
||||||
SPECIAL_KEXEC_TARGET,
|
},
|
||||||
INHIBIT_SHUTDOWN,
|
[HANDLE_KEXEC] = {
|
||||||
"org.freedesktop.login1.reboot",
|
.handle = HANDLE_KEXEC,
|
||||||
"org.freedesktop.login1.reboot-multiple-sessions",
|
.target = SPECIAL_KEXEC_TARGET,
|
||||||
"org.freedesktop.login1.reboot-ignore-inhibit",
|
.inhibit_what = INHIBIT_SHUTDOWN,
|
||||||
_SLEEP_OPERATION_INVALID,
|
.polkit_action = "org.freedesktop.login1.reboot",
|
||||||
SD_MESSAGE_SHUTDOWN_STR,
|
.polkit_action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions",
|
||||||
"System is rebooting with kexec",
|
.polkit_action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit",
|
||||||
"kexec",
|
.sleep_operation = _SLEEP_OPERATION_INVALID,
|
||||||
},
|
.message_id = SD_MESSAGE_SHUTDOWN_STR,
|
||||||
[HANDLE_SUSPEND] = {
|
.message = "System is rebooting with kexec",
|
||||||
SPECIAL_SUSPEND_TARGET,
|
.log_message = "kexec",
|
||||||
INHIBIT_SLEEP,
|
},
|
||||||
"org.freedesktop.login1.suspend",
|
[HANDLE_SUSPEND] = {
|
||||||
"org.freedesktop.login1.suspend-multiple-sessions",
|
.handle = HANDLE_SUSPEND,
|
||||||
"org.freedesktop.login1.suspend-ignore-inhibit",
|
.target = SPECIAL_SUSPEND_TARGET,
|
||||||
SLEEP_SUSPEND,
|
.inhibit_what = INHIBIT_SLEEP,
|
||||||
},
|
.polkit_action = "org.freedesktop.login1.suspend",
|
||||||
[HANDLE_HIBERNATE] = {
|
.polkit_action_multiple_sessions = "org.freedesktop.login1.suspend-multiple-sessions",
|
||||||
SPECIAL_HIBERNATE_TARGET,
|
.polkit_action_ignore_inhibit = "org.freedesktop.login1.suspend-ignore-inhibit",
|
||||||
INHIBIT_SLEEP,
|
.sleep_operation = SLEEP_SUSPEND,
|
||||||
"org.freedesktop.login1.hibernate",
|
},
|
||||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
[HANDLE_HIBERNATE] = {
|
||||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
.handle = HANDLE_HIBERNATE,
|
||||||
SLEEP_HIBERNATE,
|
.target = SPECIAL_HIBERNATE_TARGET,
|
||||||
},
|
.inhibit_what = INHIBIT_SLEEP,
|
||||||
[HANDLE_HYBRID_SLEEP] = {
|
.polkit_action = "org.freedesktop.login1.hibernate",
|
||||||
SPECIAL_HYBRID_SLEEP_TARGET,
|
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions",
|
||||||
INHIBIT_SLEEP,
|
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||||
"org.freedesktop.login1.hibernate",
|
.sleep_operation = SLEEP_HIBERNATE,
|
||||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
},
|
||||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
[HANDLE_HYBRID_SLEEP] = {
|
||||||
SLEEP_HYBRID_SLEEP,
|
.handle = HANDLE_HYBRID_SLEEP,
|
||||||
},
|
.target = SPECIAL_HYBRID_SLEEP_TARGET,
|
||||||
[HANDLE_SUSPEND_THEN_HIBERNATE] = {
|
.inhibit_what = INHIBIT_SLEEP,
|
||||||
SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
|
.polkit_action = "org.freedesktop.login1.hibernate",
|
||||||
INHIBIT_SLEEP,
|
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions",
|
||||||
"org.freedesktop.login1.hibernate",
|
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||||
"org.freedesktop.login1.hibernate-multiple-sessions",
|
.sleep_operation = SLEEP_HYBRID_SLEEP,
|
||||||
"org.freedesktop.login1.hibernate-ignore-inhibit",
|
},
|
||||||
SLEEP_SUSPEND_THEN_HIBERNATE,
|
[HANDLE_SUSPEND_THEN_HIBERNATE] = {
|
||||||
},
|
.handle = HANDLE_SUSPEND_THEN_HIBERNATE,
|
||||||
[HANDLE_FACTORY_RESET] = {
|
.target = SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
|
||||||
SPECIAL_FACTORY_RESET_TARGET,
|
.inhibit_what = INHIBIT_SLEEP,
|
||||||
_INHIBIT_WHAT_INVALID,
|
.polkit_action = "org.freedesktop.login1.hibernate",
|
||||||
NULL,
|
.polkit_action_multiple_sessions = "org.freedesktop.login1.hibernate-multiple-sessions",
|
||||||
NULL,
|
.polkit_action_ignore_inhibit = "org.freedesktop.login1.hibernate-ignore-inhibit",
|
||||||
NULL,
|
.sleep_operation = SLEEP_SUSPEND_THEN_HIBERNATE,
|
||||||
_SLEEP_OPERATION_INVALID,
|
},
|
||||||
SD_MESSAGE_FACTORY_RESET_STR,
|
[HANDLE_FACTORY_RESET] = {
|
||||||
"System is performing factory reset",
|
.handle = HANDLE_FACTORY_RESET,
|
||||||
NULL
|
.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) {
|
const ActionTableItem* manager_item_for_handle(HandleAction handle) {
|
||||||
assert(handle >= 0);
|
assert(handle >= 0);
|
||||||
assert(handle < (ssize_t) ELEMENTSOF(action_table));
|
assert(handle < (ssize_t) ELEMENTSOF(action_table));
|
||||||
@ -122,12 +120,6 @@ const ActionTableItem* manager_item_for_handle(HandleAction handle) {
|
|||||||
return &action_table[handle];
|
return &action_table[handle];
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleAction manager_handle_for_item(const ActionTableItem* a) {
|
|
||||||
if (a && a < action_table + ELEMENTSOF(action_table))
|
|
||||||
return a - action_table;
|
|
||||||
return _HANDLE_ACTION_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
int manager_handle_action(
|
int manager_handle_action(
|
||||||
Manager *m,
|
Manager *m,
|
||||||
InhibitWhat inhibit_key,
|
InhibitWhat inhibit_key,
|
||||||
|
|||||||
@ -28,6 +28,7 @@ typedef struct ActionTableItem ActionTableItem;
|
|||||||
#include "sleep-config.h"
|
#include "sleep-config.h"
|
||||||
|
|
||||||
struct ActionTableItem {
|
struct ActionTableItem {
|
||||||
|
HandleAction handle;
|
||||||
const char *target;
|
const char *target;
|
||||||
InhibitWhat inhibit_what;
|
InhibitWhat inhibit_what;
|
||||||
const char *polkit_action;
|
const char *polkit_action;
|
||||||
@ -36,8 +37,7 @@ struct ActionTableItem {
|
|||||||
SleepOperation sleep_operation;
|
SleepOperation sleep_operation;
|
||||||
const char* message_id;
|
const char* message_id;
|
||||||
const char* message;
|
const char* message;
|
||||||
const char* log_str;
|
const char* log_message;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int manager_handle_action(
|
int manager_handle_action(
|
||||||
@ -50,7 +50,6 @@ int manager_handle_action(
|
|||||||
const char* handle_action_to_string(HandleAction h) _const_;
|
const char* handle_action_to_string(HandleAction h) _const_;
|
||||||
HandleAction handle_action_from_string(const char *s) _pure_;
|
HandleAction handle_action_from_string(const char *s) _pure_;
|
||||||
|
|
||||||
const char* manager_target_for_action(HandleAction handle);
|
|
||||||
const ActionTableItem* manager_item_for_handle(HandleAction handle);
|
const ActionTableItem* manager_item_for_handle(HandleAction handle);
|
||||||
HandleAction manager_handle_for_item(const ActionTableItem* a);
|
HandleAction manager_handle_for_item(const ActionTableItem* a);
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,15 @@
|
|||||||
#include "utmp-wtmp.h"
|
#include "utmp-wtmp.h"
|
||||||
#include "virt.h"
|
#include "virt.h"
|
||||||
|
|
||||||
|
/* As a random fun fact sysvinit had a 252 (256-(strlen(" \r\n")+1))
|
||||||
|
* character limit for the wall message.
|
||||||
|
* https://git.savannah.nongnu.org/cgit/sysvinit.git/tree/src/shutdown.c#n72
|
||||||
|
* There is no real technical need for that but doesn't make sense
|
||||||
|
* to store arbitrary amounts either. As we are not stingy here, we
|
||||||
|
* allow 4k.
|
||||||
|
*/
|
||||||
|
#define WALL_MESSAGE_MAX 4096
|
||||||
|
|
||||||
static void reset_scheduled_shutdown(Manager *m);
|
static void reset_scheduled_shutdown(Manager *m);
|
||||||
|
|
||||||
static int get_sender_session(
|
static int get_sender_session(
|
||||||
@ -349,7 +358,7 @@ static int property_get_scheduled_shutdown(
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_bus_message_append(reply, "st",
|
r = sd_bus_message_append(reply, "st",
|
||||||
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);
|
m->scheduled_shutdown_timeout);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -1499,13 +1508,13 @@ static int bus_manager_log_shutdown(
|
|||||||
Manager *m,
|
Manager *m,
|
||||||
const ActionTableItem *a) {
|
const ActionTableItem *a) {
|
||||||
|
|
||||||
const char *message, *log_str;
|
const char *message, *log_message;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(a);
|
assert(a);
|
||||||
|
|
||||||
message = a->message;
|
message = a->message;
|
||||||
log_str = a->log_str;
|
log_message = a->log_message;
|
||||||
|
|
||||||
if (message)
|
if (message)
|
||||||
message = strjoina("MESSAGE=", message);
|
message = strjoina("MESSAGE=", message);
|
||||||
@ -1517,13 +1526,13 @@ static int bus_manager_log_shutdown(
|
|||||||
else
|
else
|
||||||
message = strjoina(message, " (", m->wall_message, ").");
|
message = strjoina(message, " (", m->wall_message, ").");
|
||||||
|
|
||||||
if (log_str)
|
if (log_message)
|
||||||
log_str = strjoina("SHUTDOWN=", log_str);
|
log_message = strjoina("SHUTDOWN=", log_message);
|
||||||
|
|
||||||
return log_struct(LOG_NOTICE,
|
return log_struct(LOG_NOTICE,
|
||||||
"MESSAGE_ID=%s", a->message_id ? a->message_id : SD_MESSAGE_SHUTDOWN_STR,
|
"MESSAGE_ID=%s", a->message_id ? a->message_id : SD_MESSAGE_SHUTDOWN_STR,
|
||||||
message,
|
message,
|
||||||
log_str);
|
log_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
|
static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
|
||||||
@ -1884,7 +1893,7 @@ static int method_do_shutdown_or_sleep(
|
|||||||
return r;
|
return r;
|
||||||
if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
|
if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
|
||||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
|
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
|
||||||
if (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");
|
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Reboot via kexec is only applicable with reboot operations");
|
||||||
} else {
|
} else {
|
||||||
/* Old style method: no flags parameter, but interactive bool passed as boolean in
|
/* Old style method: no flags parameter, but interactive bool passed as boolean in
|
||||||
@ -2035,6 +2044,7 @@ static int update_schedule_file(Manager *m) {
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
assert(m->scheduled_shutdown_type);
|
||||||
|
|
||||||
r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
|
r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -2052,7 +2062,7 @@ static int update_schedule_file(Manager *m) {
|
|||||||
"MODE=%s\n",
|
"MODE=%s\n",
|
||||||
m->scheduled_shutdown_timeout,
|
m->scheduled_shutdown_timeout,
|
||||||
m->enable_wall_messages,
|
m->enable_wall_messages,
|
||||||
handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)));
|
handle_action_to_string(m->scheduled_shutdown_type->handle));
|
||||||
|
|
||||||
if (!isempty(m->wall_message)) {
|
if (!isempty(m->wall_message)) {
|
||||||
_cleanup_free_ char *t = NULL;
|
_cleanup_free_ char *t = NULL;
|
||||||
@ -2240,9 +2250,10 @@ static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userd
|
|||||||
assert(m);
|
assert(m);
|
||||||
assert(message);
|
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)
|
if (!cancelled)
|
||||||
goto done;
|
return sd_bus_reply_method_return(message, "b", false);
|
||||||
|
|
||||||
a = m->scheduled_shutdown_type;
|
a = m->scheduled_shutdown_type;
|
||||||
if (!a->polkit_action)
|
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);
|
username, tty, logind_wall_tty_filter, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
return sd_bus_reply_method_return(message, "b", true);
|
||||||
return sd_bus_reply_method_return(message, "b", cancelled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int method_can_shutdown_or_sleep(
|
static int method_can_shutdown_or_sleep(
|
||||||
@ -2328,7 +2338,7 @@ static int method_can_shutdown_or_sleep(
|
|||||||
if (handle >= 0) {
|
if (handle >= 0) {
|
||||||
const char *target;
|
const char *target;
|
||||||
|
|
||||||
target = manager_target_for_action(handle);
|
target = manager_item_for_handle(handle)->target;
|
||||||
if (target) {
|
if (target) {
|
||||||
_cleanup_free_ char *load_state = NULL;
|
_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);
|
r = manager_read_efi_boot_loader_entries(m);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries);
|
(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(
|
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);
|
r = manager_read_efi_boot_loader_entries(m);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries);
|
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, /* auto_only= */ true);
|
||||||
|
|
||||||
r = sd_bus_message_open_container(reply, 'a', "s");
|
r = sd_bus_message_open_container(reply, 'a', "s");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -3115,14 +3125,10 @@ static int method_set_wall_message(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* sysvinit has a 252 (256-(strlen(" \r\n")+1)) character
|
if (strlen(wall_message) > WALL_MESSAGE_MAX)
|
||||||
* limit for the wall message. There is no real technical
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||||
* need for that but doesn't make sense to store arbitrary
|
"Wall message too long, maximum permitted length is %u characters.",
|
||||||
* amounts either.
|
WALL_MESSAGE_MAX);
|
||||||
* https://git.savannah.nongnu.org/cgit/sysvinit.git/tree/src/shutdown.c#n72)
|
|
||||||
*/
|
|
||||||
if (strlen(wall_message) > 252)
|
|
||||||
return -EMSGSIZE;
|
|
||||||
|
|
||||||
/* Short-circuit the operation if the desired state is already in place, to
|
/* Short-circuit the operation if the desired state is already in place, to
|
||||||
* avoid an unnecessary polkit permission check. */
|
* avoid an unnecessary polkit permission check. */
|
||||||
|
|||||||
@ -64,7 +64,7 @@ static int warn_wall(Manager *m, usec_t n) {
|
|||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
if (!m->enable_wall_messages)
|
if (!m->enable_wall_messages || !m->scheduled_shutdown_type)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
left = m->scheduled_shutdown_timeout > n;
|
left = m->scheduled_shutdown_timeout > n;
|
||||||
@ -72,7 +72,7 @@ static int warn_wall(Manager *m, usec_t n) {
|
|||||||
r = asprintf(&l, "%s%sThe system is going down for %s %s%s!",
|
r = asprintf(&l, "%s%sThe system is going down for %s %s%s!",
|
||||||
strempty(m->wall_message),
|
strempty(m->wall_message),
|
||||||
isempty(m->wall_message) ? "" : "\n",
|
isempty(m->wall_message) ? "" : "\n",
|
||||||
handle_action_to_string(manager_handle_for_item(m->scheduled_shutdown_type)),
|
handle_action_to_string(m->scheduled_shutdown_type->handle),
|
||||||
left ? "at " : "NOW",
|
left ? "at " : "NOW",
|
||||||
left ? FORMAT_TIMESTAMP(m->scheduled_shutdown_timeout) : "");
|
left ? FORMAT_TIMESTAMP(m->scheduled_shutdown_timeout) : "");
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
|||||||
@ -848,10 +848,6 @@ int link_drop_foreign_addresses(Link *link) {
|
|||||||
assert(link);
|
assert(link);
|
||||||
assert(link->network);
|
assert(link->network);
|
||||||
|
|
||||||
/* Keep all addresses when KeepConfiguration=yes. */
|
|
||||||
if (link->network->keep_configuration == KEEP_CONFIGURATION_YES)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* First, mark all addresses. */
|
/* First, mark all addresses. */
|
||||||
SET_FOREACH(address, link->addresses) {
|
SET_FOREACH(address, link->addresses) {
|
||||||
/* We consider IPv6LL addresses to be managed by the kernel, or dropped in link_drop_ipv6ll_addresses() */
|
/* We consider IPv6LL addresses to be managed by the kernel, or dropped in link_drop_ipv6ll_addresses() */
|
||||||
|
|||||||
@ -1240,10 +1240,13 @@ static int link_reconfigure_impl(Link *link, bool force) {
|
|||||||
|
|
||||||
link_drop_requests(link);
|
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,
|
/* When a new/updated .network file is assigned, first make all configs (addresses,
|
||||||
* routes, and so on) foreign, and then drop unnecessary configs later by
|
* routes, and so on) foreign, and then drop unnecessary configs later by
|
||||||
* link_drop_foreign_config() in link_configure(). */
|
* link_drop_foreign_config() in link_configure().
|
||||||
|
* Note, when KeepConfiguration=yes, link_drop_foreign_config() does nothing. Hence,
|
||||||
|
* here we need to drop the configs such as addresses, routes, and so on configured by
|
||||||
|
* the previously assigned .network file. */
|
||||||
link_foreignize_config(link);
|
link_foreignize_config(link);
|
||||||
else {
|
else {
|
||||||
/* Remove all managed configs. Note, foreign configs are removed in later by
|
/* Remove all managed configs. Note, foreign configs are removed in later by
|
||||||
|
|||||||
@ -3453,7 +3453,7 @@ static int inner_child(
|
|||||||
|
|
||||||
assert(!sd_id128_is_null(arg_uuid));
|
assert(!sd_id128_is_null(arg_uuid));
|
||||||
|
|
||||||
if (asprintf(envp + n_env++, "container_uuid=%s", 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();
|
return log_oom();
|
||||||
|
|
||||||
if (fdset_size(fds) > 0) {
|
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)
|
if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_STRING)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ids = new(char, ID128_UUID_STRING_MAX);
|
ids = new(char, SD_ID128_UUID_STRING_MAX);
|
||||||
if (!ids)
|
if (!ids)
|
||||||
return -ENOMEM;
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -2030,7 +2030,7 @@ static int context_dump_partitions(Context *context, const char *node) {
|
|||||||
|
|
||||||
LIST_FOREACH(partitions, p, context->partitions) {
|
LIST_FOREACH(partitions, p, context->partitions) {
|
||||||
_cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL;
|
_cleanup_free_ char *size_change = NULL, *padding_change = NULL, *partname = NULL;
|
||||||
char uuid_buffer[ID128_UUID_STRING_MAX];
|
char uuid_buffer[SD_ID128_UUID_STRING_MAX];
|
||||||
const char *label, *activity = NULL;
|
const char *label, *activity = NULL;
|
||||||
|
|
||||||
if (p->dropped)
|
if (p->dropped)
|
||||||
@ -2176,7 +2176,7 @@ static int partition_hint(const Partition *p, const char *node, char **ret) {
|
|||||||
else
|
else
|
||||||
id = p->type_uuid;
|
id = p->type_uuid;
|
||||||
|
|
||||||
buf = strdup(ID128_TO_UUID_STRING(id));
|
buf = strdup(SD_ID128_TO_UUID_STRING(id));
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (!buf)
|
if (!buf)
|
||||||
@ -2624,7 +2624,7 @@ static int partition_encrypt(
|
|||||||
CRYPT_LUKS2,
|
CRYPT_LUKS2,
|
||||||
"aes",
|
"aes",
|
||||||
"xts-plain64",
|
"xts-plain64",
|
||||||
ID128_TO_UUID_STRING(uuid),
|
SD_ID128_TO_UUID_STRING(uuid),
|
||||||
volume_key,
|
volume_key,
|
||||||
volume_key_size,
|
volume_key_size,
|
||||||
&(struct crypt_params_luks2) {
|
&(struct crypt_params_luks2) {
|
||||||
@ -3304,7 +3304,7 @@ static uint64_t partition_merge_flags(Partition *p) {
|
|||||||
if (gpt_partition_type_knows_no_auto(p->type_uuid))
|
if (gpt_partition_type_knows_no_auto(p->type_uuid))
|
||||||
SET_FLAG(f, GPT_FLAG_NO_AUTO, p->no_auto);
|
SET_FLAG(f, GPT_FLAG_NO_AUTO, p->no_auto);
|
||||||
else {
|
else {
|
||||||
char buffer[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.",
|
log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.",
|
||||||
yes_no(p->no_auto),
|
yes_no(p->no_auto),
|
||||||
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
|
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
|
||||||
@ -3315,7 +3315,7 @@ static uint64_t partition_merge_flags(Partition *p) {
|
|||||||
if (gpt_partition_type_knows_read_only(p->type_uuid))
|
if (gpt_partition_type_knows_read_only(p->type_uuid))
|
||||||
SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
|
SET_FLAG(f, GPT_FLAG_READ_ONLY, p->read_only);
|
||||||
else {
|
else {
|
||||||
char buffer[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.",
|
log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.",
|
||||||
yes_no(p->read_only),
|
yes_no(p->read_only),
|
||||||
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
|
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
|
||||||
@ -3326,7 +3326,7 @@ static uint64_t partition_merge_flags(Partition *p) {
|
|||||||
if (gpt_partition_type_knows_growfs(p->type_uuid))
|
if (gpt_partition_type_knows_growfs(p->type_uuid))
|
||||||
SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs);
|
SET_FLAG(f, GPT_FLAG_GROWFS, p->growfs);
|
||||||
else {
|
else {
|
||||||
char buffer[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.",
|
log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.",
|
||||||
yes_no(p->growfs),
|
yes_no(p->growfs),
|
||||||
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
|
gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer));
|
||||||
@ -3374,7 +3374,7 @@ static int context_mangle_partitions(Context *context) {
|
|||||||
if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
|
if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
|
||||||
assert(!sd_id128_is_null(p->new_uuid));
|
assert(!sd_id128_is_null(p->new_uuid));
|
||||||
|
|
||||||
r = fdisk_partition_set_uuid(p->current_partition, 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)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set partition UUID: %m");
|
return log_error_errno(r, "Failed to set partition UUID: %m");
|
||||||
|
|
||||||
@ -3412,7 +3412,7 @@ static int context_mangle_partitions(Context *context) {
|
|||||||
if (!t)
|
if (!t)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = fdisk_parttype_set_typestr(t, ID128_TO_UUID_STRING(p->type_uuid));
|
r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type_uuid));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to initialize partition type: %m");
|
return log_error_errno(r, "Failed to initialize partition type: %m");
|
||||||
|
|
||||||
@ -3440,7 +3440,7 @@ static int context_mangle_partitions(Context *context) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set partition number: %m");
|
return log_error_errno(r, "Failed to set partition number: %m");
|
||||||
|
|
||||||
r = fdisk_partition_set_uuid(q, ID128_TO_UUID_STRING(p->new_uuid));
|
r = fdisk_partition_set_uuid(q, SD_ID128_TO_UUID_STRING(p->new_uuid));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to set partition UUID: %m");
|
return log_error_errno(r, "Failed to set partition UUID: %m");
|
||||||
|
|
||||||
|
|||||||
@ -41,8 +41,7 @@ int manager_check_resolv_conf(const Manager *m) {
|
|||||||
|
|
||||||
/* Is it symlinked to our own uplink file? */
|
/* Is it symlinked to our own uplink file? */
|
||||||
if (stat(PRIVATE_STATIC_RESOLV_CONF, &own) >= 0 &&
|
if (stat(PRIVATE_STATIC_RESOLV_CONF, &own) >= 0 &&
|
||||||
st.st_dev == own.st_dev &&
|
stat_inode_same(&st, &own))
|
||||||
st.st_ino == own.st_ino)
|
|
||||||
return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
"DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to "
|
"DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to "
|
||||||
PRIVATE_STATIC_RESOLV_CONF " which expects DNSStubListener= to be enabled.");
|
PRIVATE_STATIC_RESOLV_CONF " which expects DNSStubListener= to be enabled.");
|
||||||
@ -64,8 +63,7 @@ static bool file_is_our_own(const struct stat *st) {
|
|||||||
|
|
||||||
/* Is it symlinked to our own uplink file? */
|
/* Is it symlinked to our own uplink file? */
|
||||||
if (stat(path, &own) >= 0 &&
|
if (stat(path, &own) >= 0 &&
|
||||||
st->st_dev == own.st_dev &&
|
stat_inode_same(st, &own))
|
||||||
st->st_ino == own.st_ino)
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,8 +416,7 @@ int resolv_conf_mode(void) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system_st.st_dev == our_st.st_dev &&
|
if (stat_inode_same(&system_st, &our_st))
|
||||||
system_st.st_ino == our_st.st_ino)
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,8 @@
|
|||||||
#include "errno-util.h"
|
#include "errno-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
#include "gpt.h"
|
||||||
|
#include "id128-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pe-header.h"
|
#include "pe-header.h"
|
||||||
@ -51,6 +53,7 @@ static void boot_entry_free(BootEntry *entry) {
|
|||||||
free(entry->efi);
|
free(entry->efi);
|
||||||
strv_free(entry->initrd);
|
strv_free(entry->initrd);
|
||||||
free(entry->device_tree);
|
free(entry->device_tree);
|
||||||
|
strv_free(entry->device_tree_overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int boot_entry_load(
|
static int boot_entry_load(
|
||||||
@ -64,26 +67,28 @@ static int boot_entry_load(
|
|||||||
|
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
unsigned line = 1;
|
unsigned line = 1;
|
||||||
char *b, *c;
|
char *c;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(root);
|
assert(root);
|
||||||
assert(path);
|
assert(path);
|
||||||
assert(entry);
|
assert(entry);
|
||||||
|
|
||||||
c = endswith_no_case(path, ".conf");
|
r = path_extract_filename(path, &tmp.id);
|
||||||
if (!c)
|
if (r < 0)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", path);
|
return log_error_errno(r, "Failed to extract file name from path '%s': %m", path);
|
||||||
|
|
||||||
b = basename(path);
|
c = endswith_no_case(tmp.id, ".conf");
|
||||||
tmp.id = strdup(b);
|
if (!c)
|
||||||
tmp.id_old = strndup(b, c - b);
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", tmp.id);
|
||||||
if (!tmp.id || !tmp.id_old)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
if (!efi_loader_entry_name_valid(tmp.id))
|
if (!efi_loader_entry_name_valid(tmp.id))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry name: %s", tmp.id);
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry name: %s", tmp.id);
|
||||||
|
|
||||||
|
tmp.id_old = strndup(tmp.id, c - tmp.id);
|
||||||
|
if (!tmp.id_old)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
tmp.path = strdup(path);
|
tmp.path = strdup(path);
|
||||||
if (!tmp.path)
|
if (!tmp.path)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
@ -142,7 +147,15 @@ static int boot_entry_load(
|
|||||||
r = strv_extend(&tmp.initrd, p);
|
r = strv_extend(&tmp.initrd, p);
|
||||||
else if (streq(field, "devicetree"))
|
else if (streq(field, "devicetree"))
|
||||||
r = free_and_strdup(&tmp.device_tree, p);
|
r = free_and_strdup(&tmp.device_tree, p);
|
||||||
else {
|
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);
|
log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -167,9 +180,11 @@ void boot_config_free(BootConfig *config) {
|
|||||||
free(config->auto_firmware);
|
free(config->auto_firmware);
|
||||||
free(config->console_mode);
|
free(config->console_mode);
|
||||||
free(config->random_seed_mode);
|
free(config->random_seed_mode);
|
||||||
|
free(config->beep);
|
||||||
|
|
||||||
free(config->entry_oneshot);
|
free(config->entry_oneshot);
|
||||||
free(config->entry_default);
|
free(config->entry_default);
|
||||||
|
free(config->entry_selected);
|
||||||
|
|
||||||
for (i = 0; i < config->n_entries; i++)
|
for (i = 0; i < config->n_entries; i++)
|
||||||
boot_entry_free(config->entries + i);
|
boot_entry_free(config->entries + i);
|
||||||
@ -234,6 +249,8 @@ static int boot_loader_read_conf(const char *path, BootConfig *config) {
|
|||||||
r = free_and_strdup(&config->console_mode, p);
|
r = free_and_strdup(&config->console_mode, p);
|
||||||
else if (streq(field, "random-seed-mode"))
|
else if (streq(field, "random-seed-mode"))
|
||||||
r = free_and_strdup(&config->random_seed_mode, p);
|
r = free_and_strdup(&config->random_seed_mode, p);
|
||||||
|
else if (streq(field, "beep"))
|
||||||
|
r = free_and_strdup(&config->beep, p);
|
||||||
else {
|
else {
|
||||||
log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field);
|
log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field);
|
||||||
continue;
|
continue;
|
||||||
@ -546,18 +563,17 @@ static int boot_entries_find_unified(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) {
|
static bool find_nonunique(const BootEntry *entries, size_t n_entries, bool arr[]) {
|
||||||
size_t i, j;
|
|
||||||
bool non_unique = false;
|
bool non_unique = false;
|
||||||
|
|
||||||
assert(entries || n_entries == 0);
|
assert(entries || n_entries == 0);
|
||||||
assert(arr || n_entries == 0);
|
assert(arr || n_entries == 0);
|
||||||
|
|
||||||
for (i = 0; i < n_entries; i++)
|
for (size_t i = 0; i < n_entries; i++)
|
||||||
arr[i] = false;
|
arr[i] = false;
|
||||||
|
|
||||||
for (i = 0; i < n_entries; i++)
|
for (size_t i = 0; i < n_entries; i++)
|
||||||
for (j = 0; j < n_entries; j++)
|
for (size_t j = 0; j < n_entries; j++)
|
||||||
if (i != j && streq(boot_entry_title(entries + i),
|
if (i != j && streq(boot_entry_title(entries + i),
|
||||||
boot_entry_title(entries + j)))
|
boot_entry_title(entries + j)))
|
||||||
non_unique = arr[i] = arr[j] = true;
|
non_unique = arr[i] = arr[j] = true;
|
||||||
@ -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) {
|
static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) {
|
||||||
|
_cleanup_free_ bool *arr = NULL;
|
||||||
char *s;
|
char *s;
|
||||||
size_t i;
|
|
||||||
int r;
|
|
||||||
bool arr[n_entries];
|
|
||||||
|
|
||||||
assert(entries || n_entries == 0);
|
assert(entries || n_entries == 0);
|
||||||
|
|
||||||
|
if (n_entries == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
arr = new(bool, n_entries);
|
||||||
|
if (!arr)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Find _all_ non-unique titles */
|
/* Find _all_ non-unique titles */
|
||||||
if (!find_nonunique(entries, n_entries, arr))
|
if (!find_nonunique(entries, n_entries, arr))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Add version to non-unique titles */
|
/* Add version to non-unique titles */
|
||||||
for (i = 0; i < n_entries; i++)
|
for (size_t i = 0; i < n_entries; i++)
|
||||||
if (arr[i] && entries[i].version) {
|
if (arr[i] && entries[i].version) {
|
||||||
r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version);
|
if (asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version) < 0)
|
||||||
if (r < 0)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
free_and_replace(entries[i].show_title, s);
|
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;
|
return 0;
|
||||||
|
|
||||||
/* Add machine-id to non-unique titles */
|
/* 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) {
|
if (arr[i] && entries[i].machine_id) {
|
||||||
r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id);
|
if (asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id) < 0)
|
||||||
if (r < 0)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
free_and_replace(entries[i].show_title, s);
|
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;
|
return 0;
|
||||||
|
|
||||||
/* Add file name to non-unique titles */
|
/* 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]) {
|
if (arr[i]) {
|
||||||
r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].id);
|
if (asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].id) < 0)
|
||||||
if (r < 0)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
free_and_replace(entries[i].show_title, s);
|
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;
|
return config->n_entries - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int boot_entries_select_selected(const BootConfig *config) {
|
||||||
|
|
||||||
|
assert(config);
|
||||||
|
assert(config->entries || config->n_entries == 0);
|
||||||
|
|
||||||
|
if (!config->entry_selected || config->n_entries == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (int i = config->n_entries - 1; i >= 0; i--)
|
||||||
|
if (streq(config->entry_selected, config->entries[i].id))
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int boot_load_efi_entry_pointers(BootConfig *config) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(config);
|
||||||
|
|
||||||
|
if (!is_efi_boot())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Loads the three "pointers" to boot loader entries from their EFI variables */
|
||||||
|
|
||||||
|
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryOneShot), &config->entry_oneshot);
|
||||||
|
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
|
||||||
|
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m");
|
||||||
|
if (r == -ENOMEM)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryDefault), &config->entry_default);
|
||||||
|
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
|
||||||
|
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m");
|
||||||
|
if (r == -ENOMEM)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntrySelected), &config->entry_selected);
|
||||||
|
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
|
||||||
|
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntrySelected\": %m");
|
||||||
|
if (r == -ENOMEM)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int boot_entries_load_config(
|
int boot_entries_load_config(
|
||||||
const char *esp_path,
|
const char *esp_path,
|
||||||
const char *xbootldr_path,
|
const char *xbootldr_path,
|
||||||
@ -700,23 +767,13 @@ int boot_entries_load_config(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to uniquify boot entries: %m");
|
return log_error_errno(r, "Failed to uniquify boot entries: %m");
|
||||||
|
|
||||||
if (is_efi_boot()) {
|
r = boot_load_efi_entry_pointers(config);
|
||||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryOneShot), &config->entry_oneshot);
|
if (r < 0)
|
||||||
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
|
return r;
|
||||||
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m");
|
|
||||||
if (r == -ENOMEM)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryDefault), &config->entry_default);
|
|
||||||
if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
|
|
||||||
log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m");
|
|
||||||
if (r == -ENOMEM)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config->default_entry = boot_entries_select_default(config);
|
config->default_entry = boot_entries_select_default(config);
|
||||||
|
config->selected_entry = boot_entries_select_selected(config);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,6 +783,7 @@ int boot_entries_load_config_auto(
|
|||||||
BootConfig *config) {
|
BootConfig *config) {
|
||||||
|
|
||||||
_cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL;
|
_cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL;
|
||||||
|
dev_t esp_devid = 0, xbootldr_devid = 0;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(config);
|
assert(config);
|
||||||
@ -746,20 +804,25 @@ int boot_entries_load_config_auto(
|
|||||||
"Failed to determine whether /run/boot-loader-entries/ exists: %m");
|
"Failed to determine whether /run/boot-loader-entries/ exists: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
r = find_esp_and_warn(override_esp_path, 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 */
|
if (r < 0) /* we don't log about ENOKEY here, but propagate it, leaving it to the caller to log */
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = find_xbootldr_and_warn(override_xbootldr_path, 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)
|
if (r < 0 && r != -ENOKEY)
|
||||||
return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */
|
return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */
|
||||||
|
|
||||||
|
/* If both paths actually refer to the same inode, suppress the xbootldr path */
|
||||||
|
if (esp_where && xbootldr_where && devid_set_and_equal(esp_devid, xbootldr_devid))
|
||||||
|
xbootldr_where = mfree(xbootldr_where);
|
||||||
|
|
||||||
return boot_entries_load_config(esp_where, xbootldr_where, config);
|
return boot_entries_load_config(esp_where, xbootldr_where, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
int boot_entries_augment_from_loader(
|
int boot_entries_augment_from_loader(
|
||||||
BootConfig *config,
|
BootConfig *config,
|
||||||
char **found_by_loader) {
|
char **found_by_loader,
|
||||||
|
bool only_auto) {
|
||||||
|
|
||||||
static const char *const title_table[] = {
|
static const char *const title_table[] = {
|
||||||
/* Pretty names for a few well-known automatically discovered entries. */
|
/* Pretty names for a few well-known automatically discovered entries. */
|
||||||
@ -778,18 +841,17 @@ int boot_entries_augment_from_loader(
|
|||||||
* already included there. */
|
* already included there. */
|
||||||
|
|
||||||
STRV_FOREACH(i, found_by_loader) {
|
STRV_FOREACH(i, found_by_loader) {
|
||||||
|
BootEntry *existing;
|
||||||
_cleanup_free_ char *c = NULL, *t = NULL, *p = NULL;
|
_cleanup_free_ char *c = NULL, *t = NULL, *p = NULL;
|
||||||
char **a, **b;
|
char **a, **b;
|
||||||
|
|
||||||
if (boot_config_has_entry(config, *i))
|
existing = boot_config_find_entry(config, *i);
|
||||||
|
if (existing) {
|
||||||
|
existing->reported_by_loader = true;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
if (only_auto && !startswith(*i, "auto-"))
|
||||||
* consider the 'auto-' entries only, because the others
|
|
||||||
* ones are detected scanning the 'esp' and 'xbootldr'
|
|
||||||
* directories by boot_entries_load_config()
|
|
||||||
*/
|
|
||||||
if (!startswith(*i, "auto-"))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
c = strdup(*i);
|
c = strdup(*i);
|
||||||
@ -812,10 +874,11 @@ int boot_entries_augment_from_loader(
|
|||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
config->entries[config->n_entries++] = (BootEntry) {
|
config->entries[config->n_entries++] = (BootEntry) {
|
||||||
.type = BOOT_ENTRY_LOADER,
|
.type = startswith(*i, "auto-") ? BOOT_ENTRY_LOADER_AUTO : BOOT_ENTRY_LOADER,
|
||||||
.id = TAKE_PTR(c),
|
.id = TAKE_PTR(c),
|
||||||
.title = TAKE_PTR(t),
|
.title = TAKE_PTR(t),
|
||||||
.path = TAKE_PTR(p),
|
.path = TAKE_PTR(p),
|
||||||
|
.reported_by_loader = true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -889,7 +952,7 @@ static int verify_esp_blkid(
|
|||||||
r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
|
r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return log_error_errno(errno ?: EIO, "Failed to probe partition type UUID of \"%s\": %m", node);
|
return log_error_errno(errno ?: EIO, "Failed to probe partition type UUID of \"%s\": %m", node);
|
||||||
if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"))
|
if (id128_equal_string(v, GPT_ESP) <= 0)
|
||||||
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
||||||
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
|
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
|
||||||
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
|
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
|
||||||
@ -982,7 +1045,7 @@ static int verify_esp_udev(
|
|||||||
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
|
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get device property: %m");
|
return log_error_errno(r, "Failed to get device property: %m");
|
||||||
if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"))
|
if (id128_equal_string(v, GPT_ESP) <= 0)
|
||||||
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
||||||
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
|
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
|
||||||
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
|
"File system \"%s\" has wrong type for an EFI System Partition (ESP).", node);
|
||||||
@ -1107,7 +1170,8 @@ static int verify_esp(
|
|||||||
uint32_t *ret_part,
|
uint32_t *ret_part,
|
||||||
uint64_t *ret_pstart,
|
uint64_t *ret_pstart,
|
||||||
uint64_t *ret_psize,
|
uint64_t *ret_psize,
|
||||||
sd_id128_t *ret_uuid) {
|
sd_id128_t *ret_uuid,
|
||||||
|
dev_t *ret_devid) {
|
||||||
|
|
||||||
bool relax_checks;
|
bool relax_checks;
|
||||||
dev_t devid;
|
dev_t devid;
|
||||||
@ -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
|
* however blkid can't work if we have no privileges to access block devices directly, which is why
|
||||||
* we use udev in that case. */
|
* we use udev in that case. */
|
||||||
if (unprivileged_mode)
|
if (unprivileged_mode)
|
||||||
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
|
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:
|
finish:
|
||||||
if (ret_part)
|
if (ret_part)
|
||||||
@ -1170,6 +1241,8 @@ finish:
|
|||||||
*ret_psize = 0;
|
*ret_psize = 0;
|
||||||
if (ret_uuid)
|
if (ret_uuid)
|
||||||
*ret_uuid = SD_ID128_NULL;
|
*ret_uuid = SD_ID128_NULL;
|
||||||
|
if (ret_devid)
|
||||||
|
*ret_devid = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1181,7 +1254,8 @@ int find_esp_and_warn(
|
|||||||
uint32_t *ret_part,
|
uint32_t *ret_part,
|
||||||
uint64_t *ret_pstart,
|
uint64_t *ret_pstart,
|
||||||
uint64_t *ret_psize,
|
uint64_t *ret_psize,
|
||||||
sd_id128_t *ret_uuid) {
|
sd_id128_t *ret_uuid,
|
||||||
|
dev_t *ret_devid) {
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1192,7 +1266,7 @@ int find_esp_and_warn(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (path) {
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1201,19 +1275,39 @@ int find_esp_and_warn(
|
|||||||
|
|
||||||
path = getenv("SYSTEMD_ESP_PATH");
|
path = getenv("SYSTEMD_ESP_PATH");
|
||||||
if (path) {
|
if (path) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
if (!path_is_valid(path) || !path_is_absolute(path))
|
if (!path_is_valid(path) || !path_is_absolute(path))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"$SYSTEMD_ESP_PATH does not refer to absolute path, refusing to use it: %s",
|
"$SYSTEMD_ESP_PATH does not refer to absolute path, refusing to use it: %s",
|
||||||
path);
|
path);
|
||||||
|
|
||||||
/* Note: when the user explicitly configured things with an env var we won't validate the mount
|
/* Note: when the user explicitly configured things with an env var we won't validate the
|
||||||
* point. After all we want this to be useful for testing. */
|
* 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;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_STRING(path, "/efi", "/boot", "/boot/efi") {
|
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)
|
if (r >= 0)
|
||||||
goto found;
|
goto found;
|
||||||
if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
|
if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
|
||||||
@ -1280,7 +1374,7 @@ static int verify_xbootldr_blkid(
|
|||||||
r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
|
r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition type UUID of \"%s\": %m", node);
|
return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition type UUID of \"%s\": %m", node);
|
||||||
if (!streq(v, "bc13c2ff-59e6-4262-a352-b275fd6f7172"))
|
if (id128_equal_string(v, GPT_XBOOTLDR) <= 0)
|
||||||
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
||||||
searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV),
|
searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV),
|
||||||
"File system \"%s\" has wrong type for extended boot loader partition.", node);
|
"File system \"%s\" has wrong type for extended boot loader partition.", node);
|
||||||
@ -1344,7 +1438,7 @@ static int verify_xbootldr_udev(
|
|||||||
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
|
r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get device property: %m");
|
return log_error_errno(r, "Failed to get device property: %m");
|
||||||
if (!streq(v, "bc13c2ff-59e6-4262-a352-b275fd6f7172"))
|
if (id128_equal_string(v, GPT_XBOOTLDR))
|
||||||
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
||||||
searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV),
|
searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV),
|
||||||
"File system \"%s\" has wrong type for extended boot loader partition.", node);
|
"File system \"%s\" has wrong type for extended boot loader partition.", node);
|
||||||
@ -1380,7 +1474,8 @@ static int verify_xbootldr(
|
|||||||
const char *p,
|
const char *p,
|
||||||
bool searching,
|
bool searching,
|
||||||
bool unprivileged_mode,
|
bool unprivileged_mode,
|
||||||
sd_id128_t *ret_uuid) {
|
sd_id128_t *ret_uuid,
|
||||||
|
dev_t *ret_devid) {
|
||||||
|
|
||||||
bool relax_checks;
|
bool relax_checks;
|
||||||
dev_t devid;
|
dev_t devid;
|
||||||
@ -1398,13 +1493,22 @@ static int verify_xbootldr(
|
|||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
if (unprivileged_mode)
|
if (unprivileged_mode)
|
||||||
return verify_xbootldr_udev(devid, searching, ret_uuid);
|
r = verify_xbootldr_udev(devid, searching, ret_uuid);
|
||||||
else
|
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:
|
finish:
|
||||||
if (ret_uuid)
|
if (ret_uuid)
|
||||||
*ret_uuid = SD_ID128_NULL;
|
*ret_uuid = SD_ID128_NULL;
|
||||||
|
if (ret_devid)
|
||||||
|
*ret_devid = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1413,14 +1517,15 @@ int find_xbootldr_and_warn(
|
|||||||
const char *path,
|
const char *path,
|
||||||
bool unprivileged_mode,
|
bool unprivileged_mode,
|
||||||
char **ret_path,
|
char **ret_path,
|
||||||
sd_id128_t *ret_uuid) {
|
sd_id128_t *ret_uuid,
|
||||||
|
dev_t *ret_devid) {
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Similar to find_esp_and_warn(), but finds the XBOOTLDR partition. Returns the same errors. */
|
/* Similar to find_esp_and_warn(), but finds the XBOOTLDR partition. Returns the same errors. */
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
r = verify_xbootldr(path, false, unprivileged_mode, ret_uuid);
|
r = verify_xbootldr(path, /* searching= */ false, unprivileged_mode, ret_uuid, ret_devid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1429,15 +1534,27 @@ int find_xbootldr_and_warn(
|
|||||||
|
|
||||||
path = getenv("SYSTEMD_XBOOTLDR_PATH");
|
path = getenv("SYSTEMD_XBOOTLDR_PATH");
|
||||||
if (path) {
|
if (path) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
if (!path_is_valid(path) || !path_is_absolute(path))
|
if (!path_is_valid(path) || !path_is_absolute(path))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"$SYSTEMD_XBOOTLDR_PATH does not refer to absolute path, refusing to use it: %s",
|
"$SYSTEMD_XBOOTLDR_PATH does not refer to absolute path, refusing to use it: %s",
|
||||||
path);
|
path);
|
||||||
|
|
||||||
|
if (stat(path, &st) < 0)
|
||||||
|
return log_error_errno(errno, "Failed to stat '%s': %m", path);
|
||||||
|
if (!S_ISDIR(st.st_mode))
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "XBOOTLDR path '%s' is not a directory.", path);
|
||||||
|
|
||||||
|
if (ret_uuid)
|
||||||
|
*ret_uuid = SD_ID128_NULL;
|
||||||
|
if (ret_devid)
|
||||||
|
*ret_devid = st.st_dev;
|
||||||
|
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = verify_xbootldr("/boot", true, unprivileged_mode, ret_uuid);
|
r = verify_xbootldr("/boot", true, unprivileged_mode, ret_uuid, ret_devid);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
path = "/boot";
|
path = "/boot";
|
||||||
goto found;
|
goto found;
|
||||||
|
|||||||
@ -11,15 +11,17 @@
|
|||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
|
||||||
typedef enum BootEntryType {
|
typedef enum BootEntryType {
|
||||||
BOOT_ENTRY_CONF, /* Type #1 entries: *.conf files */
|
BOOT_ENTRY_CONF, /* Boot Loader Specification Type #1 entries: *.conf files */
|
||||||
BOOT_ENTRY_UNIFIED, /* Type #2 entries: *.efi files */
|
BOOT_ENTRY_UNIFIED, /* Boot Loader Specification Type #2 entries: *.efi files */
|
||||||
BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI var */
|
BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI variable (regular entries) */
|
||||||
_BOOT_ENTRY_MAX,
|
BOOT_ENTRY_LOADER_AUTO, /* Additional entries augmented from LoaderEntries EFI variable (special "automatic" entries) */
|
||||||
_BOOT_ENTRY_INVALID = -EINVAL,
|
_BOOT_ENTRY_TYPE_MAX,
|
||||||
|
_BOOT_ENTRY_TYPE_INVALID = -EINVAL,
|
||||||
} BootEntryType;
|
} BootEntryType;
|
||||||
|
|
||||||
typedef struct BootEntry {
|
typedef struct BootEntry {
|
||||||
BootEntryType type;
|
BootEntryType type;
|
||||||
|
bool reported_by_loader;
|
||||||
char *id; /* This is the file basename (including extension!) */
|
char *id; /* This is the file basename (including extension!) */
|
||||||
char *id_old; /* Old-style ID, for deduplication purposes. */
|
char *id_old; /* Old-style ID, for deduplication purposes. */
|
||||||
char *path; /* This is the full path to the drop-in file */
|
char *path; /* This is the full path to the drop-in file */
|
||||||
@ -34,6 +36,7 @@ typedef struct BootEntry {
|
|||||||
char *efi;
|
char *efi;
|
||||||
char **initrd;
|
char **initrd;
|
||||||
char *device_tree;
|
char *device_tree;
|
||||||
|
char **device_tree_overlay;
|
||||||
} BootEntry;
|
} BootEntry;
|
||||||
|
|
||||||
typedef struct BootConfig {
|
typedef struct BootConfig {
|
||||||
@ -44,29 +47,33 @@ typedef struct BootConfig {
|
|||||||
char *auto_firmware;
|
char *auto_firmware;
|
||||||
char *console_mode;
|
char *console_mode;
|
||||||
char *random_seed_mode;
|
char *random_seed_mode;
|
||||||
|
char *beep;
|
||||||
|
|
||||||
char *entry_oneshot;
|
char *entry_oneshot;
|
||||||
char *entry_default;
|
char *entry_default;
|
||||||
|
char *entry_selected;
|
||||||
|
|
||||||
BootEntry *entries;
|
BootEntry *entries;
|
||||||
size_t n_entries;
|
size_t n_entries;
|
||||||
ssize_t default_entry;
|
ssize_t default_entry;
|
||||||
|
ssize_t selected_entry;
|
||||||
} BootConfig;
|
} BootConfig;
|
||||||
|
|
||||||
static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
|
static inline BootEntry* boot_config_find_entry(BootConfig *config, const char *id) {
|
||||||
size_t j;
|
assert(config);
|
||||||
|
assert(id);
|
||||||
|
|
||||||
for (j = 0; j < config->n_entries; j++) {
|
for (size_t j = 0; j < config->n_entries; j++)
|
||||||
const char* entry_id_old = config->entries[j].id_old;
|
if (streq_ptr(config->entries[j].id, id) ||
|
||||||
if (streq(config->entries[j].id, id) ||
|
streq_ptr(config->entries[j].id_old, id))
|
||||||
(entry_id_old && streq(entry_id_old, id)))
|
return config->entries + j;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline BootEntry* boot_config_default_entry(BootConfig *config) {
|
static inline BootEntry* boot_config_default_entry(BootConfig *config) {
|
||||||
|
assert(config);
|
||||||
|
|
||||||
if (config->default_entry < 0)
|
if (config->default_entry < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -76,11 +83,13 @@ static inline BootEntry* boot_config_default_entry(BootConfig *config) {
|
|||||||
void boot_config_free(BootConfig *config);
|
void boot_config_free(BootConfig *config);
|
||||||
int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
|
int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
|
||||||
int boot_entries_load_config_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config);
|
int boot_entries_load_config_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config);
|
||||||
int boot_entries_augment_from_loader(BootConfig *config, char **list);
|
int boot_entries_augment_from_loader(BootConfig *config, char **list, bool only_auto);
|
||||||
|
|
||||||
static inline const char* boot_entry_title(const BootEntry *entry) {
|
static inline const char* boot_entry_title(const BootEntry *entry) {
|
||||||
|
assert(entry);
|
||||||
|
|
||||||
return entry->show_title ?: entry->title ?: entry->id;
|
return entry->show_title ?: entry->title ?: entry->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid);
|
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);
|
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: {
|
case TABLE_UUID: {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = new(char, ID128_UUID_STRING_MAX);
|
p = new(char, SD_ID128_UUID_STRING_MAX);
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
d->formatted = id128_to_uuid_string(d->id128, p);
|
d->formatted = sd_id128_to_uuid_string(d->id128, p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2562,7 +2562,7 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) {
|
|||||||
return json_variant_new_string(ret, SD_ID128_TO_STRING(d->id128));
|
return json_variant_new_string(ret, SD_ID128_TO_STRING(d->id128));
|
||||||
|
|
||||||
case TABLE_UUID:
|
case TABLE_UUID:
|
||||||
return json_variant_new_string(ret, ID128_TO_UUID_STRING(d->id128));
|
return json_variant_new_string(ret, SD_ID128_TO_UUID_STRING(d->id128));
|
||||||
|
|
||||||
case TABLE_UID:
|
case TABLE_UID:
|
||||||
if (!uid_is_valid(d->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(
|
const char *gpt_partition_type_uuid_to_string_harder(
|
||||||
sd_id128_t id,
|
sd_id128_t id,
|
||||||
char buffer[static ID128_UUID_STRING_MAX]) {
|
char buffer[static SD_ID128_UUID_STRING_MAX]) {
|
||||||
|
|
||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ const char *gpt_partition_type_uuid_to_string_harder(
|
|||||||
if (s)
|
if (s)
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
return 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) {
|
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(sd_id128_t id);
|
||||||
const char *gpt_partition_type_uuid_to_string_harder(
|
const char *gpt_partition_type_uuid_to_string_harder(
|
||||||
sd_id128_t id,
|
sd_id128_t id,
|
||||||
char buffer[static 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);
|
int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret);
|
||||||
|
|
||||||
Architecture gpt_partition_type_uuid_to_arch(sd_id128_t id);
|
Architecture gpt_partition_type_uuid_to_arch(sd_id128_t id);
|
||||||
|
|||||||
@ -1510,7 +1510,7 @@ int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
|
|||||||
static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
|
static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
|
||||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
|
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
|
||||||
char buf[ID128_UUID_STRING_MAX];
|
char buf[SD_ID128_UUID_STRING_MAX];
|
||||||
pid_t pid, child;
|
pid_t pid, child;
|
||||||
ssize_t k;
|
ssize_t k;
|
||||||
int r;
|
int r;
|
||||||
|
|||||||
@ -94,7 +94,7 @@ int make_filesystem(
|
|||||||
bool discard) {
|
bool discard) {
|
||||||
|
|
||||||
_cleanup_free_ char *mkfs = NULL, *mangled_label = NULL;
|
_cleanup_free_ char *mkfs = NULL, *mangled_label = NULL;
|
||||||
char vol_id[CONST_MAX(ID128_UUID_STRING_MAX, 8 + 1)] = {};
|
char vol_id[CONST_MAX(SD_ID128_UUID_STRING_MAX, 8U + 1U)] = {};
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(node);
|
assert(node);
|
||||||
@ -144,7 +144,7 @@ int make_filesystem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isempty(vol_id))
|
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);
|
r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|||||||
@ -816,7 +816,7 @@ static int mount_in_namespace(
|
|||||||
return log_debug_errno(errno, "Failed to fstat mount namespace FD of systemd: %m");
|
return log_debug_errno(errno, "Failed to fstat mount namespace FD of systemd: %m");
|
||||||
|
|
||||||
/* We can't add new mounts at runtime if the process wasn't started in a namespace */
|
/* We can't add new mounts at runtime if the process wasn't started in a namespace */
|
||||||
if (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");
|
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to activate bind mount in target, not running in a mount namespace");
|
||||||
|
|
||||||
/* One day, when bind mounting /proc/self/fd/n works across namespace boundaries we should rework
|
/* One day, when bind mounting /proc/self/fd/n works across namespace boundaries we should rework
|
||||||
|
|||||||
@ -351,7 +351,7 @@ void log_device_uevent(sd_device *device, const char *str) {
|
|||||||
strempty(str), isempty(str) ? "" : " ",
|
strempty(str), isempty(str) ? "" : " ",
|
||||||
seqnum, strna(device_action_to_string(action)),
|
seqnum, strna(device_action_to_string(action)),
|
||||||
sd_id128_is_null(event_id) ? "" : ", UUID=",
|
sd_id128_is_null(event_id) ? "" : ", UUID=",
|
||||||
sd_id128_is_null(event_id) ? "" : 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) {
|
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-halt.h"
|
||||||
#include "systemctl-compat-telinit.h"
|
#include "systemctl-compat-telinit.h"
|
||||||
#include "systemctl-logind.h"
|
#include "systemctl-logind.h"
|
||||||
|
#include "systemctl-start-unit.h"
|
||||||
#include "systemctl-util.h"
|
#include "systemctl-util.h"
|
||||||
#include "systemctl.h"
|
#include "systemctl.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
@ -144,30 +145,32 @@ int halt_parse_argv(int argc, char *argv[]) {
|
|||||||
int halt_main(void) {
|
int halt_main(void) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* always try logind first */
|
if (arg_force == 0) {
|
||||||
if (arg_when > 0)
|
/* always try logind first */
|
||||||
r = logind_schedule_shutdown();
|
if (arg_when > 0)
|
||||||
else {
|
r = logind_schedule_shutdown();
|
||||||
r = logind_check_inhibitors(arg_action);
|
else {
|
||||||
if (r < 0)
|
r = logind_check_inhibitors(arg_action);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = logind_reboot(arg_action);
|
||||||
|
}
|
||||||
|
if (r >= 0)
|
||||||
return r;
|
return r;
|
||||||
|
if (IN_SET(r, -EACCES, -EOPNOTSUPP, -EINPROGRESS))
|
||||||
|
/* Requested operation requires auth, is not supported on the local system or already in
|
||||||
|
* progress */
|
||||||
|
return r;
|
||||||
|
/* on all other errors, try low-level operation */
|
||||||
|
|
||||||
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) {
|
if (geteuid() != 0) {
|
||||||
(void) must_be_root();
|
(void) must_be_root();
|
||||||
|
|||||||
@ -35,11 +35,14 @@ union sd_id128 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define SD_ID128_STRING_MAX 33U
|
#define SD_ID128_STRING_MAX 33U
|
||||||
|
#define SD_ID128_UUID_STRING_MAX 37U
|
||||||
|
|
||||||
char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]);
|
char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]);
|
||||||
|
char *sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_UUID_STRING_MAX]);
|
||||||
int sd_id128_from_string(const char *s, sd_id128_t *ret);
|
int sd_id128_from_string(const char *s, sd_id128_t *ret);
|
||||||
|
|
||||||
#define SD_ID128_TO_STRING(id) sd_id128_to_string((id), (char[SD_ID128_STRING_MAX]) {})
|
#define SD_ID128_TO_STRING(id) sd_id128_to_string((id), (char[SD_ID128_STRING_MAX]) {})
|
||||||
|
#define SD_ID128_TO_UUID_STRING(id) sd_id128_to_uuid_string((id), (char[SD_ID128_UUID_STRING_MAX]) {})
|
||||||
|
|
||||||
int sd_id128_randomize(sd_id128_t *ret);
|
int sd_id128_randomize(sd_id128_t *ret);
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
TEST(id128) {
|
TEST(id128) {
|
||||||
sd_id128_t id, id2;
|
sd_id128_t id, id2;
|
||||||
char t[SD_ID128_STRING_MAX], q[ID128_UUID_STRING_MAX];
|
char t[SD_ID128_STRING_MAX], q[SD_ID128_UUID_STRING_MAX];
|
||||||
_cleanup_free_ char *b = NULL;
|
_cleanup_free_ char *b = NULL;
|
||||||
_cleanup_close_ int fd = -1;
|
_cleanup_close_ int fd = -1;
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ TEST(id128) {
|
|||||||
printf("waldi2: %s\n", b);
|
printf("waldi2: %s\n", b);
|
||||||
assert_se(streq(t, b));
|
assert_se(streq(t, b));
|
||||||
|
|
||||||
printf("waldi3: %s\n", 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));
|
assert_se(streq(q, UUID_WALDI));
|
||||||
|
|
||||||
b = mfree(b);
|
b = mfree(b);
|
||||||
@ -136,7 +136,7 @@ TEST(id128) {
|
|||||||
assert_se(ftruncate(fd, 0) >= 0);
|
assert_se(ftruncate(fd, 0) >= 0);
|
||||||
|
|
||||||
assert_se(sd_id128_randomize(&id) >= 0);
|
assert_se(sd_id128_randomize(&id) >= 0);
|
||||||
assert_se(write(fd, 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(lseek(fd, 0, SEEK_SET) == 0);
|
||||||
assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL);
|
assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL);
|
||||||
|
|||||||
@ -213,7 +213,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
} else if (proc_cmdline_key_streq(key, "usrhash")) {
|
} else if (proc_cmdline_key_streq(key, "usrhash")) {
|
||||||
|
|
||||||
if (proc_cmdline_value_missing(key, value))
|
if (proc_cmdline_value_missing(key, value))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -285,7 +285,7 @@ static int determine_device(
|
|||||||
if (!*data_what) {
|
if (!*data_what) {
|
||||||
memcpy(&data_uuid, m, sizeof(data_uuid));
|
memcpy(&data_uuid, m, sizeof(data_uuid));
|
||||||
|
|
||||||
*data_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(data_uuid));
|
*data_what = path_join("/dev/disk/by-partuuid", SD_ID128_TO_UUID_STRING(data_uuid));
|
||||||
if (!*data_what)
|
if (!*data_what)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
}
|
}
|
||||||
@ -293,7 +293,7 @@ static int determine_device(
|
|||||||
if (!*hash_what) {
|
if (!*hash_what) {
|
||||||
memcpy(&verity_uuid, (uint8_t*) m + l - sizeof(verity_uuid), sizeof(verity_uuid));
|
memcpy(&verity_uuid, (uint8_t*) m + l - sizeof(verity_uuid), sizeof(verity_uuid));
|
||||||
|
|
||||||
*hash_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(verity_uuid));
|
*hash_what = path_join("/dev/disk/by-partuuid", SD_ID128_TO_UUID_STRING(verity_uuid));
|
||||||
if (!*hash_what)
|
if (!*hash_what)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1070,6 +1070,9 @@ install_compiled_systemd() {
|
|||||||
if get_bool "$IS_BUILT_WITH_COVERAGE"; then
|
if get_bool "$IS_BUILT_WITH_COVERAGE"; then
|
||||||
mkdir -p "${initdir}/${BUILD_DIR:?}/"
|
mkdir -p "${initdir}/${BUILD_DIR:?}/"
|
||||||
rsync -am --include='*/' --include='*.gcno' --exclude='*' "${BUILD_DIR:?}/" "${initdir}/${BUILD_DIR:?}/"
|
rsync -am --include='*/' --include='*.gcno' --exclude='*' "${BUILD_DIR:?}/" "${initdir}/${BUILD_DIR:?}/"
|
||||||
|
# Set effective & default ACLs for the build dir so unprivileged
|
||||||
|
# processes can write gcda files with coverage stats
|
||||||
|
setfacl -R -m 'd:o:rwX' -m 'o:rwX' "${initdir}/${BUILD_DIR:?}/"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1384,6 +1387,20 @@ check_coverage_reports() {
|
|||||||
lcov --remove "${dest}" -o "${dest}" '/usr/include/*' '/usr/lib/*'
|
lcov --remove "${dest}" -o "${dest}" '/usr/include/*' '/usr/lib/*'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# If the test logs contain lines like:
|
||||||
|
#
|
||||||
|
# ...systemd-resolved[735885]: profiling:/systemd-meson-build/src/shared/libsystemd-shared-250.a.p/base-filesystem.c.gcda:Cannot open
|
||||||
|
#
|
||||||
|
# it means we're possibly missing some coverage since gcov can't write the stats,
|
||||||
|
# usually due to the sandbox being too restrictive (e.g. ProtectSystem=yes,
|
||||||
|
# ProtectHome=yes) or the $BUILD_DIR being inaccessible to non-root users - see
|
||||||
|
# `setfacl` stuff in install_compiled_systemd().
|
||||||
|
|
||||||
|
if "${JOURNALCTL:?}" -q --no-pager -D "${root:?}/var/log/journal" --grep "profiling:.+?gcda:[Cc]annot open"; then
|
||||||
|
derror "Detected possibly missing coverage, check the journal"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user