1
0
mirror of https://github.com/systemd/systemd synced 2026-04-23 15:34:50 +02:00

Compare commits

..

No commits in common. "93efd9cadbc83d97bfff088eded925d736ea3f13" and "a321e0e4630518c547b42a1854d076a9fbe19a91" have entirely different histories.

20 changed files with 238 additions and 679 deletions

16
NEWS
View File

@ -656,13 +656,15 @@ CHANGES WITH 250:
may be used to set the boot menu time-out of the boot loader (for all
or just the subsequent boot).
* bootctl and kernel-install will now read variables
KERNEL_INSTALL_LAYOUT= from /etc/machine-info and layout= from
/etc/kernel/install.conf. When set, it specifies the layout to use
for installation directories on the boot partition, so that tools
don't need to guess it based on the already-existing directories. The
only value that is defined natively is "bls", corresponding to the
layout specified in
* bootctl and kernel-install will now read KERNEL_INSTALL_MACHINE_ID
and KERNEL_INSTALL_LAYOUT from kernel/install.conf. The first
variable specifies the machine-id to use for installation. It would
previously be used if set in the environment, and now it'll also be
read automatically from the config file. The second variable is new.
When set, it specifies the layout to use for installation directories
on the boot partition, so that tools don't need to guess it based on
the already-existing directories. The only value that is defined
natively is "bls", corresponding to the layout specified in
https://systemd.io/BOOT_LOADER_SPECIFICATION/. Plugins for
kernel-install that implement a different layout can declare other
values for this variable.

View File

@ -309,18 +309,6 @@ focus for this specification. More specifically, on non-EFI systems
configuration snippets following this specification cannot be used to spawn
other operating systems (such as Windows).
Unfortunately, there are implementations of boot loading infrastructure that
are also using the /loader/entries/ directory, but place files in them that are
not valid by this specification. In order to minimize confusion a boot loader
implementation may place a file /loader/entries.srel next to the
/loader/entries/ directory containing the ASCII string "type1" (suffixed
with a UNIX newline). Tools that need to determine whether an existing
directory implements the semantics described here may check for this file and
contents: if it exists and contains the mentioned string, it shall assume a
standards compliant implementation is in place. If it exists but contains a
different string it shall assume non-standard semantics are implemented. If the
file does not exist no assumptions should be made.
### Type #2 EFI Unified Kernel Images
A unified kernel image is a single EFI PE executable combining an EFI stub

View File

@ -237,8 +237,9 @@
</variablelist>
<para><varname>$KERNEL_INSTALL_INITRD_GENERATOR</varname> is set for plugins to select the initrd
generator. This may be configured as <varname>initrd_generator=</varname> in
<filename>install.conf</filename>. See below.</para>
generator. This should be configured as <varname>initrd_generator=</varname> in
<filename>install.conf</filename>.
</para>
<para><varname>$KERNEL_INSTALL_STAGING_AREA</varname> is set for plugins to a path to a directory.
Plugins may drop files in that directory, and they will be installed as part of the loader entry, based
@ -324,10 +325,10 @@
<filename>/etc/kernel/install.conf</filename>
</term>
<listitem>
<para>Configuration options for <command>kernel-install</command>, as a series of
<varname>KEY=</varname><replaceable>VALUE</replaceable> assignments, compatible with shell
syntax. This currently supports two keys: <varname>layout=</varname> and
<varname>initrd_generator=</varname>, for details see the Environment variables section above.</para>
<para>Configuration options for <command>kernel-install</command>,
as a series of <varname>KEY=</varname><replaceable>VALUE</replaceable> assignments,
compatible with shell syntax.
See the Environment variables section for supported keys.</para>
</listitem>
</varlistentry>
</variablelist>

View File

@ -23,7 +23,6 @@
<refsynopsisdiv>
<para><filename><replaceable>ESP</replaceable>/loader/loader.conf</filename>,
<filename><replaceable>ESP</replaceable>/loader/entries/*.conf</filename>
<filename><replaceable>XBOOTLDR</replaceable>/loader/entries/*.conf</filename>
</para>
</refsynopsisdiv>
@ -34,16 +33,13 @@
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> will
read <filename><replaceable>ESP</replaceable>/loader/loader.conf</filename>, and any files with the
<literal>.conf</literal> extension under
<filename><replaceable>ESP</replaceable>/loader/entries/</filename> on the EFI system partition (ESP),
and <filename><replaceable>XBOOTLDR</replaceable>/loader/entries/</filename> on the extended boot loader
partition (XBOOTLDR) as defined by <ulink url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader
Specification</ulink>.
<filename><replaceable>ESP</replaceable>/loader/entries/</filename> on the EFI system partition (ESP) as
defined by <ulink url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink>.
</para>
<para>Each of these configuration files must consist of series of newline (i.e. ASCII code 10) separated
lines, each consisting of an option name, followed by whitespace, and the option
value. <literal>#</literal> may be used to start a comment line. Empty and comment lines are ignored. The
files use UTF-8 encoding.</para>
<para>Each configuration file must consist of an option name, followed by
whitespace, and the option value. <literal>#</literal> may be used to start
a comment line. Empty and comment lines are ignored.</para>
<para>Boolean arguments may be written as
<literal>yes</literal>/<literal>y</literal>/<literal>true</literal>/<literal>t</literal>/<literal>on</literal>/<literal>1</literal> or
@ -54,14 +50,7 @@
<refsect1>
<title>Options</title>
<para>The configuration options supported by
<filename><replaceable>ESP</replaceable>/loader/entries/*.conf</filename> and
<filename><replaceable>XBOOTLDR</replaceable>/loader/entries/*.conf</filename> files are defined as part
of the <ulink url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader
Specification</ulink>.</para>
<para>The following configuration are supported by the <filename>loader.conf</filename> configuration
file:</para>
<para>The following configuration options in <filename>loader.conf</filename> are understood:</para>
<variablelist>
<varlistentry>

View File

@ -971,7 +971,7 @@ manpages = [
['systemd-stdio-bridge', '1', [], ''],
['systemd-stub',
'7',
['linuxaa64.efi.stub', 'linuxia32.efi.stub', 'linuxx64.efi.stub', 'sd-stub'],
['linuxaa64.efi.stub', 'linuxia32.efi.stub', 'linuxx64.efi.stub'],
'HAVE_GNU_EFI'],
['systemd-suspend.service',
'8',

View File

@ -30,12 +30,12 @@
<para><command>systemd-boot</command> loads boot entry information from the EFI system partition (ESP),
usually mounted at <filename>/efi/</filename>, <filename>/boot/</filename>, or
<filename>/boot/efi/</filename> during OS runtime, as well as from the Extended Boot Loader partition
(XBOOTLDR) if it exists (usually mounted to <filename>/boot/</filename>). Configuration file fragments,
kernels, initrds and other EFI images to boot generally need to reside on the ESP or the Extended Boot
Loader partition. Linux kernels must be built with <option>CONFIG_EFI_STUB</option> to be able to be
directly executed as an EFI image. During boot <command>systemd-boot</command> automatically assembles a
list of boot entries from the following sources:</para>
<filename>/boot/efi/</filename> during OS runtime, as well as from the Extended Boot Loader partition if
it exists (usually mounted to <filename>/boot/</filename>). Configuration file fragments, kernels,
initrds and other EFI images to boot generally need to reside on the ESP or the Extended Boot Loader
partition. Linux kernels must be built with <option>CONFIG_EFI_STUB</option> to be able to be directly
executed as an EFI image. During boot <command>systemd-boot</command> automatically assembles a list of
boot entries from the following sources:</para>
<itemizedlist>
<listitem><para>Boot entries defined with <ulink

View File

@ -17,7 +17,6 @@
<refnamediv>
<refname>systemd-stub</refname>
<refname>sd-stub</refname>
<refname>linuxx64.efi.stub</refname>
<refname>linuxia32.efi.stub</refname>
<refname>linuxaa64.efi.stub</refname>

View File

@ -280,9 +280,9 @@
<term><option>-t</option></term>
<term><option>--type=<replaceable>TYPE</replaceable></option></term>
<listitem>
<para>Trigger a specific type of devices. Valid types are <literal>all</literal>,
<literal>devices</literal>, and <literal>subsystems</literal>. The default value is
<literal>devices</literal>.</para>
<para>Trigger a specific type of devices. Valid types are:
<command>devices</command>, <command>subsystems</command>.
The default value is <command>devices</command>.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -297,19 +297,6 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--prioritized-subsystem=<replaceable>SUBSYSTEM<optional>,<replaceable>SUBSYSTEM</replaceable></optional></replaceable></option></term>
<listitem>
<para>Takes a comma separated list of subsystems. When triggering events for devices, the
devices from the specified subsystems and their parents are triggered first. For example,
if <option>--prioritized-subsystem=block,net</option>, then firstly all block devices and
their parents are triggered, in the next all network devices and their parents are
triggered, and lastly the other devices are triggered. This option can be specified
multiple times, and in that case the lists of the subsystems will be merged. That is,
<option>--prioritized-subsystem=block --prioritized-subsystem=net</option> is equivalent to
<option>--prioritized-subsystem=block,net</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-s</option></term>
<term><option>--subsystem-match=<replaceable>SUBSYSTEM</replaceable></option></term>
@ -395,35 +382,6 @@
then each matching result is ORed, that is, all children of each specified device are triggered.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--initialized-match</option></term>
<term><option>--initialized-nomatch</option></term>
<listitem>
<para>When <option>--initialized-match</option> is specified, trigger events for devices
that are already initialized by <command>systemd-udevd</command>, and skip devices that
are not initialized yet.</para>
<para>When <option>--initialized-nomatch</option> is specified, trigger events for devices
that are not initialized by <command>systemd-udevd</command> yet, and skip devices that
are already initialized.</para>
<para>Here, initialized devices are those for which at least one udev rule already
completed execution for any action but <literal>remove</literal> — that set a property
or other device setting (and thus has an entry in the udev device database). Devices are
no longer considered initialized if a <literal>remove</literal> action is seen for them
(which removes their entry in the udev device database). Note that devices that have no
udev rules are never considered initialized, but might still be announced via the sd-device
API (or similar). Typically, it is thus essential that applications which intend to use
such a match, make sure a suitable udev rule is installed that sets at least one property
on devices that shall be matched.</para>
<para>WARNING: <option>--initialized-nomatch</option> can potentially save a significant
amount of time compared to re-triggering all devices in the system and e.g. can be used to
optimize boot time. However, this is not safe to be used in a boot sequence in general.
Especially, when udev rules for a device depend on its parent devices (e.g.
<literal>ATTRS</literal> or <literal>IMPORT{parent}</literal> keys, see
<citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for more details), the final state of the device becomes easily unstable with this option.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-w</option></term>
<term><option>--settle</option></term>

View File

@ -51,12 +51,10 @@ _udevadm() {
[INFO_STANDALONE]='-r --root -a --attribute-walk -x --export -e --export-db -c --cleanup-db
-w --wait-for-initialization --value'
[INFO_ARG]='-q --query -p --path -n --name -P --export-prefix -d --device-id-of-file --property'
[TRIGGER_STANDALONE]='-v --verbose -n --dry-run -q --quiet -w --settle --wait-daemon --uuid
--initialized-match --initialized-nomatch'
[TRIGGER_STANDALONE]='-v --verbose -n --dry-run -q --quiet -w --settle --wait-daemon --uuid'
[TRIGGER_ARG]='-t --type -c --action -s --subsystem-match -S --subsystem-nomatch
-a --attr-match -A --attr-nomatch -p --property-match
-g --tag-match -y --sysname-match --name-match -b --parent-match
--prioritized-subsystem'
-g --tag-match -y --sysname-match --name-match -b --parent-match'
[SETTLE]='-t --timeout -E --exit-if-exists'
[CONTROL_STANDALONE]='-e --exit -s --stop-exec-queue -S --start-exec-queue -R --reload --ping'
[CONTROL_ARG]='-l --log-priority -p --property -m --children-max -t --timeout'
@ -119,7 +117,7 @@ _udevadm() {
if __contains_word "$prev" ${OPTS[TRIGGER_ARG]}; then
case $prev in
-t|--type)
comps='all devices subsystems'
comps='devices subsystems'
;;
-c|--action)
comps=$( udevadm trigger --action help )

View File

@ -24,7 +24,7 @@ _udevadm_trigger(){
'--verbose[Print the list of devices which will be triggered.]' \
'--dry-run[Do not actually trigger the event.]' \
'--quiet[Suppress error logging in triggering events.]' \
'--type=[Trigger a specific type of devices.]:types:(all devices subsystems failed)' \
'--type=[Trigger a specific type of devices.]:types:(devices subsystems failed)' \
'--action=[Type of event to be triggered.]:actions:(add change remove move online offline bind unbind)' \
'--subsystem-match=[Trigger events for devices which belong to a matching subsystem.]' \
'--subsystem-nomatch=[Do not trigger events for devices which belong to a matching subsystem.]' \
@ -34,10 +34,7 @@ _udevadm_trigger(){
'--tag-match=property[Trigger events for devices with a matching tag.]' \
'--sysname-match=[Trigger events for devices with a matching sys device name.]' \
'--parent-match=[Trigger events for all children of a given device.]' \
'--initialized-match[Trigger events for devices that are already initialized.]' \
'--initialized-nomatch[Trigger events for devices that are not initialized yet.]' \
'--uuid[Print synthetic uevent UUID.]' \
'--prioritized-subsystem=[Trigger events for devices which belong to a matching subsystem earlier.]'
'--uuid[Print synthetic uevent UUID.]'
}
(( $+functions[_udevadm_settle] )) ||

View File

@ -28,7 +28,7 @@ static inline uint32_t random_u32(void) {
}
/* Some limits on the pool sizes when we deal with the kernel random pool */
#define RANDOM_POOL_SIZE_MIN 32U
#define RANDOM_POOL_SIZE_MIN 512U
#define RANDOM_POOL_SIZE_MAX (10U*1024U*1024U)
size_t random_pool_size(void);

View File

@ -275,28 +275,6 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
return fd;
}
int fopen_tmpfile_linkable(const char *target, int flags, char **ret_path, FILE **ret_file) {
_cleanup_free_ char *path = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_close_ int fd = -1;
assert(target);
assert(ret_file);
assert(ret_path);
fd = open_tmpfile_linkable(target, flags, &path);
if (fd < 0)
return fd;
f = take_fdopen(&fd, "w");
if (!f)
return -ENOMEM;
*ret_path = TAKE_PTR(path);
*ret_file = TAKE_PTR(f);
return 0;
}
int link_tmpfile(int fd, const char *path, const char *target) {
assert(fd >= 0);
assert(target);
@ -314,23 +292,6 @@ int link_tmpfile(int fd, const char *path, const char *target) {
return RET_NERRNO(linkat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), AT_FDCWD, target, AT_SYMLINK_FOLLOW));
}
int flink_tmpfile(FILE *f, const char *path, const char *target) {
int fd, r;
assert(f);
assert(target);
fd = fileno(f);
if (fd < 0) /* Not all FILE* objects encapsulate fds */
return -EBADF;
r = fflush_sync_and_check(f);
if (r < 0)
return r;
return link_tmpfile(fd, path, target);
}
int mkdtemp_malloc(const char *template, char **ret) {
_cleanup_free_ char *p = NULL;
int r;

View File

@ -13,9 +13,7 @@ int tempfn_random_child(const char *p, const char *extra, char **ret);
int open_tmpfile_unlinkable(const char *directory, int flags);
int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
int fopen_tmpfile_linkable(const char *target, int flags, char **ret_path, FILE **ret_file);
int link_tmpfile(int fd, const char *path, const char *target);
int flink_tmpfile(FILE *f, const char *path, const char *target);
int mkdtemp_malloc(const char *template, char **ret);

View File

@ -144,70 +144,38 @@ static int acquire_xbootldr(
return 1;
}
static int load_etc_machine_id(void) {
int r;
r = sd_id128_get_machine(&arg_machine_id);
if (IN_SET(r, -ENOENT, -ENOMEDIUM)) /* Not set or empty */
return 0;
if (r < 0)
return log_error_errno(r, "Failed to get machine-id: %m");
log_debug("Loaded machine ID %s from /etc/machine-id.", SD_ID128_TO_STRING(arg_machine_id));
return 0;
}
static int load_etc_machine_info(void) {
/* systemd v250 added support to store the kernel-install layout setting and the machine ID to use
* for setting up the ESP in /etc/machine-info. The newer /etc/kernel/entry-token file, as well as
* the $layout field in /etc/kernel/install.conf are better replacements for this though, hence this
* has been deprecated and is only returned for compatibility. */
static int load_install_machine_id_and_layout(void) {
/* Figure out the right machine-id for operations. If KERNEL_INSTALL_MACHINE_ID is configured in
* /etc/machine-info, let's use that. Otherwise, just use the real machine-id.
*
* Also load KERNEL_INSTALL_LAYOUT.
*/
_cleanup_free_ char *s = NULL, *layout = NULL;
int r;
r = parse_env_file(NULL, "/etc/machine-info",
"KERNEL_INSTALL_LAYOUT", &layout,
"KERNEL_INSTALL_MACHINE_ID", &s);
if (r == -ENOENT)
return 0;
if (r < 0)
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to parse /etc/machine-info: %m");
if (!isempty(s)) {
log_notice("Read $KERNEL_INSTALL_MACHINE_ID from /etc/machine-info. Please move it to /etc/kernel/entry-token.");
if (isempty(s)) {
r = sd_id128_get_machine(&arg_machine_id);
if (r < 0 && !IN_SET(r, -ENOENT, -ENOMEDIUM))
return log_error_errno(r, "Failed to get machine-id: %m");
} else {
r = sd_id128_from_string(s, &arg_machine_id);
if (r < 0)
return log_error_errno(r, "Failed to parse KERNEL_INSTALL_MACHINE_ID=%s in /etc/machine-info: %m", s);
log_debug("Loaded KERNEL_INSTALL_MACHINE_ID=%s from KERNEL_INSTALL_MACHINE_ID in /etc/machine-info.",
SD_ID128_TO_STRING(arg_machine_id));
}
log_debug("Using KERNEL_INSTALL_MACHINE_ID=%s from %s.",
SD_ID128_TO_STRING(arg_machine_id),
isempty(s) ? "/etc/machine_id" : "KERNEL_INSTALL_MACHINE_ID in /etc/machine-info");
if (!isempty(layout)) {
log_notice("Read $KERNEL_INSTALL_LAYOUT from /etc/machine-info. Please move it to the layout= setting of /etc/kernel/install.conf.");
log_debug("KERNEL_INSTALL_LAYOUT=%s is specified in /etc/machine-info.", layout);
free_and_replace(arg_install_layout, layout);
}
return 0;
}
static int load_etc_kernel_install_conf(void) {
_cleanup_free_ char *layout = NULL;
int r;
r = parse_env_file(NULL, "/etc/kernel/install.conf",
"layout", &layout);
if (r == -ENOENT)
return 0;
if (r < 0)
return log_error_errno(r, "Failed to parse /etc/kernel/install.conf: %m");
if (!isempty(layout)) {
log_debug("layout=%s is specified in /etc/machine-info.", layout);
free_and_replace(arg_install_layout, layout);
arg_install_layout = TAKE_PTR(layout);
}
return 0;
@ -314,15 +282,7 @@ static bool use_boot_loader_spec_type1(void) {
static int settle_make_entry_directory(void) {
int r;
r = load_etc_machine_id();
if (r < 0)
return r;
r = load_etc_machine_info();
if (r < 0)
return r;
r = load_etc_kernel_install_conf();
r = load_install_machine_id_and_layout();
if (r < 0)
return r;
@ -1286,6 +1246,7 @@ static int remove_loader_variables(void) {
static int install_loader_config(const char *esp_path) {
_cleanup_(unlink_and_freep) char *t = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_close_ int fd = -1;
const char *p;
int r;
@ -1295,9 +1256,13 @@ static int install_loader_config(const char *esp_path) {
if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */
return 0;
r = fopen_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t, &f);
if (r < 0)
return log_error_errno(r, "Failed to open \"%s\" for writing: %m", p);
fd = open_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t);
if (fd < 0)
return log_error_errno(fd, "Failed to open \"%s\" for writing: %m", p);
f = take_fdopen(&fd, "w");
if (!f)
return log_oom();
fprintf(f, "#timeout 3\n"
"#console-mode keep\n");
@ -1307,36 +1272,11 @@ static int install_loader_config(const char *esp_path) {
fprintf(f, "default %s-*\n", arg_entry_token);
}
r = flink_tmpfile(f, t, p);
if (r == -EEXIST)
return 0; /* Silently skip creation if the file exists now (recheck) */
r = fflush_sync_and_check(f);
if (r < 0)
return log_error_errno(r, "Failed to move \"%s\" into place: %m", p);
return log_error_errno(r, "Failed to write \"%s\": %m", p);
t = mfree(t);
return 1;
}
static int install_loader_specification(const char *root) {
_cleanup_(unlink_and_freep) char *t = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
int r;
p = path_join(root, "/loader/entries.srel");
if (!p)
return log_oom();
if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */
return 0;
r = fopen_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t, &f);
if (r < 0)
return log_error_errno(r, "Failed to open \"%s\" for writing: %m", p);
fprintf(f, "type1\n");
r = flink_tmpfile(f, t, p);
r = link_tmpfile(fileno(f), t, p);
if (r == -EEXIST)
return 0; /* Silently skip creation if the file exists now (recheck) */
if (r < 0)
@ -2058,10 +1998,6 @@ static int verb_install(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
}
r = install_loader_specification(arg_dollar_boot_path());
if (r < 0)
return r;
}
(void) sync_everything();
@ -2101,10 +2037,6 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
if (q < 0 && r >= 0)
r = q;
q = remove_file(arg_esp_path, "/loader/entries.srel");
if (q < 0 && r >= 0)
r = q;
q = remove_subdirs(arg_esp_path, esp_subdirs);
if (q < 0 && r >= 0)
r = q;
@ -2118,12 +2050,7 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
r = q;
if (arg_xbootldr_path) {
/* Remove a subset of these also from the XBOOTLDR partition if it exists */
q = remove_file(arg_xbootldr_path, "/loader/entries.srel");
if (q < 0 && r >= 0)
r = q;
/* Remove the latter two also in the XBOOTLDR partition if it exists */
q = remove_subdirs(arg_xbootldr_path, dollar_boot_subdirs);
if (q < 0 && r >= 0)
r = q;

View File

@ -155,29 +155,10 @@ done
[ -z "$ENTRY_TOKEN" ] && ENTRY_TOKEN="$MACHINE_ID"
if [ -z "$layout" ]; then
# No layout configured by the administrator. Let's try to figure it out
# automatically from metadata already contained in $BOOT_ROOT.
if [ -e "$BOOT_ROOT/loader/entries.srel" ]; then
read -r ENTRIES_SREL <"$BOOT_ROOT/loader/entries.srel"
if [ "$ENTRIES_SREL" = "type1" ]; then
# The loader/entries.srel file clearly indicates that the installed
# boot loader implements the proper standard upstream boot loader
# spec for Type #1 entries. Let's default to that, then.
# Administrative decision: if not present, some scripts generate into /boot.
if [ -d "$BOOT_ROOT/$ENTRY_TOKEN" ]; then
layout="bls"
else
# The loader/entries.srel file indicates some other spec is
# implemented and owns the /loader/entries/ directory. Since we
# have no idea what that means, let's stay away from it by default.
layout="other"
fi
elif [ -d "$BOOT_ROOT/$ENTRY_TOKEN" ]; then
# If the metadata in $BOOT_ROOT doesn't tell us anything, then check if
# the entry token directory already exists. If so, let's assume it's
# the standard boot loader spec, too.
layout="bls"
else
# There's no metadata in $BOOT_ROOT, and apparently no entry token
# directory installed? Then we really don't know anything.
layout="other"
fi
fi

View File

@ -3,22 +3,11 @@
#include "sd-device.h"
typedef enum MatchInitializedType {
MATCH_INITIALIZED_NO, /* only devices without a db entry */
MATCH_INITIALIZED_YES, /* only devices with a db entry */
MATCH_INITIALIZED_ALL, /* all devices */
MATCH_INITIALIZED_COMPAT, /* only devices that have no devnode/ifindex or have a db entry */
_MATCH_INITIALIZED_MAX,
_MATCH_INITIALIZED_INVALID = -EINVAL,
} MatchInitializedType;
int device_enumerator_scan_devices(sd_device_enumerator *enumeartor);
int device_enumerator_scan_subsystems(sd_device_enumerator *enumeartor);
int device_enumerator_scan_devices_and_subsystems(sd_device_enumerator *enumerator);
int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device);
int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator, MatchInitializedType type);
int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator);
int device_enumerator_add_match_parent_incremental(sd_device_enumerator *enumerator, sd_device *parent);
int device_enumerator_add_prioritized_subsystem(sd_device_enumerator *enumerator, const char *subsystem);
sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator);
sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator);
sd_device **device_enumerator_get_devices(sd_device_enumerator *enumerator, size_t *ret_n_devices);

View File

@ -20,7 +20,6 @@
typedef enum DeviceEnumerationType {
DEVICE_ENUMERATION_TYPE_DEVICES,
DEVICE_ENUMERATION_TYPE_SUBSYSTEMS,
DEVICE_ENUMERATION_TYPE_ALL,
_DEVICE_ENUMERATION_TYPE_MAX,
_DEVICE_ENUMERATION_TYPE_INVALID = -EINVAL,
} DeviceEnumerationType;
@ -29,13 +28,10 @@ struct sd_device_enumerator {
unsigned n_ref;
DeviceEnumerationType type;
Hashmap *devices_by_syspath;
sd_device **devices;
size_t n_devices, current_device_index;
bool scan_uptodate;
bool sorted;
char **prioritized_subsystems;
Set *match_subsystem;
Set *nomatch_subsystem;
Hashmap *match_sysattr;
@ -44,7 +40,7 @@ struct sd_device_enumerator {
Set *match_sysname;
Set *match_tag;
Set *match_parent;
MatchInitializedType match_initialized;
bool match_allow_uninitialized;
};
_public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
@ -59,7 +55,6 @@ _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
*enumerator = (sd_device_enumerator) {
.n_ref = 1,
.type = _DEVICE_ENUMERATION_TYPE_INVALID,
.match_initialized = MATCH_INITIALIZED_COMPAT,
};
*ret = TAKE_PTR(enumerator);
@ -67,29 +62,13 @@ _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
return 0;
}
static void device_unref_many(sd_device **devices, size_t n) {
assert(devices || n == 0);
for (size_t i = 0; i < n; i++)
sd_device_unref(devices[i]);
}
static void device_enumerator_unref_devices(sd_device_enumerator *enumerator) {
assert(enumerator);
hashmap_clear_with_destructor(enumerator->devices_by_syspath, sd_device_unref);
device_unref_many(enumerator->devices, enumerator->n_devices);
enumerator->devices = mfree(enumerator->devices);
enumerator->n_devices = 0;
}
static sd_device_enumerator *device_enumerator_free(sd_device_enumerator *enumerator) {
assert(enumerator);
device_enumerator_unref_devices(enumerator);
for (size_t i = 0; i < enumerator->n_devices; i++)
sd_device_unref(enumerator->devices[i]);
hashmap_free(enumerator->devices_by_syspath);
strv_free(enumerator->prioritized_subsystems);
free(enumerator->devices);
set_free(enumerator->match_subsystem);
set_free(enumerator->nomatch_subsystem);
hashmap_free(enumerator->match_sysattr);
@ -104,24 +83,6 @@ static sd_device_enumerator *device_enumerator_free(sd_device_enumerator *enumer
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_enumerator, sd_device_enumerator, device_enumerator_free);
int device_enumerator_add_prioritized_subsystem(sd_device_enumerator *enumerator, const char *subsystem) {
int r;
assert(enumerator);
assert(subsystem);
if (strv_contains(enumerator->prioritized_subsystems, subsystem))
return 0;
r = strv_extend(&enumerator->prioritized_subsystems, subsystem);
if (r < 0)
return r;
enumerator->scan_uptodate = false;
return 1;
}
_public_ int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match) {
Set **set;
int r;
@ -245,214 +206,82 @@ _public_ int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumera
_public_ int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator) {
assert_return(enumerator, -EINVAL);
enumerator->match_initialized = MATCH_INITIALIZED_ALL;
enumerator->match_allow_uninitialized = true;
enumerator->scan_uptodate = false;
return 1;
}
int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator, MatchInitializedType type) {
int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator) {
assert_return(enumerator, -EINVAL);
assert_return(type >= 0 && type < _MATCH_INITIALIZED_MAX, -EINVAL);
enumerator->match_initialized = type;
enumerator->match_allow_uninitialized = false;
enumerator->scan_uptodate = false;
return 1;
}
static int sound_device_compare(const char *devpath_a, const char *devpath_b) {
const char *sound_a, *sound_b;
size_t prefix_len;
static int device_compare(sd_device * const *_a, sd_device * const *_b) {
sd_device *a = *(sd_device **)_a, *b = *(sd_device **)_b;
const char *devpath_a, *devpath_b, *sound_a;
bool delay_a, delay_b;
int r;
assert(devpath_a);
assert(devpath_b);
/* For sound cards the control device must be enumerated last to make sure it's the final
* device node that gets ACLs applied. Applications rely on this fact and use ACL changes on
* the control node as an indicator that the ACL change of the entire sound card completed. The
* kernel makes this guarantee when creating those devices, and hence we should too when
* enumerating them. */
assert_se(sd_device_get_devpath(a, &devpath_a) >= 0);
assert_se(sd_device_get_devpath(b, &devpath_b) >= 0);
sound_a = strstr(devpath_a, "/sound/card");
if (!sound_a)
return 0;
if (sound_a) {
/* For sound cards the control device must be enumerated last to
* make sure it's the final device node that gets ACLs applied.
* Applications rely on this fact and use ACL changes on the
* control node as an indicator that the ACL change of the
* entire sound card completed. The kernel makes this guarantee
* when creating those devices, and hence we should too when
* enumerating them. */
sound_a += STRLEN("/sound/card");
sound_a = strchr(devpath_a, '/');
if (!sound_a)
return 0;
sound_a = strchr(sound_a, '/');
if (sound_a) {
unsigned prefix_len;
prefix_len = sound_a - devpath_a;
if (!strneq(devpath_a, devpath_b, prefix_len))
return 0;
if (strneq(devpath_a, devpath_b, prefix_len)) {
const char *sound_b;
sound_b = devpath_b + prefix_len;
return CMP(!!startswith(sound_a, "/controlC"),
r = CMP(!!startswith(sound_a, "/controlC"),
!!startswith(sound_b, "/controlC"));
}
static bool devpath_is_late_block(const char *devpath) {
assert(devpath);
return strstr(devpath, "/block/md") || strstr(devpath, "/block/dm-");
}
static int device_compare(sd_device * const *a, sd_device * const *b) {
const char *devpath_a, *devpath_b;
int r;
assert(a);
assert(b);
assert(*a);
assert(*b);
assert_se(sd_device_get_devpath(*(sd_device**) a, &devpath_a) >= 0);
assert_se(sd_device_get_devpath(*(sd_device**) b, &devpath_b) >= 0);
r = sound_device_compare(devpath_a, devpath_b);
if (r != 0)
return r;
}
}
}
/* md and dm devices are enumerated after all other devices */
r = CMP(devpath_is_late_block(devpath_a), devpath_is_late_block(devpath_b));
delay_a = strstr(devpath_a, "/block/md") || strstr(devpath_a, "/block/dm-");
delay_b = strstr(devpath_b, "/block/md") || strstr(devpath_b, "/block/dm-");
r = CMP(delay_a, delay_b);
if (r != 0)
return r;
return strcmp(devpath_a, devpath_b);
}
static int enumerator_sort_devices(sd_device_enumerator *enumerator) {
size_t n_sorted = 0, n = 0;
sd_device **devices;
sd_device *device;
int r;
assert(enumerator);
if (enumerator->sorted)
return 0;
devices = new(sd_device*, hashmap_size(enumerator->devices_by_syspath));
if (!devices)
return -ENOMEM;
STRV_FOREACH(prioritized_subsystem, enumerator->prioritized_subsystems) {
for (;;) {
const char *syspath;
size_t m = n;
HASHMAP_FOREACH_KEY(device, syspath, enumerator->devices_by_syspath) {
_cleanup_free_ char *p = NULL;
const char *subsys;
if (sd_device_get_subsystem(device, &subsys) < 0)
continue;
if (!streq(subsys, *prioritized_subsystem))
continue;
devices[n++] = sd_device_ref(device);
for (;;) {
_cleanup_free_ char *q = NULL;
r = path_extract_directory(p ?: syspath, &q);
if (r == -EADDRNOTAVAIL)
break;
if (r < 0)
goto failed;
device = hashmap_get(enumerator->devices_by_syspath, q);
if (device)
devices[n++] = sd_device_ref(device);
free_and_replace(p, q);
}
break;
}
/* We cannot remove multiple entries in the loop HASHMAP_FOREACH_KEY() above. */
for (size_t i = m; i < n; i++) {
r = sd_device_get_syspath(devices[i], &syspath);
if (r < 0)
goto failed;
assert_se(hashmap_remove(enumerator->devices_by_syspath, syspath) == devices[i]);
sd_device_unref(devices[i]);
}
if (m == n)
break;
}
typesafe_qsort(devices + n_sorted, n - n_sorted, device_compare);
n_sorted = n;
}
HASHMAP_FOREACH(device, enumerator->devices_by_syspath)
devices[n++] = sd_device_ref(device);
/* Move all devices back to the hashmap. Otherwise, devices added by
* udev_enumerate_add_syspath() -> device_enumerator_add_device() may not be listed. */
for (size_t i = 0; i < n_sorted; i++) {
const char *syspath;
r = sd_device_get_syspath(devices[i], &syspath);
if (r < 0)
goto failed;
r = hashmap_put(enumerator->devices_by_syspath, syspath, devices[i]);
if (r < 0)
goto failed;
assert(r > 0);
sd_device_ref(devices[i]);
}
typesafe_qsort(devices + n_sorted, n - n_sorted, device_compare);
device_unref_many(enumerator->devices, enumerator->n_devices);
enumerator->n_devices = n;
free_and_replace(enumerator->devices, devices);
enumerator->sorted = true;
return 0;
failed:
device_unref_many(devices, n);
free(devices);
return r;
}
int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) {
const char *syspath;
int r;
assert_return(enumerator, -EINVAL);
assert_return(device, -EINVAL);
r = sd_device_get_syspath(device, &syspath);
if (r < 0)
return r;
if (!GREEDY_REALLOC(enumerator->devices, enumerator->n_devices + 1))
return -ENOMEM;
enumerator->devices[enumerator->n_devices++] = sd_device_ref(device);
r = hashmap_ensure_put(&enumerator->devices_by_syspath, &string_hash_ops, syspath, device);
if (IN_SET(r, -EEXIST, 0))
return 0;
if (r < 0)
return r;
sd_device_ref(device);
enumerator->sorted = false;
return 1;
}
static bool match_property(sd_device_enumerator *enumerator, sd_device *device) {
@ -515,42 +344,10 @@ static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname)
return false;
}
static int match_initialized(sd_device_enumerator *enumerator, sd_device *device) {
int r;
assert(enumerator);
assert(device);
if (enumerator->match_initialized == MATCH_INITIALIZED_ALL)
return true;
r = sd_device_get_is_initialized(device);
if (r == -ENOENT) /* this is necessarily racey, so ignore missing devices */
return false;
if (r < 0)
return r;
if (enumerator->match_initialized == MATCH_INITIALIZED_COMPAT) {
/* only devices that have no devnode/ifindex or have a db entry are accepted. */
if (r > 0)
return true;
if (sd_device_get_devnum(device, NULL) >= 0)
return true;
if (sd_device_get_ifindex(device, NULL) >= 0)
return true;
return false;
}
return (enumerator->match_initialized == MATCH_INITIALIZED_NO) == (r == 0);
}
static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, const char *basedir, const char *subdir1, const char *subdir2) {
_cleanup_closedir_ DIR *dir = NULL;
char *path;
int k, r = 0;
int r = 0;
assert(enumerator);
assert(basedir);
@ -571,6 +368,7 @@ static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator,
FOREACH_DIRENT_ALL(de, dir, return -errno) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
char syspath[strlen(path) + 1 + strlen(de->d_name) + 1];
int initialized, k;
if (de->d_name[0] == '.')
continue;
@ -589,13 +387,31 @@ static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator,
continue;
}
k = match_initialized(enumerator, device);
if (k <= 0) {
if (k < 0)
r = k;
initialized = sd_device_get_is_initialized(device);
if (initialized < 0) {
if (initialized != -ENOENT)
/* this is necessarily racey, so ignore missing devices */
r = initialized;
continue;
}
/*
* All devices with a device node or network interfaces
* possibly need udev to adjust the device node permission
* or context, or rename the interface before it can be
* reliably used from other processes.
*
* For now, we can only check these types of devices, we
* might not store a database, and have no way to find out
* for all other types of devices.
*/
if (!enumerator->match_allow_uninitialized &&
!initialized &&
(sd_device_get_devnum(device, NULL) >= 0 ||
sd_device_get_ifindex(device, NULL) >= 0))
continue;
if (!device_match_parent(device, enumerator->match_parent, NULL))
continue;
@ -854,10 +670,18 @@ static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) {
}
static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) {
int k, r = 0;
int r = 0;
log_debug("sd-device-enumerator: Scan all dirs");
if (access("/sys/subsystem", F_OK) >= 0) {
/* we have /subsystem/, forget all the old stuff */
r = enumerator_scan_dir(enumerator, "subsystem", "devices", NULL);
if (r < 0)
return log_debug_errno(r, "sd-device-enumerator: Failed to scan /sys/subsystem: %m");
} else {
int k;
k = enumerator_scan_dir(enumerator, "bus", "devices", NULL);
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/bus: %m");
@ -865,10 +689,38 @@ static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) {
k = enumerator_scan_dir(enumerator, "class", NULL, NULL);
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/class: %m");
}
return r;
}
static void device_enumerator_dedup_devices(sd_device_enumerator *enumerator) {
sd_device **a, **b, **end;
assert(enumerator);
if (enumerator->n_devices <= 1)
return;
a = enumerator->devices + 1;
b = enumerator->devices;
end = enumerator->devices + enumerator->n_devices;
for (; a < end; a++) {
const char *devpath_a, *devpath_b;
assert_se(sd_device_get_devpath(*a, &devpath_a) >= 0);
assert_se(sd_device_get_devpath(*b, &devpath_b) >= 0);
if (path_equal(devpath_a, devpath_b))
sd_device_unref(*a);
else
*(++b) = *a;
}
enumerator->n_devices = b - enumerator->devices + 1;
}
int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
int r = 0, k;
@ -878,7 +730,10 @@ int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES)
return 0;
device_enumerator_unref_devices(enumerator);
for (size_t i = 0; i < enumerator->n_devices; i++)
sd_device_unref(enumerator->devices[i]);
enumerator->n_devices = 0;
if (!set_isempty(enumerator->match_tag)) {
k = enumerator_scan_devices_tags(enumerator);
@ -894,6 +749,9 @@ int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
r = k;
}
typesafe_qsort(enumerator->devices, enumerator->n_devices, device_compare);
device_enumerator_dedup_devices(enumerator);
enumerator->scan_uptodate = true;
enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES;
@ -901,12 +759,12 @@ int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
}
_public_ sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator) {
int r;
assert_return(enumerator, NULL);
if (device_enumerator_scan_devices(enumerator) < 0)
return NULL;
if (enumerator_sort_devices(enumerator) < 0)
r = device_enumerator_scan_devices(enumerator);
if (r < 0)
return NULL;
enumerator->current_device_index = 0;
@ -921,7 +779,6 @@ _public_ sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *e
assert_return(enumerator, NULL);
if (!enumerator->scan_uptodate ||
!enumerator->sorted ||
enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES ||
enumerator->current_device_index + 1 >= enumerator->n_devices)
return NULL;
@ -930,6 +787,7 @@ _public_ sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *e
}
int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
const char *subsysdir;
int r = 0, k;
assert(enumerator);
@ -938,7 +796,10 @@ int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
return 0;
device_enumerator_unref_devices(enumerator);
for (size_t i = 0; i < enumerator->n_devices; i++)
sd_device_unref(enumerator->devices[i]);
enumerator->n_devices = 0;
/* modules */
if (match_subsystem(enumerator, "module")) {
@ -947,20 +808,28 @@ int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan modules: %m");
}
if (access("/sys/subsystem", F_OK) >= 0)
subsysdir = "subsystem";
else
subsysdir = "bus";
/* subsystems (only buses support coldplug) */
if (match_subsystem(enumerator, "subsystem")) {
k = enumerator_scan_dir_and_add_devices(enumerator, "bus", NULL, NULL);
k = enumerator_scan_dir_and_add_devices(enumerator, subsysdir, NULL, NULL);
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan subsystems: %m");
}
/* subsystem drivers */
if (match_subsystem(enumerator, "drivers")) {
k = enumerator_scan_dir(enumerator, "bus", "drivers", "drivers");
k = enumerator_scan_dir(enumerator, subsysdir, "drivers", "drivers");
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan drivers: %m");
}
typesafe_qsort(enumerator->devices, enumerator->n_devices, device_compare);
device_enumerator_dedup_devices(enumerator);
enumerator->scan_uptodate = true;
enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS;
@ -968,12 +837,12 @@ int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
}
_public_ sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator) {
int r;
assert_return(enumerator, NULL);
if (device_enumerator_scan_subsystems(enumerator) < 0)
return NULL;
if (enumerator_sort_devices(enumerator) < 0)
r = device_enumerator_scan_subsystems(enumerator);
if (r < 0)
return NULL;
enumerator->current_device_index = 0;
@ -988,7 +857,6 @@ _public_ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator
assert_return(enumerator, NULL);
if (!enumerator->scan_uptodate ||
!enumerator->sorted ||
enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS ||
enumerator->current_device_index + 1 >= enumerator->n_devices)
return NULL;
@ -996,67 +864,12 @@ _public_ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator
return enumerator->devices[++enumerator->current_device_index];
}
int device_enumerator_scan_devices_and_subsystems(sd_device_enumerator *enumerator) {
int r = 0, k;
assert(enumerator);
if (enumerator->scan_uptodate &&
enumerator->type == DEVICE_ENUMERATION_TYPE_ALL)
return 0;
device_enumerator_unref_devices(enumerator);
if (!set_isempty(enumerator->match_tag)) {
k = enumerator_scan_devices_tags(enumerator);
if (k < 0)
r = k;
} else if (enumerator->match_parent) {
k = enumerator_scan_devices_children(enumerator);
if (k < 0)
r = k;
} else {
k = enumerator_scan_dir(enumerator, "class", NULL, NULL);
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/class: %m");
k = enumerator_scan_dir(enumerator, "bus", "devices", NULL);
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/bus: %m");
if (match_subsystem(enumerator, "module")) {
k = enumerator_scan_dir_and_add_devices(enumerator, "module", NULL, NULL);
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan modules: %m");
}
if (match_subsystem(enumerator, "subsystem")) {
k = enumerator_scan_dir_and_add_devices(enumerator, "bus", NULL, NULL);
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan subsystems: %m");
}
if (match_subsystem(enumerator, "drivers")) {
k = enumerator_scan_dir(enumerator, "bus", "drivers", "drivers");
if (k < 0)
r = log_debug_errno(k, "sd-device-enumerator: Failed to scan drivers: %m");
}
}
enumerator->scan_uptodate = true;
enumerator->type = DEVICE_ENUMERATION_TYPE_ALL;
return r;
}
sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator) {
assert_return(enumerator, NULL);
if (!enumerator->scan_uptodate)
return NULL;
if (enumerator_sort_devices(enumerator) < 0)
return NULL;
enumerator->current_device_index = 0;
if (enumerator->n_devices == 0)
@ -1069,7 +882,6 @@ sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator) {
assert_return(enumerator, NULL);
if (!enumerator->scan_uptodate ||
!enumerator->sorted ||
enumerator->current_device_index + 1 >= enumerator->n_devices)
return NULL;
@ -1083,9 +895,6 @@ sd_device **device_enumerator_get_devices(sd_device_enumerator *enumerator, size
if (!enumerator->scan_uptodate)
return NULL;
if (enumerator_sort_devices(enumerator) < 0)
return NULL;
*ret_n_devices = enumerator->n_devices;
return enumerator->devices;
}

View File

@ -365,7 +365,7 @@ _public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev
assert_return(udev_enumerate, -EINVAL);
r = device_enumerator_add_match_is_initialized(udev_enumerate->enumerator, MATCH_INITIALIZED_COMPAT);
r = device_enumerator_add_match_is_initialized(udev_enumerate->enumerator);
if (r < 0)
return r;

View File

@ -11,7 +11,6 @@
#include "device-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "set.h"
@ -227,14 +226,10 @@ static int help(void) {
" -y --sysname-match=NAME Trigger devices with this /sys path\n"
" --name-match=NAME Trigger devices with this /dev name\n"
" -b --parent-match=NAME Trigger devices with that parent device\n"
" --initialized-match Trigger devices that are already initialized\n"
" --initialized-nomatch Trigger devices that are not initialized yet\n"
" -w --settle Wait for the triggered events to complete\n"
" --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n"
" before triggering uevents\n"
" --uuid Print synthetic uevent UUID\n"
" --prioritized-subsystem=SUBSYSTEM[,SUBSYSTEM…]\n"
" Trigger devices from a matching subsystem first\n",
" --uuid Print synthetic uevent UUID\n",
program_invocation_short_name);
return 0;
@ -245,9 +240,6 @@ int trigger_main(int argc, char *argv[], void *userdata) {
ARG_NAME = 0x100,
ARG_PING,
ARG_UUID,
ARG_PRIORITIZED_SUBSYSTEM,
ARG_INITIALIZED_MATCH,
ARG_INITIALIZED_NOMATCH,
};
static const struct option options[] = {
@ -265,20 +257,16 @@ int trigger_main(int argc, char *argv[], void *userdata) {
{ "sysname-match", required_argument, NULL, 'y' },
{ "name-match", required_argument, NULL, ARG_NAME },
{ "parent-match", required_argument, NULL, 'b' },
{ "initialized-match", no_argument, NULL, ARG_INITIALIZED_MATCH },
{ "initialized-nomatch", no_argument, NULL, ARG_INITIALIZED_NOMATCH },
{ "settle", no_argument, NULL, 'w' },
{ "wait-daemon", optional_argument, NULL, ARG_PING },
{ "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' },
{ "uuid", no_argument, NULL, ARG_UUID },
{ "prioritized-subsystem", required_argument, NULL, ARG_PRIORITIZED_SUBSYSTEM },
{}
};
enum {
TYPE_DEVICES,
TYPE_SUBSYSTEMS,
TYPE_ALL,
} device_type = TYPE_DEVICES;
sd_device_action_t action = SD_DEVICE_CHANGE;
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
@ -321,8 +309,6 @@ int trigger_main(int argc, char *argv[], void *userdata) {
device_type = TYPE_DEVICES;
else if (streq(optarg, "subsystems"))
device_type = TYPE_SUBSYSTEMS;
else if (streq(optarg, "all"))
device_type = TYPE_ALL;
else
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg);
break;
@ -419,26 +405,6 @@ int trigger_main(int argc, char *argv[], void *userdata) {
arg_uuid = true;
break;
case ARG_PRIORITIZED_SUBSYSTEM: {
_cleanup_strv_free_ char **subsystems = NULL;
subsystems = strv_split(optarg, ",");
if (!subsystems)
return log_error_errno(r, "Failed to parse prioritized subsystem '%s': %m", optarg);
STRV_FOREACH(p, subsystems) {
r = device_enumerator_add_prioritized_subsystem(e, *p);
if (r < 0)
return log_error_errno(r, "Failed to add prioritized subsystem '%s': %m", *p);
}
break;
}
case ARG_INITIALIZED_MATCH:
case ARG_INITIALIZED_NOMATCH:
r = device_enumerator_add_match_is_initialized(e, c == ARG_INITIALIZED_MATCH ? MATCH_INITIALIZED_YES : MATCH_INITIALIZED_NO);
if (r < 0)
return log_error_errno(r, "Failed to set initialized filter: %m");
break;
case 'V':
return print_version();
case 'h':
@ -511,11 +477,6 @@ int trigger_main(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to scan devices: %m");
break;
case TYPE_ALL:
r = device_enumerator_scan_devices_and_subsystems(e);
if (r < 0)
return log_error_errno(r, "Failed to scan devices and subsystems: %m");
break;
default:
assert_not_reached();
}

View File

@ -19,4 +19,5 @@ ConditionPathIsReadWrite=/sys
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=-udevadm trigger --type=all --action=add --prioritized-subsystem=block,tpmrm
ExecStart=-udevadm trigger --type=subsystems --action=add
ExecStart=-udevadm trigger --type=devices --action=add