1
0
mirror of https://github.com/systemd/systemd synced 2026-04-25 08:25:12 +02:00

Compare commits

..

No commits in common. "f379362157e12d6eb107c4bb97d10d3972e66c78" and "e4f92a62a83a20b6992615b0bb595b97f67481da" have entirely different histories.

46 changed files with 323 additions and 1264 deletions

5
TODO
View File

@ -78,10 +78,7 @@ Janitorial Clean-ups:
Features: Features:
* udevadm: a new "tree" verb that shows tree of devices as syspath hierarchy, * bootctl: show whether audit mode is available
along with their properties. uninitialized devices should be greyed out.
* bootctl: show whether UEFI audit mode is available
* dissect: rework how we access partitions: instead of letting the kernel probe * dissect: rework how we access partitions: instead of letting the kernel probe
partition tables asynchronously, just pass the stuff we parsed in userspace partition tables asynchronously, just pass the stuff we parsed in userspace

View File

@ -75,25 +75,6 @@ And please keep in mind: BSD file locks (`flock()`) and POSIX file locks
orthogonal. The scheme discussed above uses the former and not the latter, orthogonal. The scheme discussed above uses the former and not the latter,
because these types of locks more closely match the required semantics. because these types of locks more closely match the required semantics.
If multiple devices are to be locked at the same time (for example in order to
format a RAID file system), the devices should be locked in the order of the
the device nodes' major numbers (primary ordering key, ascending) and minor
numbers (secondary ordering key, ditto), in order to avoid ABBA locking issues
between subsystems.
Note that the locks should only be taken while the device is repartitioned,
file systems formatted or `dd`'ed in, and similar cases that
apply/remove/change superblocks/partition information. It should not be held
during normal operation, i.e. while file systems on it are mounted for
application use.
The [`udevadm
lock`](https://www.freedesktop.org/software/systemd/man/udevadm.html) command
is provided to lock block devices following this scheme from the command line,
for the use in scripts and similar. (Note though that it's typically preferable
to use native support for block device locking in tools where that's
available.)
Summarizing: it is recommended to take `LOCK_EX` BSD file locks when Summarizing: it is recommended to take `LOCK_EX` BSD file locks when
manipulating block devices in all tools that change file system block devices manipulating block devices in all tools that change file system block devices
(`mkfs`, `fsck`, …) or partition tables (`fdisk`, `parted`, …), right after (`mkfs`, `fsck`, …) or partition tables (`fdisk`, `parted`, …), right after

View File

@ -3,7 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later --> <!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="kernel-install" conditional='ENABLE_KERNEL_INSTALL' <refentry id="kernel-install"
xmlns:xi="http://www.w3.org/2001/XInclude"> xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo> <refentryinfo>

View File

@ -502,19 +502,6 @@ manpages = [
'sd_bus_track_unrefp'], 'sd_bus_track_unrefp'],
''], ''],
['sd_bus_wait', '3', [], ''], ['sd_bus_wait', '3', [], ''],
['sd_device_get_syspath',
'3',
['sd_device_get_devname',
'sd_device_get_devnum',
'sd_device_get_devpath',
'sd_device_get_devtype',
'sd_device_get_diskseq',
'sd_device_get_driver',
'sd_device_get_ifindex',
'sd_device_get_subsystem',
'sd_device_get_sysname',
'sd_device_get_sysnum'],
''],
['sd_event_add_child', ['sd_event_add_child',
'3', '3',
['sd_event_add_child_pidfd', ['sd_event_add_child_pidfd',

View File

@ -1,200 +0,0 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="sd_device_get_syspath"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_device_get_syspath</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>sd_device_get_syspath</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_device_get_syspath</refname>
<refname>sd_device_get_devpath</refname>
<refname>sd_device_get_sysname</refname>
<refname>sd_device_get_sysnum</refname>
<refname>sd_device_get_subsystem</refname>
<refname>sd_device_get_devtype</refname>
<refname>sd_device_get_devname</refname>
<refname>sd_device_get_devnum</refname>
<refname>sd_device_get_ifindex</refname>
<refname>sd_device_get_driver</refname>
<refname>sd_device_get_diskseq</refname>
<refpurpose>Returns various fields of device objects</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-device.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_device_get_syspath</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>const char **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_devpath</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>const char **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_sysname</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>const char **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_sysnum</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>const char **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_subsystem</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>const char **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_devtype</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>const char **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_devname</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>const char **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_devnum</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>dev_t *<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_ifindex</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>int *<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_driver</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>const char **<parameter>ret</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_device_get_diskseq</function></funcdef>
<paramdef>sd_device *<parameter>device</parameter></paramdef>
<paramdef>uint64_t *<parameter>ret</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_device_get_syspath()</function> returns the sysfs path of the specified device record,
including the <filename>/sys</filename> prefix. Example: <filename>/sys/devices/virtual/tty/tty7</filename></para>
<para><function>sd_device_get_devpath()</function> returns the sysfs path of the specified device record,
excluding the <filename>/sys</filename> prefix. Example: <filename>/devices/virtual/tty/tty7</filename></para>
<para><function>sd_device_get_sysname()</function> returns the sysfs name of the specified device record,
i.e. the last component of the sysfs path. Example: <literal>tty7</literal> for the device
<filename>/sys/devices/virtual/tty/tty7</filename></para>
<para><function>sd_device_get_sysnum()</function> returns the sysfs device number of the specified device
record, i.e. the numeric suffix of the last component of the sysfs path. Example: <literal>7</literal>
for the device <filename>/sys/devices/virtual/tty/tty7</filename></para>
<para><function>sd_device_get_subsystem()</function> returns the kernel subsystem of the specified device
record. This is a short string fitting into a filename, and thus does not contain a slash and cannot be
empty. Example: <literal>tty</literal>, <literal>block</literal> or <literal>net</literal>.</para>
<para><function>sd_device_get_devtype()</function> returns the device type of the specified device
record, if the subsystem manages multiple types of devices. Example: for devices of the
<literal>block</literal> subsystem this can be <literal>disk</literal> or <literal>partition</literal>
</para>
<para><function>sd_device_get_devname()</function> returns the device node path of the specified device
record if the device has a device node. Example: for <filename>/sys/devices/virtual/tty/tty7</filename>
the string <filename>/dev/tty7</filename> is typically returned.</para>
<para><function>sd_device_get_devnum()</function> returns the device node major/minor
(i.e. <type>dev_t</type>) of the specified device record if the device has a device node (i.e. the one
returned by <function>sd_device_get_devname()</function>). For devices belonging to the
<literal>block</literal> subsystem this refers to a block device node, in all other cases to a character
device node. Example: for the <filename>/sys/devices/virtual/tty/tty7</filename> device this typically
returns the device number with major/minor <literal>4:7</literal>.</para>
<para><function>sd_device_get_ifindex()</function> returns the network interface index of the specified
device record, if the device encapsulates a network interface device, i.e. belongs to the
<literal>net</literal> subsystem. Example: the <literal>lo</literal> interface typically has interface
index 1.</para>
<para><function>sd_device_get_driver()</function> returns the kernel driver name attached to the
device. Note that the driver field is set on the devices consumed by the driver, not on the device
created by it. Example: a PCI device <filename>/sys/bus/pci/devices/0000:00:1f.6</filename> might be
attached to a driver <literal>e1000e</literal>.</para>
<para><function>sd_device_get_diskseq()</function> returns the kernel disk sequence number of the block
device. This number monotonically increases whenever a backing medium of a block device changes without
the device name changing, and is relevant for block devices encapsulating devices with changing media
(e.g. floppy or CD-ROM), or loopback block devices. Only defined for block devices, i.e. those of
subsystem <literal>block</literal>.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>On success, these calls return 0 or a positive integer. On failure, they return a negative
errno-style error code.</para>
<refsect2>
<title>Errors</title>
<para>Returned errors may indicate the following problems:</para>
<variablelist>
<varlistentry>
<term><constant>-EINVAL</constant></term>
<listitem><para>A specified parameter is invalid.</para></listitem>
</varlistentry>
<varlistentry>
<term><constant>-ENOENT</constant></term>
<listitem><para>The requested field is not present in the device record.</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -51,9 +51,6 @@
<cmdsynopsis> <cmdsynopsis>
<command>udevadm wait <optional>options</optional> <replaceable>device|syspath</replaceable></command> <command>udevadm wait <optional>options</optional> <replaceable>device|syspath</replaceable></command>
</cmdsynopsis> </cmdsynopsis>
<cmdsynopsis>
<command>udevadm lock <optional>options</optional> <replaceable>command</replaceable></command>
</cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
<refsect1><title>Description</title> <refsect1><title>Description</title>
@ -230,30 +227,6 @@
<entry><literal>P:</literal></entry> <entry><literal>P:</literal></entry>
<entry>Device path in <filename>/sys/</filename></entry> <entry>Device path in <filename>/sys/</filename></entry>
</row> </row>
<row>
<entry><literal>M:</literal></entry>
<entry>Device name in <filename>/sys/</filename> (i.e. the last component of <literal>P:</literal>)</entry>
</row>
<row>
<entry><literal>R:</literal></entry>
<entry>Device number in <filename>/sys/</filename> (i.e. the numeric suffix of the last component of <literal>P:</literal>)</entry>
</row>
<row>
<entry><literal>U:</literal></entry>
<entry>Kernel subsystem</entry>
</row>
<row>
<entry><literal>T:</literal></entry>
<entry>Kernel device type within subsystem</entry>
</row>
<row>
<entry><literal>D:</literal></entry>
<entry>Kernel device node major/minor</entry>
</row>
<row>
<entry><literal>I:</literal></entry>
<entry>Network interface index</entry>
</row>
<row> <row>
<entry><literal>N:</literal></entry> <entry><literal>N:</literal></entry>
<entry>Kernel device node name</entry> <entry>Kernel device node name</entry>
@ -266,14 +239,6 @@
<entry><literal>S:</literal></entry> <entry><literal>S:</literal></entry>
<entry>Device node symlink</entry> <entry>Device node symlink</entry>
</row> </row>
<row>
<entry><literal>Q:</literal></entry>
<entry>Block device sequence number (DISKSEQ)</entry>
</row>
<row>
<entry><literal>V:</literal></entry>
<entry>Attached driver</entry>
</row>
<row> <row>
<entry><literal>E:</literal></entry> <entry><literal>E:</literal></entry>
<entry>Device property</entry> <entry>Device property</entry>
@ -782,87 +747,6 @@
<xi:include href="standard-options.xml" xpointer="help" /> <xi:include href="standard-options.xml" xpointer="help" />
</variablelist> </variablelist>
</refsect2> </refsect2>
<refsect2>
<title>udevadm lock
<arg choice="opt"><replaceable>options</replaceable></arg>
<arg choice="opt"><replaceable>command</replaceable></arg>
</title>
<para><command>udevadm lock</command> takes an (advisory) exclusive lock(s) on a block device (or
multiple therof), as per <ulink url="https://systemd.io/BLOCK_DEVICE_LOCKING">Locking Block Device
Access</ulink> and invokes a program with the lock(s) taken. When the invoked program exits the lock(s)
are automatically released.</para>
<para>This tool is in particular useful to ensure that
<citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
does not probe a block device while changes are made to it, for example partitions created or file
systems formatted. Note that many tools that interface with block devices natively support taking
relevant locks, see for example
<citerefentry><refentrytitle>sfdisk</refentrytitle><manvolnum>8</manvolnum></citerefentry>'s
<option>--lock</option> switch.</para>
<para>The command expects at least one block device specified via <option>--device=</option> or
<option>--backing=</option>, and a command line to execute as arguments.</para>
<variablelist>
<varlistentry>
<term><option>--device=<replaceable>DEVICE</replaceable></option></term>
<term><option>-d <replaceable>DEVICE</replaceable></option></term>
<listitem><para>Takes a path to a device node of the device to lock. This switch may be used
multiple times (and in combination with <option>--backing=</option>) in order to lock multiple
devices. If a partition block device node is specified the containing "whole" block device is
automatically determined and used for the lock, as per the specification. If multiple devices are
specified, they are deduplicated, sorted by the major/minor of their device nodes and then locked
in order.</para>
<para>This switch must be used at least once, to specify at least one device to
lock. (Alternatively, use <option>--backing=</option>, see below.)</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--backing=<replaceable>PATH</replaceable></option></term>
<term><option>-b <replaceable>PATH</replaceable></option></term>
<listitem><para>If a path to a device node is specified, identical to
<option>--device=</option>. However, this switch alternatively accepts a path to a regular file or
directory, in which case the block device of the file system the file/directory resides on is
automatically determined and used as if it was specified with
<option>--device=</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--timeout=<replaceable>SECS</replaceable></option></term>
<term><option>-t <replaceable>SECS</replaceable></option></term>
<listitem><para>Specifies how long to wait at most until all locks can be taken. Takes a value in
seconds, or in the usual supported time units, see
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>. If
specified as zero the lock is attempted and if not successful the invocation will immediately
fail. If passed as <literal>infinity</literal> (the default) the invocation will wait indefinitely
until the lock can be acquired. If the lock cannot be taken in the specified time the specified
command will not be executed and the invocation will fail.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--print</option></term>
<term><option>-p</option></term>
<listitem><para>Instead of locking the specified device(s) and executing a command, just print the
device path(s) that would be locked, and execute no command. This command is useful to determine
the "whole" block device in case a partition block device is specified. The devices will be sorted
by their device node major number as primary ordering key and the minor number as secondary
ordering key (i.e. they are shown in the order they'd be locked). Note that the number of lines
printed here can be less than the the number of <option>--device=</option> and
<option>--backing=</option> switches specified in case these resolve to the same "whole"
devices.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
</variablelist>
</refsect2>
</refsect1> </refsect1>
<refsect1> <refsect1>
@ -876,38 +760,6 @@
still be announced via the sd-device API (or similar).</para> still be announced via the sd-device API (or similar).</para>
</refsect1> </refsect1>
<refsect1>
<title>Example</title>
<example>
<title>Format a File System</title>
<para>Take a lock on the backing block device while creating a file system, to ensure that
<command>systemd-udevd</command> doesn't probe or announce the new superblock before it is
comprehensively written:</para>
<programlisting># udevadm lock --device=/dev/sda1 mkfs.ext4 /dev/sda1</programlisting>
</example>
<example>
<title>Format a RAID File System</title>
<para>Similar, but take locks on multiple devices at once:</para>
<programlisting># udevadm lock --device=/dev/sda1 --device=/dev/sdb1 mkfs.btrfs /dev/sda1 /dev/sdb1</programlisting>
</example>
<example>
<title>Copy in a File System</title>
<para>Take a lock on the backing block device while copying in a prepared file system image, to ensure
that <command>systemd-udevd</command> doesn't probe or announce the new superblock before it is fully
written:</para>
<programlisting># udevadm lock -d /dev/sda1 dd if=fs.raw of=/dev/sda1</programlisting>
</example>
</refsect1>
<refsect1> <refsect1>
<title>See Also</title> <title>See Also</title>
<para><citerefentry> <para><citerefentry>

View File

@ -3076,6 +3076,27 @@ if conf.get('ENABLE_BINFMT') == 1
endif endif
endif endif
if conf.get('ENABLE_REPART') == 1
exe = executable(
'systemd-repart',
systemd_repart_sources,
include_directories : includes,
link_with : [libshared],
dependencies : [threads,
libblkid,
libfdisk],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
public_programs += exe
if want_tests != 'false'
test('test-repart',
test_repart_sh,
args : exe.full_path())
endif
endif
if conf.get('ENABLE_SYSUPDATE') == 1 if conf.get('ENABLE_SYSUPDATE') == 1
exe = executable( exe = executable(
'systemd-sysupdate', 'systemd-sysupdate',
@ -3496,7 +3517,7 @@ public_programs += executable(
install : true, install : true,
install_dir : rootlibexecdir) install_dir : rootlibexecdir)
udevadm = executable( public_programs += executable(
'udevadm', 'udevadm',
udevadm_sources, udevadm_sources,
include_directories : includes, include_directories : includes,
@ -3510,28 +3531,6 @@ udevadm = executable(
install_rpath : udev_rpath, install_rpath : udev_rpath,
install : true, install : true,
install_dir : rootbindir) install_dir : rootbindir)
public_programs += udevadm
if conf.get('ENABLE_REPART') == 1
exe = executable(
'systemd-repart',
systemd_repart_sources,
include_directories : includes,
link_with : [libshared],
dependencies : [threads,
libblkid,
libfdisk],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootbindir)
public_programs += exe
if want_tests != 'false'
test('test-repart',
test_repart_sh,
args : [exe.full_path(), udevadm.full_path()])
endif
endif
executable( executable(
'systemd-shutdown', 'systemd-shutdown',

View File

@ -7,7 +7,7 @@
#include "string-table.h" #include "string-table.h"
#include "string-util.h" #include "string-util.h"
Architecture uname_architecture(void) { int uname_architecture(void) {
/* Return a sanitized enum identifying the architecture we are running on. This /* Return a sanitized enum identifying the architecture we are running on. This
* is based on uname(), and the user may hence control what this returns by using * is based on uname(), and the user may hence control what this returns by using
@ -22,7 +22,7 @@ Architecture uname_architecture(void) {
static const struct { static const struct {
const char *machine; const char *machine;
Architecture arch; int arch;
} arch_map[] = { } arch_map[] = {
#if defined(__aarch64__) || defined(__arm__) #if defined(__aarch64__) || defined(__arm__)
{ "aarch64", ARCHITECTURE_ARM64 }, { "aarch64", ARCHITECTURE_ARM64 },
@ -122,7 +122,7 @@ Architecture uname_architecture(void) {
#endif #endif
}; };
static Architecture cached = _ARCHITECTURE_INVALID; static int cached = _ARCHITECTURE_INVALID;
struct utsname u; struct utsname u;
if (cached != _ARCHITECTURE_INVALID) if (cached != _ARCHITECTURE_INVALID)
@ -175,4 +175,4 @@ static const char *const architecture_table[_ARCHITECTURE_MAX] = {
[ARCHITECTURE_TILEGX] = "tilegx", [ARCHITECTURE_TILEGX] = "tilegx",
}; };
DEFINE_STRING_TABLE_LOOKUP(architecture, Architecture); DEFINE_STRING_TABLE_LOOKUP(architecture, int);

View File

@ -48,7 +48,7 @@ typedef enum {
_ARCHITECTURE_INVALID = -EINVAL, _ARCHITECTURE_INVALID = -EINVAL,
} Architecture; } Architecture;
Architecture uname_architecture(void); int uname_architecture(void);
/* /*
* LIB_ARCH_TUPLE should resolve to the local library path * LIB_ARCH_TUPLE should resolve to the local library path
@ -243,5 +243,5 @@ Architecture uname_architecture(void);
# error "Please register your architecture here!" # error "Please register your architecture here!"
#endif #endif
const char *architecture_to_string(Architecture a) _const_; const char *architecture_to_string(int a) _const_;
Architecture architecture_from_string(const char *s) _pure_; int architecture_from_string(const char *s) _pure_;

View File

@ -102,16 +102,10 @@ DEFINE_HASH_OPS(uint64_hash_ops, uint64_t, uint64_hash_func, uint64_compare_func
void devt_hash_func(const dev_t *p, struct siphash *state) { void devt_hash_func(const dev_t *p, struct siphash *state) {
siphash24_compress(p, sizeof(dev_t), state); siphash24_compress(p, sizeof(dev_t), state);
} }
#endif
int devt_compare_func(const dev_t *a, const dev_t *b) { int devt_compare_func(const dev_t *a, const dev_t *b) {
int r; return CMP(*a, *b);
r = CMP(major(*a), major(*b));
if (r != 0)
return r;
return CMP(minor(*a), minor(*b));
} }
DEFINE_HASH_OPS(devt_hash_ops, dev_t, devt_hash_func, devt_compare_func); DEFINE_HASH_OPS(devt_hash_ops, dev_t, devt_hash_func, devt_compare_func);
#endif

View File

@ -102,9 +102,10 @@ extern const struct hash_ops uint64_hash_ops;
* 64bit archs. Yuck! */ * 64bit archs. Yuck! */
#if SIZEOF_DEV_T != 8 #if SIZEOF_DEV_T != 8
void devt_hash_func(const dev_t *p, struct siphash *state) _pure_; void devt_hash_func(const dev_t *p, struct siphash *state) _pure_;
#else
#define devt_hash_func uint64_hash_func
#endif
int devt_compare_func(const dev_t *a, const dev_t *b) _pure_; int devt_compare_func(const dev_t *a, const dev_t *b) _pure_;
extern const struct hash_ops devt_hash_ops; extern const struct hash_ops devt_hash_ops;
#else
#define devt_hash_func uint64_hash_func
#define devt_compare_func uint64_compare_func
#define devt_hash_ops uint64_hash_ops
#endif

View File

@ -1026,7 +1026,7 @@ bool oom_score_adjust_is_valid(int oa) {
} }
unsigned long personality_from_string(const char *p) { unsigned long personality_from_string(const char *p) {
Architecture architecture; int architecture;
if (!p) if (!p)
return PERSONALITY_INVALID; return PERSONALITY_INVALID;
@ -1050,7 +1050,7 @@ unsigned long personality_from_string(const char *p) {
} }
const char* personality_to_string(unsigned long p) { const char* personality_to_string(unsigned long p) {
Architecture architecture = _ARCHITECTURE_INVALID; int architecture = _ARCHITECTURE_INVALID;
if (p == PER_LINUX) if (p == PER_LINUX)
architecture = native_architecture(); architecture = native_architecture();

View File

@ -28,30 +28,31 @@ enum {
SMBIOS_VM_BIT_UNKNOWN, SMBIOS_VM_BIT_UNKNOWN,
}; };
static Virtualization detect_vm_cpuid(void) { #if defined(__i386__) || defined(__x86_64__)
static const char *const vm_table[_VIRTUALIZATION_MAX] = {
[VIRTUALIZATION_XEN] = "XenVMMXenVMM",
[VIRTUALIZATION_KVM] = "KVMKVMKVM",
[VIRTUALIZATION_HV_KVM] = "Linux KVM Hv",
[VIRTUALIZATION_QEMU] = "TCGTCGTCGTCG",
/* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
[VIRTUALIZATION_VMWARE] = "VMwareVMware",
/* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
[VIRTUALIZATION_MICROSOFT] = "Microsoft Hv",
/* https://wiki.freebsd.org/bhyve */
[VIRTUALIZATION_BHYVE] = "bhyve bhyve ",
[VIRTUALIZATION_QNX] = "QNXQVMBSQG",
/* https://projectacrn.org */
[VIRTUALIZATION_ACRN] = "ACRNACRNACRN",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(vm, int);
#endif
static int detect_vm_cpuid(void) {
/* CPUID is an x86 specific interface. */ /* CPUID is an x86 specific interface. */
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
static const struct {
const char sig[13];
Virtualization id;
} vm_table[] = {
{ "XenVMMXenVMM", VIRTUALIZATION_XEN },
{ "KVMKVMKVM", VIRTUALIZATION_KVM }, /* qemu with KVM */
{ "Linux KVM Hv", VIRTUALIZATION_KVM }, /* qemu with KVM + HyperV Enlightenments */
{ "TCGTCGTCGTCG", VIRTUALIZATION_QEMU }, /* qemu without KVM */
/* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
{ "VMwareVMware", VIRTUALIZATION_VMWARE },
/* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */
{ "Microsoft Hv", VIRTUALIZATION_MICROSOFT },
/* https://wiki.freebsd.org/bhyve */
{ "bhyve bhyve ", VIRTUALIZATION_BHYVE },
{ "QNXQVMBSQG", VIRTUALIZATION_QNX },
/* https://projectacrn.org */
{ "ACRNACRNACRN", VIRTUALIZATION_ACRN },
};
uint32_t eax, ebx, ecx, edx; uint32_t eax, ebx, ecx, edx;
bool hypervisor; bool hypervisor;
@ -68,6 +69,7 @@ static Virtualization detect_vm_cpuid(void) {
uint32_t sig32[3]; uint32_t sig32[3];
char text[13]; char text[13];
} sig = {}; } sig = {};
int v;
/* There is a hypervisor, see what it is */ /* There is a hypervisor, see what it is */
__cpuid(0x40000000U, eax, ebx, ecx, edx); __cpuid(0x40000000U, eax, ebx, ecx, edx);
@ -78,13 +80,11 @@ static Virtualization detect_vm_cpuid(void) {
log_debug("Virtualization found, CPUID=%s", sig.text); log_debug("Virtualization found, CPUID=%s", sig.text);
for (size_t i = 0; i < ELEMENTSOF(vm_table); i++) v = vm_from_string(sig.text);
if (memcmp_nn(sig.text, sizeof(sig.text), if (v < 0)
vm_table[i].sig, sizeof(vm_table[i].sig)) == 0)
return vm_table[i].id;
log_debug("Unknown virtualization with CPUID=%s. Add to vm_table[]?", sig.text);
return VIRTUALIZATION_VM_OTHER; return VIRTUALIZATION_VM_OTHER;
return v;
} }
#endif #endif
log_debug("No virtualization found in CPUID"); log_debug("No virtualization found in CPUID");
@ -92,7 +92,7 @@ static Virtualization detect_vm_cpuid(void) {
return VIRTUALIZATION_NONE; return VIRTUALIZATION_NONE;
} }
static Virtualization detect_vm_device_tree(void) { static int detect_vm_device_tree(void) {
#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__) #if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__)
_cleanup_free_ char *hvtype = NULL; _cleanup_free_ char *hvtype = NULL;
int r; int r;
@ -142,7 +142,7 @@ static Virtualization detect_vm_device_tree(void) {
} }
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64)
static Virtualization detect_vm_dmi_vendor(void) { static int detect_vm_dmi_vendor(void) {
static const char *const dmi_vendors[] = { static const char *const dmi_vendors[] = {
"/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */ "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */
"/sys/class/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor",
@ -153,7 +153,7 @@ static Virtualization detect_vm_dmi_vendor(void) {
static const struct { static const struct {
const char *vendor; const char *vendor;
Virtualization id; int id;
} dmi_vendor_table[] = { } dmi_vendor_table[] = {
{ "KVM", VIRTUALIZATION_KVM }, { "KVM", VIRTUALIZATION_KVM },
{ "Amazon EC2", VIRTUALIZATION_AMAZON }, { "Amazon EC2", VIRTUALIZATION_AMAZON },
@ -173,6 +173,7 @@ static Virtualization detect_vm_dmi_vendor(void) {
for (size_t i = 0; i < ELEMENTSOF(dmi_vendors); i++) { for (size_t i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
_cleanup_free_ char *s = NULL; _cleanup_free_ char *s = NULL;
unsigned j;
r = read_one_line_file(dmi_vendors[i], &s); r = read_one_line_file(dmi_vendors[i], &s);
if (r < 0) { if (r < 0) {
@ -182,7 +183,7 @@ static Virtualization detect_vm_dmi_vendor(void) {
return r; return r;
} }
for (size_t j = 0; j < ELEMENTSOF(dmi_vendor_table); j++) for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++)
if (startswith(s, dmi_vendor_table[j].vendor)) { if (startswith(s, dmi_vendor_table[j].vendor)) {
log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]); log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]);
return dmi_vendor_table[j].id; return dmi_vendor_table[j].id;
@ -229,7 +230,7 @@ static int detect_vm_smbios(void) {
} }
#endif /* defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) */ #endif /* defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) */
static Virtualization detect_vm_dmi(void) { static int detect_vm_dmi(void) {
#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64) #if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || defined(__loongarch64)
int r; int r;
@ -331,7 +332,7 @@ static int detect_vm_xen_dom0(void) {
} }
} }
static Virtualization detect_vm_xen(void) { static int detect_vm_xen(void) {
/* The presence of /proc/xen indicates some form of a Xen domain /* The presence of /proc/xen indicates some form of a Xen domain
The check for Dom0 is handled outside this function */ The check for Dom0 is handled outside this function */
if (access("/proc/xen", F_OK) < 0) { if (access("/proc/xen", F_OK) < 0) {
@ -342,7 +343,7 @@ static Virtualization detect_vm_xen(void) {
return VIRTUALIZATION_XEN; return VIRTUALIZATION_XEN;
} }
static Virtualization detect_vm_hypervisor(void) { static int detect_vm_hypervisor(void) {
_cleanup_free_ char *hvtype = NULL; _cleanup_free_ char *hvtype = NULL;
int r; int r;
@ -360,7 +361,7 @@ static Virtualization detect_vm_hypervisor(void) {
return VIRTUALIZATION_VM_OTHER; return VIRTUALIZATION_VM_OTHER;
} }
static Virtualization detect_vm_uml(void) { static int detect_vm_uml(void) {
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
int r; int r;
@ -399,7 +400,7 @@ static Virtualization detect_vm_uml(void) {
return VIRTUALIZATION_NONE; return VIRTUALIZATION_NONE;
} }
static Virtualization detect_vm_zvm(void) { static int detect_vm_zvm(void) {
#if defined(__s390__) #if defined(__s390__)
_cleanup_free_ char *t = NULL; _cleanup_free_ char *t = NULL;
@ -423,11 +424,10 @@ static Virtualization detect_vm_zvm(void) {
} }
/* Returns a short identifier for the various VM implementations */ /* Returns a short identifier for the various VM implementations */
Virtualization detect_vm(void) { int detect_vm(void) {
static thread_local Virtualization cached_found = _VIRTUALIZATION_INVALID; static thread_local int cached_found = _VIRTUALIZATION_INVALID;
bool other = false; bool other = false;
int xen_dom0 = 0; int r, dmi, xen_dom0 = 0;
Virtualization v, dmi;
if (cached_found >= 0) if (cached_found >= 0)
return cached_found; return cached_found;
@ -446,22 +446,22 @@ Virtualization detect_vm(void) {
dmi = detect_vm_dmi(); dmi = detect_vm_dmi();
if (IN_SET(dmi, VIRTUALIZATION_ORACLE, VIRTUALIZATION_XEN, VIRTUALIZATION_AMAZON)) { if (IN_SET(dmi, VIRTUALIZATION_ORACLE, VIRTUALIZATION_XEN, VIRTUALIZATION_AMAZON)) {
v = dmi; r = dmi;
goto finish; goto finish;
} }
/* Detect UML */ /* Detect UML */
v = detect_vm_uml(); r = detect_vm_uml();
if (v < 0) if (r < 0)
return v; return r;
if (v != VIRTUALIZATION_NONE) if (r != VIRTUALIZATION_NONE)
goto finish; goto finish;
/* Detect Xen */ /* Detect Xen */
v = detect_vm_xen(); r = detect_vm_xen();
if (v < 0) if (r < 0)
return v; return r;
if (v == VIRTUALIZATION_XEN) { if (r == VIRTUALIZATION_XEN) {
/* If we are Dom0, then we expect to not report as a VM. However, as we might be nested /* If we are Dom0, then we expect to not report as a VM. However, as we might be nested
* inside another hypervisor which can be detected via the CPUID check, wait to report this * inside another hypervisor which can be detected via the CPUID check, wait to report this
* until after the CPUID check. */ * until after the CPUID check. */
@ -471,17 +471,17 @@ Virtualization detect_vm(void) {
if (xen_dom0 == 0) if (xen_dom0 == 0)
goto finish; goto finish;
v = VIRTUALIZATION_NONE; r = VIRTUALIZATION_NONE;
} else if (v != VIRTUALIZATION_NONE) } else if (r != VIRTUALIZATION_NONE)
assert_not_reached(); assert_not_reached();
/* Detect from CPUID */ /* Detect from CPUID */
v = detect_vm_cpuid(); r = detect_vm_cpuid();
if (v < 0) if (r < 0)
return v; return r;
if (v == VIRTUALIZATION_VM_OTHER) if (r == VIRTUALIZATION_VM_OTHER)
other = true; other = true;
else if (v != VIRTUALIZATION_NONE) else if (r != VIRTUALIZATION_NONE)
goto finish; goto finish;
/* If we are in Dom0 and have not yet finished, finish with the result of detect_vm_cpuid */ /* If we are in Dom0 and have not yet finished, finish with the result of detect_vm_cpuid */
@ -494,38 +494,38 @@ Virtualization detect_vm(void) {
if (dmi == VIRTUALIZATION_VM_OTHER) if (dmi == VIRTUALIZATION_VM_OTHER)
other = true; other = true;
else if (dmi != VIRTUALIZATION_NONE) { else if (dmi != VIRTUALIZATION_NONE) {
v = dmi; r = dmi;
goto finish; goto finish;
} }
/* Check high-level hypervisor sysfs file */ /* Check high-level hypervisor sysfs file */
v = detect_vm_hypervisor(); r = detect_vm_hypervisor();
if (v < 0) if (r < 0)
return v; return r;
if (v == VIRTUALIZATION_VM_OTHER) if (r == VIRTUALIZATION_VM_OTHER)
other = true; other = true;
else if (v != VIRTUALIZATION_NONE) else if (r != VIRTUALIZATION_NONE)
goto finish; goto finish;
v = detect_vm_device_tree(); r = detect_vm_device_tree();
if (v < 0) if (r < 0)
return v; return r;
if (v == VIRTUALIZATION_VM_OTHER) if (r == VIRTUALIZATION_VM_OTHER)
other = true; other = true;
else if (v != VIRTUALIZATION_NONE) else if (r != VIRTUALIZATION_NONE)
goto finish; goto finish;
v = detect_vm_zvm(); r = detect_vm_zvm();
if (v < 0) if (r < 0)
return v; return r;
finish: finish:
if (v == VIRTUALIZATION_NONE && other) if (r == VIRTUALIZATION_NONE && other)
v = VIRTUALIZATION_VM_OTHER; r = VIRTUALIZATION_VM_OTHER;
cached_found = v; cached_found = r;
log_debug("Found VM virtualization %s", virtualization_to_string(v)); log_debug("Found VM virtualization %s", virtualization_to_string(r));
return v; return r;
} }
static const char *const container_table[_VIRTUALIZATION_MAX] = { static const char *const container_table[_VIRTUALIZATION_MAX] = {
@ -608,10 +608,12 @@ static int running_in_cgroupns(void) {
} }
} }
static Virtualization detect_container_files(void) { static int detect_container_files(void) {
unsigned i;
static const struct { static const struct {
const char *file_path; const char *file_path;
Virtualization id; int id;
} container_file_table[] = { } container_file_table[] = {
/* https://github.com/containers/podman/issues/6192 */ /* https://github.com/containers/podman/issues/6192 */
/* https://github.com/containers/podman/issues/3586#issuecomment-661918679 */ /* https://github.com/containers/podman/issues/3586#issuecomment-661918679 */
@ -621,7 +623,7 @@ static Virtualization detect_container_files(void) {
{ "/.dockerenv", VIRTUALIZATION_DOCKER }, { "/.dockerenv", VIRTUALIZATION_DOCKER },
}; };
for (size_t i = 0; i < ELEMENTSOF(container_file_table); i++) { for (i = 0; i < ELEMENTSOF(container_file_table); i++) {
if (access(container_file_table[i].file_path, F_OK) >= 0) if (access(container_file_table[i].file_path, F_OK) >= 0)
return container_file_table[i].id; return container_file_table[i].id;
@ -634,11 +636,10 @@ static Virtualization detect_container_files(void) {
return VIRTUALIZATION_NONE; return VIRTUALIZATION_NONE;
} }
Virtualization detect_container(void) { int detect_container(void) {
static thread_local Virtualization cached_found = _VIRTUALIZATION_INVALID; static thread_local int cached_found = _VIRTUALIZATION_INVALID;
_cleanup_free_ char *m = NULL, *o = NULL, *p = NULL; _cleanup_free_ char *m = NULL, *o = NULL, *p = NULL;
const char *e = NULL; const char *e = NULL;
Virtualization v;
int r; int r;
if (cached_found >= 0) if (cached_found >= 0)
@ -650,7 +651,7 @@ Virtualization detect_container(void) {
log_debug_errno(errno, "Failed to check if /proc/vz exists, ignoring: %m"); log_debug_errno(errno, "Failed to check if /proc/vz exists, ignoring: %m");
} else if (access("/proc/bc", F_OK) < 0) { } else if (access("/proc/bc", F_OK) < 0) {
if (errno == ENOENT) { if (errno == ENOENT) {
v = VIRTUALIZATION_OPENVZ; r = VIRTUALIZATION_OPENVZ;
goto finish; goto finish;
} }
@ -662,7 +663,7 @@ Virtualization detect_container(void) {
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to read /proc/sys/kernel/osrelease, ignoring: %m"); log_debug_errno(r, "Failed to read /proc/sys/kernel/osrelease, ignoring: %m");
else if (strstr(o, "Microsoft") || strstr(o, "WSL")) { else if (strstr(o, "Microsoft") || strstr(o, "WSL")) {
v = VIRTUALIZATION_WSL; r = VIRTUALIZATION_WSL;
goto finish; goto finish;
} }
@ -687,7 +688,7 @@ Virtualization detect_container(void) {
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to read %s, ignoring: %m", pf); log_debug_errno(r, "Failed to read %s, ignoring: %m", pf);
else if (startswith(ptrace_comm, "proot")) { else if (startswith(ptrace_comm, "proot")) {
v = VIRTUALIZATION_PROOT; r = VIRTUALIZATION_PROOT;
goto finish; goto finish;
} }
} }
@ -714,7 +715,7 @@ Virtualization detect_container(void) {
if (!e) if (!e)
goto check_files; goto check_files;
if (isempty(e)) { if (isempty(e)) {
v = VIRTUALIZATION_NONE; r = VIRTUALIZATION_NONE;
goto finish; goto finish;
} }
@ -745,51 +746,49 @@ check_files:
* for other specific container managers, otherwise we risk mistaking another * for other specific container managers, otherwise we risk mistaking another
* container manager for Docker: the /.dockerenv file could inadvertently end up * container manager for Docker: the /.dockerenv file could inadvertently end up
* in a file system image. */ * in a file system image. */
v = detect_container_files(); r = detect_container_files();
if (v < 0) if (r)
return v;
if (v != VIRTUALIZATION_NONE)
goto finish; goto finish;
r = running_in_cgroupns(); r = running_in_cgroupns();
if (r > 0) { if (r > 0) {
v = VIRTUALIZATION_CONTAINER_OTHER; r = VIRTUALIZATION_CONTAINER_OTHER;
goto finish; goto finish;
} }
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to detect cgroup namespace: %m"); log_debug_errno(r, "Failed to detect cgroup namespace: %m");
/* If none of that worked, give up, assume no container manager. */ /* If none of that worked, give up, assume no container manager. */
v = VIRTUALIZATION_NONE; r = VIRTUALIZATION_NONE;
goto finish; goto finish;
translate_name: translate_name:
if (streq(e, "oci")) { if (streq(e, "oci")) {
/* Some images hardcode container=oci, but OCI is not a specific container manager. /* Some images hardcode container=oci, but OCI is not a specific container manager.
* Try to detect one based on well-known files. */ * Try to detect one based on well-known files. */
v = detect_container_files(); r = detect_container_files();
if (v != VIRTUALIZATION_NONE) if (!r)
v = VIRTUALIZATION_CONTAINER_OTHER; r = VIRTUALIZATION_CONTAINER_OTHER;
goto finish; goto finish;
} }
v = container_from_string(e); r = container_from_string(e);
if (v < 0) if (r < 0)
v = VIRTUALIZATION_CONTAINER_OTHER; r = VIRTUALIZATION_CONTAINER_OTHER;
finish: finish:
log_debug("Found container virtualization %s.", virtualization_to_string(v)); log_debug("Found container virtualization %s.", virtualization_to_string(r));
cached_found = v; cached_found = r;
return v; return r;
} }
Virtualization detect_virtualization(void) { int detect_virtualization(void) {
int v; int r;
v = detect_container(); r = detect_container();
if (v != VIRTUALIZATION_NONE) if (r == 0)
return v; r = detect_vm();
return detect_vm(); return r;
} }
static int userns_has_mapping(const char *name) { static int userns_has_mapping(const char *name) {
@ -997,6 +996,7 @@ bool has_cpu_with_flag(const char *flag) {
static const char *const virtualization_table[_VIRTUALIZATION_MAX] = { static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
[VIRTUALIZATION_NONE] = "none", [VIRTUALIZATION_NONE] = "none",
[VIRTUALIZATION_KVM] = "kvm", [VIRTUALIZATION_KVM] = "kvm",
[VIRTUALIZATION_HV_KVM] = "kvm",
[VIRTUALIZATION_AMAZON] = "amazon", [VIRTUALIZATION_AMAZON] = "amazon",
[VIRTUALIZATION_QEMU] = "qemu", [VIRTUALIZATION_QEMU] = "qemu",
[VIRTUALIZATION_BOCHS] = "bochs", [VIRTUALIZATION_BOCHS] = "bochs",
@ -1026,4 +1026,4 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
[VIRTUALIZATION_CONTAINER_OTHER] = "container-other", [VIRTUALIZATION_CONTAINER_OTHER] = "container-other",
}; };
DEFINE_STRING_TABLE_LOOKUP(virtualization, Virtualization); DEFINE_STRING_TABLE_LOOKUP(virtualization, int);

View File

@ -3,14 +3,14 @@
#include <stdbool.h> #include <stdbool.h>
#include "errno-list.h"
#include "macro.h" #include "macro.h"
typedef enum Virtualization { enum {
VIRTUALIZATION_NONE = 0, VIRTUALIZATION_NONE = 0,
VIRTUALIZATION_VM_FIRST, VIRTUALIZATION_VM_FIRST,
VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST, VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST,
VIRTUALIZATION_HV_KVM,
VIRTUALIZATION_AMAZON, VIRTUALIZATION_AMAZON,
VIRTUALIZATION_QEMU, VIRTUALIZATION_QEMU,
VIRTUALIZATION_BOCHS, VIRTUALIZATION_BOCHS,
@ -44,24 +44,23 @@ typedef enum Virtualization {
_VIRTUALIZATION_MAX, _VIRTUALIZATION_MAX,
_VIRTUALIZATION_INVALID = -EINVAL, _VIRTUALIZATION_INVALID = -EINVAL,
_VIRTUALIZATION_ERRNO_MAX = -ERRNO_MAX, /* ensure full range of errno fits into this enum */ };
} Virtualization;
static inline bool VIRTUALIZATION_IS_VM(Virtualization x) { static inline bool VIRTUALIZATION_IS_VM(int x) {
return x >= VIRTUALIZATION_VM_FIRST && x <= VIRTUALIZATION_VM_LAST; return x >= VIRTUALIZATION_VM_FIRST && x <= VIRTUALIZATION_VM_LAST;
} }
static inline bool VIRTUALIZATION_IS_CONTAINER(Virtualization x) { static inline bool VIRTUALIZATION_IS_CONTAINER(int x) {
return x >= VIRTUALIZATION_CONTAINER_FIRST && x <= VIRTUALIZATION_CONTAINER_LAST; return x >= VIRTUALIZATION_CONTAINER_FIRST && x <= VIRTUALIZATION_CONTAINER_LAST;
} }
Virtualization detect_vm(void); int detect_vm(void);
Virtualization detect_container(void); int detect_container(void);
Virtualization detect_virtualization(void); int detect_virtualization(void);
int running_in_userns(void); int running_in_userns(void);
int running_in_chroot(void); int running_in_chroot(void);
const char *virtualization_to_string(Virtualization v) _const_; const char *virtualization_to_string(int v) _const_;
Virtualization virtualization_from_string(const char *s) _pure_; int virtualization_from_string(const char *s) _pure_;
bool has_cpu_with_flag(const char *flag); bool has_cpu_with_flag(const char *flag);

View File

@ -71,7 +71,7 @@ static int property_get_virtualization(
void *userdata, void *userdata,
sd_bus_error *error) { sd_bus_error *error) {
Virtualization v; int v;
assert(bus); assert(bus);
assert(reply); assert(reply);

View File

@ -102,7 +102,7 @@ static int parse_argv(int argc, char *argv[]) {
break; break;
case ARG_LIST: case ARG_LIST:
DUMP_STRING_TABLE(virtualization, Virtualization, _VIRTUALIZATION_MAX); DUMP_STRING_TABLE(virtualization, int, _VIRTUALIZATION_MAX);
return 0; return 0;
case '?': case '?':
@ -121,7 +121,6 @@ static int parse_argv(int argc, char *argv[]) {
} }
static int run(int argc, char *argv[]) { static int run(int argc, char *argv[]) {
Virtualization v;
int r; int r;
/* This is mostly intended to be used for scripts which want /* This is mostly intended to be used for scripts which want
@ -136,15 +135,15 @@ static int run(int argc, char *argv[]) {
switch (arg_mode) { switch (arg_mode) {
case ONLY_VM: case ONLY_VM:
v = detect_vm(); r = detect_vm();
if (v < 0) if (r < 0)
return log_error_errno(v, "Failed to check for VM: %m"); return log_error_errno(r, "Failed to check for VM: %m");
break; break;
case ONLY_CONTAINER: case ONLY_CONTAINER:
v = detect_container(); r = detect_container();
if (v < 0) if (r < 0)
return log_error_errno(v, "Failed to check for container: %m"); return log_error_errno(r, "Failed to check for container: %m");
break; break;
case ONLY_CHROOT: case ONLY_CHROOT:
@ -161,16 +160,16 @@ static int run(int argc, char *argv[]) {
case ANY_VIRTUALIZATION: case ANY_VIRTUALIZATION:
default: default:
v = detect_virtualization(); r = detect_virtualization();
if (v < 0) if (r < 0)
return log_error_errno(v, "Failed to check for virtualization: %m"); return log_error_errno(r, "Failed to check for virtualization: %m");
break; break;
} }
if (!arg_quiet) if (!arg_quiet)
puts(virtualization_to_string(v)); puts(virtualization_to_string(r));
return v == VIRTUALIZATION_NONE; return r == VIRTUALIZATION_NONE;
} }
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);

View File

@ -261,9 +261,8 @@ static bool valid_deployment(const char *deployment) {
static const char* fallback_chassis(void) { static const char* fallback_chassis(void) {
const char *chassis; const char *chassis;
_cleanup_free_ char *type = NULL; _cleanup_free_ char *type = NULL;
Virtualization v;
unsigned t; unsigned t;
int r; int v, r;
v = detect_virtualization(); v = detect_virtualization();
if (v < 0) if (v < 0)

View File

@ -157,7 +157,7 @@ static int cache_space_refresh(Server *s, JournalStorage *storage) {
avail = LESS_BY(vfs_avail, metrics->keep_free); avail = LESS_BY(vfs_avail, metrics->keep_free);
space->limit = CLAMP(vfs_used + avail, metrics->min_use, metrics->max_use); space->limit = MIN(MAX(vfs_used + avail, metrics->min_use), metrics->max_use);
space->available = LESS_BY(space->limit, vfs_used); space->available = LESS_BY(space->limit, vfs_used);
space->timestamp = ts; space->timestamp = ts;
return 1; return 1;

View File

@ -64,7 +64,7 @@ struct sd_dhcp6_client {
struct duid duid; struct duid duid;
size_t duid_len; size_t duid_len;
be16_t *req_opts; be16_t *req_opts;
size_t n_req_opts; size_t req_opts_len;
char *fqdn; char *fqdn;
char *mudurl; char *mudurl;
char **user_class; char **user_class;

View File

@ -51,20 +51,18 @@ bool dhcp6_option_can_request(uint16_t option) {
return false; return false;
case SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME: case SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME:
case SD_DHCP6_OPTION_SIP_SERVER_ADDRESS: case SD_DHCP6_OPTION_SIP_SERVER_ADDRESS:
case SD_DHCP6_OPTION_DNS_SERVER: case SD_DHCP6_OPTION_DNS_SERVERS:
case SD_DHCP6_OPTION_DOMAIN: case SD_DHCP6_OPTION_DOMAIN_LIST:
return true; return true;
case SD_DHCP6_OPTION_IA_PD: case SD_DHCP6_OPTION_IA_PD:
case SD_DHCP6_OPTION_IA_PD_PREFIX: case SD_DHCP6_OPTION_IA_PD_PREFIX:
return false; return false;
case SD_DHCP6_OPTION_NIS_SERVER: case SD_DHCP6_OPTION_NIS_SERVERS:
case SD_DHCP6_OPTION_NISP_SERVER: case SD_DHCP6_OPTION_NISP_SERVERS:
case SD_DHCP6_OPTION_NIS_DOMAIN_NAME: case SD_DHCP6_OPTION_NIS_DOMAIN_NAME:
case SD_DHCP6_OPTION_NISP_DOMAIN_NAME: case SD_DHCP6_OPTION_NISP_DOMAIN_NAME:
case SD_DHCP6_OPTION_SNTP_SERVER: case SD_DHCP6_OPTION_SNTP_SERVERS:
return true;
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME: case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
return false; /* This is automatically set when sending INFORMATION_REQUEST message. */
case SD_DHCP6_OPTION_BCMCS_SERVER_D: case SD_DHCP6_OPTION_BCMCS_SERVER_D:
case SD_DHCP6_OPTION_BCMCS_SERVER_A: case SD_DHCP6_OPTION_BCMCS_SERVER_A:
case SD_DHCP6_OPTION_GEOCONF_CIVIC: case SD_DHCP6_OPTION_GEOCONF_CIVIC:
@ -126,9 +124,9 @@ bool dhcp6_option_can_request(uint16_t option) {
case SD_DHCP6_OPTION_CLIENT_LINKLAYER_ADDR: case SD_DHCP6_OPTION_CLIENT_LINKLAYER_ADDR:
case SD_DHCP6_OPTION_LINK_ADDRESS: case SD_DHCP6_OPTION_LINK_ADDRESS:
case SD_DHCP6_OPTION_RADIUS: case SD_DHCP6_OPTION_RADIUS:
case SD_DHCP6_OPTION_SOL_MAX_RT: /* Automatically set when sending SOLICIT message. */
case SD_DHCP6_OPTION_INF_MAX_RT: /* Automatically set when sending INFORMATION_REQUEST message. */
return false; return false;
case SD_DHCP6_OPTION_SOL_MAX_RT:
case SD_DHCP6_OPTION_INF_MAX_RT:
case SD_DHCP6_OPTION_ADDRSEL: case SD_DHCP6_OPTION_ADDRSEL:
case SD_DHCP6_OPTION_ADDRSEL_TABLE: case SD_DHCP6_OPTION_ADDRSEL_TABLE:
case SD_DHCP6_OPTION_V6_PCP_SERVER: case SD_DHCP6_OPTION_V6_PCP_SERVER:

View File

@ -23,10 +23,16 @@
#include "io-util.h" #include "io-util.h"
#include "random-util.h" #include "random-util.h"
#include "socket-util.h" #include "socket-util.h"
#include "sort-util.h"
#include "strv.h" #include "strv.h"
#include "web-util.h" #include "web-util.h"
static const uint16_t default_req_opts[] = {
SD_DHCP6_OPTION_DNS_SERVERS,
SD_DHCP6_OPTION_DOMAIN_LIST,
SD_DHCP6_OPTION_NTP_SERVER,
SD_DHCP6_OPTION_SNTP_SERVERS,
};
#define DHCP6_CLIENT_DONT_DESTROY(client) \ #define DHCP6_CLIENT_DONT_DESTROY(client) \
_cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client) _cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
@ -365,12 +371,8 @@ int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enable
return 0; return 0;
} }
static int be16_compare_func(const be16_t *a, const be16_t *b) {
return CMP(be16toh(*a), be16toh(*b));
}
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) { int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {
be16_t opt; size_t t;
assert_return(client, -EINVAL); assert_return(client, -EINVAL);
assert_return(!sd_dhcp6_client_is_running(client), -EBUSY); assert_return(!sd_dhcp6_client_is_running(client), -EBUSY);
@ -378,17 +380,15 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
if (!dhcp6_option_can_request(option)) if (!dhcp6_option_can_request(option))
return -EINVAL; return -EINVAL;
opt = htobe16(option); for (t = 0; t < client->req_opts_len; t++)
if (typesafe_bsearch(&opt, client->req_opts, client->n_req_opts, be16_compare_func)) if (client->req_opts[t] == htobe16(option))
return -EEXIST; return -EEXIST;
if (!GREEDY_REALLOC(client->req_opts, client->n_req_opts + 1)) if (!GREEDY_REALLOC(client->req_opts, client->req_opts_len + 1))
return -ENOMEM; return -ENOMEM;
client->req_opts[client->n_req_opts++] = opt; client->req_opts[client->req_opts_len++] = htobe16(option);
/* Sort immediately to make the above binary search will work for the next time. */
typesafe_qsort(client->req_opts, client->n_req_opts, be16_compare_func);
return 0; return 0;
} }
@ -635,51 +635,6 @@ static DHCP6MessageType client_message_type_from_state(sd_dhcp6_client *client)
} }
} }
static int client_append_oro(sd_dhcp6_client *client, uint8_t **opt, size_t *optlen) {
_cleanup_free_ be16_t *buf = NULL;
be16_t *req_opts;
size_t n;
assert(client);
assert(opt);
assert(optlen);
switch (client->state) {
case DHCP6_STATE_INFORMATION_REQUEST:
n = client->n_req_opts;
buf = new(be16_t, n + 2);
if (!buf)
return -ENOMEM;
memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
buf[n++] = htobe16(SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME); /* RFC 8415 section 21.23 */
buf[n++] = htobe16(SD_DHCP6_OPTION_INF_MAX_RT); /* RFC 8415 section 21.25 */
typesafe_qsort(buf, n, be16_compare_func);
req_opts = buf;
break;
case DHCP6_STATE_SOLICITATION:
n = client->n_req_opts;
buf = new(be16_t, n + 1);
if (!buf)
return -ENOMEM;
memcpy_safe(buf, client->req_opts, n * sizeof(be16_t));
buf[n++] = htobe16(SD_DHCP6_OPTION_SOL_MAX_RT); /* RFC 8415 section 21.24 */
typesafe_qsort(buf, n, be16_compare_func);
req_opts = buf;
break;
default:
n = client->n_req_opts;
req_opts = client->req_opts;
}
return dhcp6_option_append(opt, optlen, SD_DHCP6_OPTION_ORO, n * sizeof(be16_t), req_opts);
}
int dhcp6_client_send_message(sd_dhcp6_client *client) { int dhcp6_client_send_message(sd_dhcp6_client *client) {
_cleanup_free_ DHCP6Message *message = NULL; _cleanup_free_ DHCP6Message *message = NULL;
struct in6_addr all_servers = struct in6_addr all_servers =
@ -757,7 +712,9 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
return r; return r;
} }
r = client_append_oro(client, &opt, &optlen); r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO,
client->req_opts_len * sizeof(be16_t),
client->req_opts);
if (r < 0) if (r < 0)
return r; return r;
@ -1456,9 +1413,18 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_client, sd_dhcp6_client, dhcp6_client_fre
int sd_dhcp6_client_new(sd_dhcp6_client **ret) { int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
_cleanup_free_ be16_t *req_opts = NULL;
size_t t;
assert_return(ret, -EINVAL); assert_return(ret, -EINVAL);
req_opts = new(be16_t, ELEMENTSOF(default_req_opts));
if (!req_opts)
return -ENOMEM;
for (t = 0; t < ELEMENTSOF(default_req_opts); t++)
req_opts[t] = htobe16(default_req_opts[t]);
client = new(sd_dhcp6_client, 1); client = new(sd_dhcp6_client, 1);
if (!client) if (!client)
return -ENOMEM; return -ENOMEM;
@ -1470,6 +1436,8 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
.ifindex = -1, .ifindex = -1,
.request_ia = DHCP6_REQUEST_IA_NA | DHCP6_REQUEST_IA_PD, .request_ia = DHCP6_REQUEST_IA_NA | DHCP6_REQUEST_IA_PD,
.fd = -1, .fd = -1,
.req_opts_len = ELEMENTSOF(default_req_opts),
.req_opts = TAKE_PTR(req_opts),
}; };
*ret = TAKE_PTR(client); *ret = TAKE_PTR(client);

View File

@ -570,14 +570,14 @@ static int dhcp6_lease_parse_message(
break; break;
case SD_DHCP6_OPTION_DNS_SERVER: case SD_DHCP6_OPTION_DNS_SERVERS:
r = dhcp6_lease_add_dns(lease, optval, optlen); r = dhcp6_lease_add_dns(lease, optval, optlen);
if (r < 0) if (r < 0)
log_dhcp6_client_errno(client, r, "Failed to parse DNS server option, ignoring: %m"); log_dhcp6_client_errno(client, r, "Failed to parse DNS server option, ignoring: %m");
break; break;
case SD_DHCP6_OPTION_DOMAIN: case SD_DHCP6_OPTION_DOMAIN_LIST:
r = dhcp6_lease_add_domains(lease, optval, optlen); r = dhcp6_lease_add_domains(lease, optval, optlen);
if (r < 0) if (r < 0)
log_dhcp6_client_errno(client, r, "Failed to parse domain list option, ignoring: %m"); log_dhcp6_client_errno(client, r, "Failed to parse domain list option, ignoring: %m");
@ -591,7 +591,7 @@ static int dhcp6_lease_parse_message(
break; break;
case SD_DHCP6_OPTION_SNTP_SERVER: case SD_DHCP6_OPTION_SNTP_SERVERS:
r = dhcp6_lease_add_sntp(lease, optval, optlen); r = dhcp6_lease_add_sntp(lease, optval, optlen);
if (r < 0) if (r < 0)
log_dhcp6_client_errno(client, r, "Failed to parse SNTP server option, ignoring: %m"); log_dhcp6_client_errno(client, r, "Failed to parse SNTP server option, ignoring: %m");

View File

@ -97,15 +97,15 @@ TEST(client_basic) {
assert_se(sd_dhcp6_client_set_fqdn(client, "~host.domain") == -EINVAL); assert_se(sd_dhcp6_client_set_fqdn(client, "~host.domain") == -EINVAL);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER) >= 0); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) >= 0); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER) >= 0); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVERS) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN) >= 0); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL); assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVER) >= 0); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVERS) == 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVER) >= 0); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVERS) == 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVER) == -EEXIST); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVERS) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVER) == -EEXIST); assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVERS) == -EEXIST);
assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0); assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0);
v = 0; v = 0;
@ -403,7 +403,7 @@ TEST(client_parse_message_issue_22099) {
0x00, SD_DHCP6_OPTION_PREFERENCE, 0x00, 0x01, 0x00, SD_DHCP6_OPTION_PREFERENCE, 0x00, 0x01,
0x00, 0x00,
/* DNS servers */ /* DNS servers */
0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x10, 0x00, SD_DHCP6_OPTION_DNS_SERVERS, 0x00, 0x10,
0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
/* v6 pcp server */ /* v6 pcp server */
0x00, SD_DHCP6_OPTION_V6_PCP_SERVER, 0x00, 0x10, 0x00, SD_DHCP6_OPTION_V6_PCP_SERVER, 0x00, 0x10,
@ -450,13 +450,11 @@ static const uint8_t msg_information_request[] = {
0x0f, 0xb4, 0xe5, 0x0f, 0xb4, 0xe5,
/* MUD URL */ /* MUD URL */
/* ORO */ /* ORO */
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0c, 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, SD_DHCP6_OPTION_DNS_SERVERS,
0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, SD_DHCP6_OPTION_DOMAIN_LIST,
0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0x00, SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME,
0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, SD_DHCP6_OPTION_NTP_SERVER,
0x00, SD_DHCP6_OPTION_INF_MAX_RT, 0x00, SD_DHCP6_OPTION_SNTP_SERVERS,
/* Client ID */ /* Client ID */
0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e, 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
CLIENT_ID_BYTES, CLIENT_ID_BYTES,
@ -492,12 +490,11 @@ static const uint8_t msg_solicit[] = {
/* Vendor Options */ /* Vendor Options */
/* MUD URL */ /* MUD URL */
/* ORO */ /* ORO */
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0a, 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, SD_DHCP6_OPTION_DNS_SERVERS,
0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, SD_DHCP6_OPTION_DOMAIN_LIST,
0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, SD_DHCP6_OPTION_NTP_SERVER,
0x00, SD_DHCP6_OPTION_SOL_MAX_RT, 0x00, SD_DHCP6_OPTION_SNTP_SERVERS,
/* Client ID */ /* Client ID */
0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e, 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
CLIENT_ID_BYTES, CLIENT_ID_BYTES,
@ -557,10 +554,10 @@ static const uint8_t msg_request[] = {
/* MUD URL */ /* MUD URL */
/* ORO */ /* ORO */
0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08, 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, SD_DHCP6_OPTION_DNS_SERVERS,
0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, SD_DHCP6_OPTION_DOMAIN_LIST,
0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, SD_DHCP6_OPTION_NTP_SERVER,
0x00, SD_DHCP6_OPTION_SNTP_SERVERS,
/* Client ID */ /* Client ID */
0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e, 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
CLIENT_ID_BYTES, CLIENT_ID_BYTES,
@ -622,11 +619,11 @@ static const uint8_t msg_reply[] = {
0x40, /* prefixlen */ 0x40, /* prefixlen */
IA_PD_PREFIX1_BYTES, IA_PD_PREFIX1_BYTES,
/* DNS servers */ /* DNS servers */
0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20, 0x00, SD_DHCP6_OPTION_DNS_SERVERS, 0x00, 0x20,
DNS1_BYTES, DNS1_BYTES,
DNS2_BYTES, DNS2_BYTES,
/* SNTP servers */ /* SNTP servers */
0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20, 0x00, SD_DHCP6_OPTION_SNTP_SERVERS, 0x00, 0x20,
SNTP1_BYTES, SNTP1_BYTES,
SNTP2_BYTES, SNTP2_BYTES,
/* NTP servers */ /* NTP servers */
@ -641,7 +638,7 @@ static const uint8_t msg_reply[] = {
0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b, 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b,
0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00, 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
/* Domain list */ /* Domain list */
0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b, 0x00, SD_DHCP6_OPTION_DOMAIN_LIST, 0x00, 0x0b,
0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00, 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
/* Client FQDN */ /* Client FQDN */
0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12, 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
@ -701,11 +698,11 @@ static const uint8_t msg_advertise[] = {
0x40, /* prefixlen */ 0x40, /* prefixlen */
IA_PD_PREFIX1_BYTES, IA_PD_PREFIX1_BYTES,
/* DNS servers */ /* DNS servers */
0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20, 0x00, SD_DHCP6_OPTION_DNS_SERVERS, 0x00, 0x20,
DNS1_BYTES, DNS1_BYTES,
DNS2_BYTES, DNS2_BYTES,
/* SNTP servers */ /* SNTP servers */
0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20, 0x00, SD_DHCP6_OPTION_SNTP_SERVERS, 0x00, 0x20,
SNTP1_BYTES, SNTP1_BYTES,
SNTP2_BYTES, SNTP2_BYTES,
/* NTP servers */ /* NTP servers */
@ -720,7 +717,7 @@ static const uint8_t msg_advertise[] = {
0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b, 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b,
0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00, 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
/* Domain list */ /* Domain list */
0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b, 0x00, SD_DHCP6_OPTION_DOMAIN_LIST, 0x00, 0x0b,
0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00, 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
/* Client FQDN */ /* Client FQDN */
0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12, 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
@ -980,11 +977,6 @@ TEST(dhcp6_client) {
assert_se(sd_dhcp6_client_set_iaid(client, unaligned_read_be32((uint8_t[]) { IA_ID_BYTES })) >= 0); assert_se(sd_dhcp6_client_set_iaid(client, unaligned_read_be32((uint8_t[]) { IA_ID_BYTES })) >= 0);
dhcp6_client_set_test_mode(client, true); dhcp6_client_set_test_mode(client, true);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER) >= 0);
assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0); assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0);
assert_se(sd_dhcp6_client_set_callback(client, test_client_callback, NULL) >= 0); assert_se(sd_dhcp6_client_set_callback(client, test_client_callback, NULL) >= 0);

View File

@ -109,7 +109,6 @@ int device_set_devname(sd_device *device, const char *devname);
int device_set_devtype(sd_device *device, const char *devtype); int device_set_devtype(sd_device *device, const char *devtype);
int device_set_devnum(sd_device *device, const char *major, const char *minor); int device_set_devnum(sd_device *device, const char *major, const char *minor);
int device_set_subsystem(sd_device *device, const char *subsystem); int device_set_subsystem(sd_device *device, const char *subsystem);
int device_set_diskseq(sd_device *device, const char *str);
int device_set_drivers_subsystem(sd_device *device); int device_set_drivers_subsystem(sd_device *device);
int device_set_driver(sd_device *device, const char *driver); int device_set_driver(sd_device *device, const char *driver);
int device_set_usec_initialized(sd_device *device, usec_t when); int device_set_usec_initialized(sd_device *device, usec_t when);

View File

@ -255,6 +255,28 @@ static int device_set_seqnum(sd_device *device, const char *str) {
return 0; return 0;
} }
static int device_set_diskseq(sd_device *device, const char *str) {
uint64_t diskseq;
int r;
assert(device);
assert(str);
r = safe_atou64(str, &diskseq);
if (r < 0)
return r;
if (diskseq == 0)
return -EINVAL;
r = device_add_property_internal(device, "DISKSEQ", str);
if (r < 0)
return r;
device->diskseq = diskseq;
return 0;
}
static int device_amend(sd_device *device, const char *key, const char *value) { static int device_amend(sd_device *device, const char *key, const char *value) {
int r; int r;

View File

@ -570,34 +570,7 @@ int device_set_devnum(sd_device *device, const char *major, const char *minor) {
return 0; return 0;
} }
int device_set_diskseq(sd_device *device, const char *str) { static int handle_uevent_line(sd_device *device, const char *key, const char *value, const char **major, const char **minor) {
uint64_t diskseq;
int r;
assert(device);
assert(str);
r = safe_atou64(str, &diskseq);
if (r < 0)
return r;
if (diskseq == 0)
return -EINVAL;
r = device_add_property_internal(device, "DISKSEQ", str);
if (r < 0)
return r;
device->diskseq = diskseq;
return 0;
}
static int handle_uevent_line(
sd_device *device,
const char *key,
const char *value,
const char **major,
const char **minor) {
int r; int r;
assert(device); assert(device);
@ -622,10 +595,6 @@ static int handle_uevent_line(
r = device_set_devmode(device, value); r = device_set_devmode(device, value);
if (r < 0) if (r < 0)
return r; return r;
} else if (streq(key, "DISKSEQ")) {
r = device_set_diskseq(device, value);
if (r < 0)
return r;
} else if (streq(key, "MAJOR")) } else if (streq(key, "MAJOR"))
*major = value; *major = value;
else if (streq(key, "MINOR")) else if (streq(key, "MINOR"))
@ -1078,15 +1047,14 @@ _public_ int sd_device_get_driver(sd_device *device, const char **ret) {
return 0; return 0;
} }
_public_ int sd_device_get_devpath(sd_device *device, const char **ret) { _public_ int sd_device_get_devpath(sd_device *device, const char **devpath) {
assert_return(device, -EINVAL); assert_return(device, -EINVAL);
assert(device->devpath); assert(device->devpath);
assert(device->devpath[0] == '/'); assert(device->devpath[0] == '/');
if (ret) if (devpath)
*ret = device->devpath; *devpath = device->devpath;
return 0; return 0;
} }

View File

@ -3585,9 +3585,6 @@ fail:
(void) journal_file_close(f); (void) journal_file_close(f);
if (newly_created && fd < 0)
(void) unlink(fname);
return r; return r;
} }

View File

@ -622,29 +622,6 @@ static int dhcp6_configure(Link *link) {
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to set MUD URL: %m"); return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to set MUD URL: %m");
} }
if (link->network->dhcp6_use_dns) {
r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request DNS servers: %m");
}
if (link->network->dhcp6_use_domains > 0) {
r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request domains: %m");
}
if (link->network->dhcp6_use_ntp) {
r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request NTP servers: %m");
/* If the server does not provide NTP servers, then we fallback to use SNTP servers. */
r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to request SNTP servers: %m");
}
SET_FOREACH(request_options, link->network->dhcp6_request_options) { SET_FOREACH(request_options, link->network->dhcp6_request_options) {
uint32_t option = PTR_TO_UINT32(request_options); uint32_t option = PTR_TO_UINT32(request_options);

View File

@ -6,9 +6,7 @@ set -o pipefail
[[ -e /dev/loop-control ]] || exit 77 [[ -e /dev/loop-control ]] || exit 77
repart="${1:?}" repart="${1:?}"
udevadm="${2:?}"
test -x "$repart" test -x "$repart"
test -x "$udevadm"
PATH=$PATH:/sbin:/usr/sbin PATH=$PATH:/sbin:/usr/sbin
@ -201,7 +199,10 @@ $D/zzz7 : start= 6291416, size= 98304, type=0FC63DAF-8483-4772-8E79-3D
EOF EOF
LOOP="$(losetup -P --show --find "$D/zzz")" LOOP="$(losetup -P --show --find "$D/zzz")"
"${udevadm:?}" wait --timeout 60 --initialized=yes --settle "${LOOP:?}" while : ; do
test -e "$LOOP" && break
sleep .2
done
VOLUME="test-repart-$RANDOM" VOLUME="test-repart-$RANDOM"

View File

@ -459,8 +459,7 @@ static int condition_test_group(Condition *c, char **env) {
} }
static int condition_test_virtualization(Condition *c, char **env) { static int condition_test_virtualization(Condition *c, char **env) {
Virtualization v; int b, v;
int b;
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);
@ -476,7 +475,7 @@ static int condition_test_virtualization(Condition *c, char **env) {
/* First, compare with yes/no */ /* First, compare with yes/no */
b = parse_boolean(c->parameter); b = parse_boolean(c->parameter);
if (b >= 0) if (b >= 0)
return b == (v != VIRTUALIZATION_NONE); return b == !!v;
/* Then, compare categorization */ /* Then, compare categorization */
if (streq(c->parameter, "vm")) if (streq(c->parameter, "vm"))
@ -490,7 +489,7 @@ static int condition_test_virtualization(Condition *c, char **env) {
} }
static int condition_test_architecture(Condition *c, char **env) { static int condition_test_architecture(Condition *c, char **env) {
Architecture a, b; int a, b;
assert(c); assert(c);
assert(c->parameter); assert(c->parameter);

View File

@ -612,7 +612,7 @@ static void dissected_partition_done(DissectedPartition *p) {
*p = (DissectedPartition) { *p = (DissectedPartition) {
.partno = -1, .partno = -1,
.architecture = _ARCHITECTURE_INVALID, .architecture = -1
}; };
} }
@ -917,7 +917,7 @@ int dissect_image(
if (is_gpt) { if (is_gpt) {
PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID; PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID;
Architecture architecture = _ARCHITECTURE_INVALID; int architecture = _ARCHITECTURE_INVALID;
const char *stype, *sid, *fstype = NULL, *label; const char *stype, *sid, *fstype = NULL, *label;
sd_id128_t type_id, id; sd_id128_t type_id, id;
bool rw = true, growfs = false; bool rw = true, growfs = false;

View File

@ -21,7 +21,7 @@ struct DissectedPartition {
bool rw:1; bool rw:1;
bool growfs:1; bool growfs:1;
int partno; /* -1 if there was no partition and the images contains a file system directly */ int partno; /* -1 if there was no partition and the images contains a file system directly */
Architecture architecture; /* Intended architecture: either native, secondary or unset ARCHITECTURE_INVALID. */ int architecture; /* Intended architecture: either native, secondary or unset (-1). */
sd_id128_t uuid; /* Partition entry UUID as reported by the GPT */ sd_id128_t uuid; /* Partition entry UUID as reported by the GPT */
char *fstype; char *fstype;
char *node; char *node;

View File

@ -65,25 +65,14 @@ const GptPartitionType gpt_partition_type_table[] = {
{} {}
}; };
static const GptPartitionType *gpt_partition_type_find_by_uuid(sd_id128_t id) { const char *gpt_partition_type_uuid_to_string(sd_id128_t id) {
for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++) for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++)
if (sd_id128_equal(id, gpt_partition_type_table[i].uuid)) if (sd_id128_equal(id, gpt_partition_type_table[i].uuid))
return gpt_partition_type_table + i; return gpt_partition_type_table[i].name;
return NULL; return NULL;
} }
const char *gpt_partition_type_uuid_to_string(sd_id128_t id) {
const GptPartitionType *pt;
pt = gpt_partition_type_find_by_uuid(id);
if (!pt)
return NULL;
return pt->name;
}
const char *gpt_partition_type_uuid_to_string_harder( const char *gpt_partition_type_uuid_to_string_harder(
sd_id128_t id, sd_id128_t id,
char buffer[static SD_ID128_UUID_STRING_MAX]) { char buffer[static SD_ID128_UUID_STRING_MAX]) {
@ -113,13 +102,11 @@ 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) {
const GptPartitionType *pt; for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++)
if (sd_id128_equal(id, gpt_partition_type_table[i].uuid))
return gpt_partition_type_table[i].arch;
pt = gpt_partition_type_find_by_uuid(id);
if (!pt)
return _ARCHITECTURE_INVALID; return _ARCHITECTURE_INVALID;
return pt->arch;
} }
int gpt_partition_label_valid(const char *s) { int gpt_partition_label_valid(const char *s) {
@ -133,11 +120,9 @@ int gpt_partition_label_valid(const char *s) {
} }
static GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) { static GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) {
const GptPartitionType *pt; for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++)
if (sd_id128_equal(id, gpt_partition_type_table[i].uuid))
pt = gpt_partition_type_find_by_uuid(id); return gpt_partition_type_table[i];
if (pt)
return *pt;
return (GptPartitionType) { .uuid = id, .arch = _ARCHITECTURE_INVALID }; return (GptPartitionType) { .uuid = id, .arch = _ARCHITECTURE_INVALID };
} }

View File

@ -134,7 +134,7 @@ enum {
SD_DHCP_OPTION_NDS_SERVER = 85, /* [RFC2241] */ SD_DHCP_OPTION_NDS_SERVER = 85, /* [RFC2241] */
SD_DHCP_OPTION_NDS_TREE_NAME = 86, /* [RFC2241] */ SD_DHCP_OPTION_NDS_TREE_NAME = 86, /* [RFC2241] */
SD_DHCP_OPTION_NDS_CONTEXT = 87, /* [RFC2241] */ SD_DHCP_OPTION_NDS_CONTEXT = 87, /* [RFC2241] */
SD_DHCP_OPTION_BCMCS_CONTROLLER_DOMAIN_NAME = 88, /* [RFC4280] */ SD_DHCP_OPTION_BCMCS_CONTROLLER_DOMAIN_NAM = 88, /* [RFC4280] */
SD_DHCP_OPTION_BCMCS_CONTROLLER_ADDRESS = 89, /* [RFC4280] */ SD_DHCP_OPTION_BCMCS_CONTROLLER_ADDRESS = 89, /* [RFC4280] */
SD_DHCP_OPTION_AUTHENTICATION = 90, /* [RFC3118] */ SD_DHCP_OPTION_AUTHENTICATION = 90, /* [RFC3118] */
SD_DHCP_OPTION_CLIENT_LAST_TRANSACTION_TIME = 91, /* [RFC4388] */ SD_DHCP_OPTION_CLIENT_LAST_TRANSACTION_TIME = 91, /* [RFC4388] */
@ -173,7 +173,7 @@ enum {
SD_DHCP_OPTION_CAPWAP_AC_ADDRESS = 138, /* [RFC5417] */ SD_DHCP_OPTION_CAPWAP_AC_ADDRESS = 138, /* [RFC5417] */
SD_DHCP_OPTION_MOS_ADDRESS = 139, /* [RFC5678] */ SD_DHCP_OPTION_MOS_ADDRESS = 139, /* [RFC5678] */
SD_DHCP_OPTION_MOS_FQDN = 140, /* [RFC5678] */ SD_DHCP_OPTION_MOS_FQDN = 140, /* [RFC5678] */
SD_DHCP_OPTION_SIP_SERVICE_DOMAIN = 141, /* [RFC6011] */ SD_DHCP_OPTION_SIP_SERVICE_DOMAINS = 141, /* [RFC6011] */
SD_DHCP_OPTION_ANDSF_ADDRESS = 142, /* [RFC6153] */ SD_DHCP_OPTION_ANDSF_ADDRESS = 142, /* [RFC6153] */
SD_DHCP_OPTION_SZTP_REDIRECT = 143, /* [RFC8572] */ SD_DHCP_OPTION_SZTP_REDIRECT = 143, /* [RFC8572] */
SD_DHCP_OPTION_GEOLOC = 144, /* [RFC6225] */ SD_DHCP_OPTION_GEOLOC = 144, /* [RFC6225] */

View File

@ -63,15 +63,15 @@ enum {
SD_DHCP6_OPTION_RECONF_ACCEPT = 20, /* RFC 8415 */ SD_DHCP6_OPTION_RECONF_ACCEPT = 20, /* RFC 8415 */
SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME = 21, /* RFC 3319 */ SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME = 21, /* RFC 3319 */
SD_DHCP6_OPTION_SIP_SERVER_ADDRESS = 22, /* RFC 3319 */ SD_DHCP6_OPTION_SIP_SERVER_ADDRESS = 22, /* RFC 3319 */
SD_DHCP6_OPTION_DNS_SERVER = 23, /* RFC 3646 */ SD_DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */
SD_DHCP6_OPTION_DOMAIN = 24, /* RFC 3646 */ SD_DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */
SD_DHCP6_OPTION_IA_PD = 25, /* RFC 3633, RFC 8415 */ SD_DHCP6_OPTION_IA_PD = 25, /* RFC 3633, RFC 8415 */
SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, RFC 8415 */ SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, RFC 8415 */
SD_DHCP6_OPTION_NIS_SERVER = 27, /* RFC 3898 */ SD_DHCP6_OPTION_NIS_SERVERS = 27, /* RFC 3898 */
SD_DHCP6_OPTION_NISP_SERVER = 28, /* RFC 3898 */ SD_DHCP6_OPTION_NISP_SERVERS = 28, /* RFC 3898 */
SD_DHCP6_OPTION_NIS_DOMAIN_NAME = 29, /* RFC 3898 */ SD_DHCP6_OPTION_NIS_DOMAIN_NAME = 29, /* RFC 3898 */
SD_DHCP6_OPTION_NISP_DOMAIN_NAME = 30, /* RFC 3898 */ SD_DHCP6_OPTION_NISP_DOMAIN_NAME = 30, /* RFC 3898 */
SD_DHCP6_OPTION_SNTP_SERVER = 31, /* RFC 4075, deprecated */ SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */
SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 4242, 8415, sec. 21.23 */ SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 4242, 8415, sec. 21.23 */
SD_DHCP6_OPTION_BCMCS_SERVER_D = 33, /* RFC 4280 */ SD_DHCP6_OPTION_BCMCS_SERVER_D = 33, /* RFC 4280 */
SD_DHCP6_OPTION_BCMCS_SERVER_A = 34, /* RFC 4280 */ SD_DHCP6_OPTION_BCMCS_SERVER_A = 34, /* RFC 4280 */

View File

@ -1,15 +1,13 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "architecture.h" #include "architecture.h"
#include "errno-util.h"
#include "log.h" #include "log.h"
#include "tests.h" #include "tests.h"
#include "util.h" #include "util.h"
#include "virt.h" #include "virt.h"
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
Virtualization v; int a, v;
Architecture a;
const char *p; const char *p;
test_setup_logging(LOG_INFO); test_setup_logging(LOG_INFO);
@ -22,7 +20,7 @@ int main(int argc, char *argv[]) {
assert_se(architecture_from_string(architecture_to_string(1)) == 1); assert_se(architecture_from_string(architecture_to_string(1)) == 1);
v = detect_virtualization(); v = detect_virtualization();
if (v < 0 && ERRNO_IS_PRIVILEGE(v)) if (IN_SET(v, -EPERM, -EACCES))
return log_tests_skipped("Cannot detect virtualization"); return log_tests_skipped("Cannot detect virtualization");
assert_se(v >= 0); assert_se(v >= 0);

View File

@ -15,11 +15,10 @@
#include <unistd.h> #include <unistd.h>
#include "barrier.h" #include "barrier.h"
#include "errno-util.h"
#include "tests.h"
#include "time-util.h"
#include "util.h" #include "util.h"
#include "tests.h"
#include "virt.h" #include "virt.h"
#include "time-util.h"
/* 20ms to test deadlocks; All timings use multiples of this constant as /* 20ms to test deadlocks; All timings use multiples of this constant as
* alarm/sleep timers. If this timeout is too small for slow machines to perform * alarm/sleep timers. If this timeout is too small for slow machines to perform
@ -435,8 +434,8 @@ static int intro(void) {
* false-positives in CIs. * false-positives in CIs.
*/ */
Virtualization v = detect_virtualization(); int v = detect_virtualization();
if (v < 0 && ERRNO_IS_PRIVILEGE(v)) if (IN_SET(v, -EPERM, -EACCES))
return log_tests_skipped("Cannot detect virtualization"); return log_tests_skipped("Cannot detect virtualization");
if (v != VIRTUALIZATION_NONE) if (v != VIRTUALIZATION_NONE)

View File

@ -276,7 +276,7 @@ TEST(condition_test_host) {
TEST(condition_test_architecture) { TEST(condition_test_architecture) {
Condition *condition; Condition *condition;
const char *sa; const char *sa;
Architecture a; int a;
a = uname_architecture(); a = uname_architecture();
assert_se(a >= 0); assert_se(a >= 0);

View File

@ -17,7 +17,7 @@ TEST(gpt_types_against_architectures) {
* types. Also validates whether we can properly categorize the entries. */ * types. Also validates whether we can properly categorize the entries. */
FOREACH_STRING(prefix, "root-", "usr-") FOREACH_STRING(prefix, "root-", "usr-")
for (Architecture a = 0; a < _ARCHITECTURE_MAX; a++) for (int a = 0; a < _ARCHITECTURE_MAX; a++)
FOREACH_STRING(suffix, "", "-verity", "-verity-sig") { FOREACH_STRING(suffix, "", "-verity", "-verity-sig") {
_cleanup_free_ char *joined = NULL; _cleanup_free_ char *joined = NULL;
sd_id128_t id; sd_id128_t id;

View File

@ -121,7 +121,6 @@ int main(int argc, char **argv) {
test_table(unit_file_state, UNIT_FILE_STATE); test_table(unit_file_state, UNIT_FILE_STATE);
test_table(unit_load_state, UNIT_LOAD_STATE); test_table(unit_load_state, UNIT_LOAD_STATE);
test_table(unit_type, UNIT_TYPE); test_table(unit_type, UNIT_TYPE);
test_table(virtualization, VIRTUALIZATION);
test_table_sparse(object_compressed, OBJECT_COMPRESSED); test_table_sparse(object_compressed, OBJECT_COMPRESSED);

View File

@ -6,7 +6,6 @@ udevadm_sources = files(
'udevadm-control.c', 'udevadm-control.c',
'udevadm-hwdb.c', 'udevadm-hwdb.c',
'udevadm-info.c', 'udevadm-info.c',
'udevadm-lock.c',
'udevadm-monitor.c', 'udevadm-monitor.c',
'udevadm-settle.c', 'udevadm-settle.c',
'udevadm-test.c', 'udevadm-test.c',

View File

@ -22,10 +22,9 @@
#include "static-destruct.h" #include "static-destruct.h"
#include "string-table.h" #include "string-table.h"
#include "string-util.h" #include "string-util.h"
#include "terminal-util.h"
#include "udev-util.h" #include "udev-util.h"
#include "udevadm.h"
#include "udevadm-util.h" #include "udevadm-util.h"
#include "udevadm.h"
typedef enum ActionType { typedef enum ActionType {
ACTION_QUERY, ACTION_QUERY,
@ -172,72 +171,26 @@ static int print_device_chain(sd_device *device) {
} }
static int print_record(sd_device *device) { static int print_record(sd_device *device) {
const char *str, *val, *subsys; const char *str, *val;
dev_t devnum; int i;
uint64_t q;
int i, ifi;
assert(device); assert(device);
/* We don't show syspath here, because it's identical to devpath (modulo the "/sys" prefix). (void) sd_device_get_devpath(device, &str);
* printf("P: %s\n", str);
* We don't show action/seqnum here because that only makes sense for records synthesized from
* uevents, not for those synthesized from database entries.
*
* We don't show sysattrs here, because they can be expensive and potentially issue expensive driver
* IO.
*
* Coloring: let's be conservative with coloring. Let's use it to group related fields. Right now:
*
* white for fields that give the device a name
* green for fields that categorize the device into subsystem/devtype and similar
* cyan for fields about associated device nodes/symlinks/network interfaces and such
* magenta for block device diskseq
* yellow for driver info
* no color for regular properties */
assert_se(sd_device_get_devpath(device, &str) >= 0);
printf("P: %s%s%s\n", ansi_highlight_white(), str, ansi_normal());
if (sd_device_get_sysname(device, &str) >= 0)
printf("M: %s%s%s\n", ansi_highlight_white(), str, ansi_normal());
if (sd_device_get_sysnum(device, &str) >= 0)
printf("R: %s%s%s\n", ansi_highlight_white(), str, ansi_normal());
if (sd_device_get_subsystem(device, &subsys) >= 0)
printf("U: %s%s%s\n", ansi_highlight_green(), subsys, ansi_normal());
if (sd_device_get_devtype(device, &str) >= 0)
printf("T: %s%s%s\n", ansi_highlight_green(), str, ansi_normal());
if (sd_device_get_devnum(device, &devnum) >= 0)
printf("D: %s%c %u:%u%s\n",
ansi_highlight_cyan(),
streq_ptr(subsys, "block") ? 'b' : 'c', major(devnum), minor(devnum),
ansi_normal());
if (sd_device_get_ifindex(device, &ifi) >= 0)
printf("I: %s%i%s\n", ansi_highlight_cyan(), ifi, ansi_normal());
if (sd_device_get_devname(device, &str) >= 0) { if (sd_device_get_devname(device, &str) >= 0) {
assert_se(val = path_startswith(str, "/dev/")); assert_se(val = path_startswith(str, "/dev/"));
printf("N: %s%s%s\n", ansi_highlight_cyan(), val, ansi_normal()); printf("N: %s\n", val);
}
if (device_get_devlink_priority(device, &i) >= 0) if (device_get_devlink_priority(device, &i) >= 0)
printf("L: %s%i%s\n", ansi_highlight_cyan(), i, ansi_normal()); printf("L: %i\n", i);
FOREACH_DEVICE_DEVLINK(device, str) { FOREACH_DEVICE_DEVLINK(device, str) {
assert_se(val = path_startswith(str, "/dev/")); assert_se(val = path_startswith(str, "/dev/"));
printf("S: %s%s%s\n", ansi_highlight_cyan(), val, ansi_normal()); printf("S: %s\n", val);
} }
}
if (sd_device_get_diskseq(device, &q) >= 0)
printf("Q: %s%" PRIu64 "%s\n", ansi_highlight_magenta(), q, ansi_normal());
if (sd_device_get_driver(device, &str) >= 0)
printf("V: %s%s%s\n", ansi_highlight_yellow4(), str, ansi_normal());
FOREACH_DEVICE_PROPERTY(device, str, val) FOREACH_DEVICE_PROPERTY(device, str, val)
printf("E: %s=%s\n", str, val); printf("E: %s=%s\n", str, val);
@ -489,7 +442,7 @@ static int help(void) {
int info_main(int argc, char *argv[], void *userdata) { int info_main(int argc, char *argv[], void *userdata) {
_cleanup_strv_free_ char **devices = NULL; _cleanup_strv_free_ char **devices = NULL;
_cleanup_free_ char *name = NULL; _cleanup_free_ char *name = NULL;
int c, r, ret; int c, r;
enum { enum {
ARG_PROPERTY = 0x100, ARG_PROPERTY = 0x100,
@ -631,21 +584,14 @@ int info_main(int argc, char *argv[], void *userdata) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"-x/--export or -P/--export-prefix cannot be used with --value"); "-x/--export or -P/--export-prefix cannot be used with --value");
ret = 0;
STRV_FOREACH(p, devices) { STRV_FOREACH(p, devices) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL; _cleanup_(sd_device_unrefp) sd_device *device = NULL;
r = find_device(*p, NULL, &device); r = find_device(*p, NULL, &device);
if (r < 0) {
if (r == -EINVAL) if (r == -EINVAL)
log_error_errno(r, "Bad argument \"%s\", expected an absolute path in /dev/ or /sys/ or a unit name: %m", *p); return log_error_errno(r, "Bad argument \"%s\", expected an absolute path in /dev/ or /sys or a unit name: %m", *p);
else if (r < 0)
log_error_errno(r, "Unknown device \"%s\": %m", *p); return log_error_errno(r, "Unknown device \"%s\": %m", *p);
if (ret == 0)
ret = r;
continue;
}
if (arg_wait_for_initialization_timeout > 0) { if (arg_wait_for_initialization_timeout > 0) {
sd_device *d; sd_device *d;
@ -672,5 +618,5 @@ int info_main(int argc, char *argv[], void *userdata) {
return r; return r;
} }
return ret; return 0;
} }

View File

@ -1,399 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <getopt.h>
#include <stdlib.h>
#include <sys/file.h>
#include <unistd.h>
#include "blockdev-util.h"
#include "btrfs-util.h"
#include "fd-util.h"
#include "fdset.h"
#include "main-func.h"
#include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "signal-util.h"
#include "sort-util.h"
#include "stat-util.h"
#include "strv.h"
#include "time-util.h"
#include "udevadm.h"
static usec_t arg_timeout_usec = USEC_INFINITY;
static char **arg_devices = NULL;
static char **arg_backing = NULL;
static char **arg_cmdline = NULL;
static bool arg_print = false;
STATIC_DESTRUCTOR_REGISTER(arg_devices, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_backing, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_cmdline, strv_freep);
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
r = terminal_urlify_man("udevadm", "8", &link);
if (r < 0)
return log_oom();
printf("%s [OPTIONS...] COMMAND\n"
"%s [OPTIONS...] --print\n"
"\n%sLock a block device and run a comand.%s\n\n"
" -h --help Print this message\n"
" -V --version Print version of the program\n"
" -d --device=DEVICE Block device to lock\n"
" -b --backing=FILE File whose backing block device to lock\n"
" -t --timeout=SECS Block at most the specified time waiting for lock\n"
" -p --print Only show which block device the lock would be taken on\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
program_invocation_short_name,
ansi_highlight(),
ansi_normal(),
link);
return 0;
}
static int parse_argv(int argc, char *argv[]) {
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "device", required_argument, NULL, 'd' },
{ "backing", required_argument, NULL, 'b' },
{ "timeout", required_argument, NULL, 't' },
{ "print", no_argument, NULL, 'p' },
{}
};
int c, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, arg_print ? "hVd:b:t:p" : "+hVd:b:t:p", options, NULL)) >= 0)
switch (c) {
case 'h':
return help();
case 'V':
return print_version();
case 'd':
case 'b': {
_cleanup_free_ char *s = NULL;
char ***l = c == 'd' ? &arg_devices : &arg_backing;
r = path_make_absolute_cwd(optarg, &s);
if (r < 0)
return log_error_errno(r, "Failed to make path '%s' absolute: %m", optarg);
path_simplify(s);
if (strv_consume(l, TAKE_PTR(s)) < 0)
return log_oom();
strv_uniq(*l);
break;
}
case 't':
r = parse_sec(optarg, &arg_timeout_usec);
if (r < 0)
return log_error_errno(r, "Failed to parse --timeout= parameter: %s", optarg);
break;
case 'p':
arg_print = true;
break;
case '?':
return -EINVAL;
default:
assert_not_reached();
}
if (arg_print) {
if (optind != argc)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No arguments expected");
} else {
if (optind + 1 > argc)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too few arguments, command to execute.");
arg_cmdline = strv_copy(argv + optind);
if (!arg_cmdline)
return log_oom();
}
if (strv_isempty(arg_devices) && strv_isempty(arg_backing))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No devices to lock specified, refusing.");
return 1;
}
static int find_devno(
dev_t **devnos,
size_t *n_devnos,
const char *device,
bool backing) {
dev_t devt, whole_devt;
struct stat st;
int r;
assert(devnos);
assert(n_devnos);
assert(*devnos || *n_devnos == 0);
assert(device);
if (stat(device, &st) < 0)
return log_error_errno(errno, "Failed to stat '%s': %m", device);
if (S_ISBLK(st.st_mode))
devt = st.st_rdev;
else if (!backing)
return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Not a block device: %s", device);
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Not a block device, regular file or directory: %s", device);
else if (major(st.st_dev) != 0)
devt = st.st_dev;
else {
_cleanup_close_ int regfd = -1;
struct stat st2;
/* If major(st.st_dev) is zero, this might mean we are backed by btrfs, which needs special
* handing, to get the backing device node. */
regfd = open(device, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (regfd < 0)
return log_error_errno(errno, "Failed to open '%s': %m", device);
/* Extra safety: let's check we are still looking at the same file */
if (fstat(regfd, &st2) < 0)
return log_error_errno(errno, "Failed to stat '%s': %m", device);
if (!stat_inode_same(&st, &st2))
return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "File '%s' was replaced while we were looking at it.", device);
r = btrfs_get_block_device_fd(regfd, &devt);
if (r == -ENOTTY)
return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Path '%s' not backed by block device.", device);
if (r < 0)
return log_error_errno(r, "Failed to acquire btrfs backing device of '%s': %m", device);
}
r = block_get_whole_disk(devt, &whole_devt);
if (r < 0)
return log_error_errno(r, "Failed to find whole block device for '%s': %m", device);
if (typesafe_bsearch(&whole_devt, *devnos, *n_devnos, devt_compare_func)) {
log_debug("Device %u:%u already listed for locking, ignoring.", major(whole_devt), minor(whole_devt));
return 0;
}
if (!GREEDY_REALLOC(*devnos, *n_devnos + 1))
return log_oom();
(*devnos)[(*n_devnos)++] = whole_devt;
/* Immediately sort again, to ensure the binary search above will work for the next device we add */
typesafe_qsort(*devnos, *n_devnos, devt_compare_func);
return 1;
}
static int lock_device(
const char *path,
dev_t devno,
usec_t deadline) {
_cleanup_close_ int fd = -1;
struct stat st;
int r;
fd = open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return log_error_errno(errno, "Failed to open '%s': %m", path);
if (fstat(fd, &st) < 0)
return log_error_errno(errno, "Failed to stat '%s': %m", path);
/* Extra safety: check that the device still refers to what we think it refers to */
if (!S_ISBLK(st.st_mode) || st.st_rdev != devno)
return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Path '%s' no longer refers to specified block device %u:%u: %m", path, major(devno), minor(devno));
if (flock(fd, LOCK_EX|LOCK_NB) < 0) {
if (errno != EAGAIN)
return log_error_errno(errno, "Failed to lock device '%s': %m", path);
if (deadline == 0)
return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Device '%s' is currently locked.", path);
if (deadline == USEC_INFINITY) {
log_info("Device '%s' is currently locked, waiting…", path);
if (flock(fd, LOCK_EX) < 0)
return log_error_errno(errno, "Failed to lock device '%s': %m", path);
} else {
_cleanup_(sigkill_waitp) pid_t flock_pid = 0;
/* flock() doesn't support a time-out. Let's fake one then. The traditional way to do
* this is via alarm()/setitimer()/timer_create(), but that's racy, given that the
* SIGALRM might aleady fire between the alarm() and the flock() in which case the
* flock() is never cancelled and we lock up (this is a short time window, but with
* short timeouts on a loaded machine we might run into it, who knows?). Let's
* instead do the lock out-of-process: fork off a child that does the locking, and
* that we'll wait on and kill if it takes too long. */
log_info("Device '%s' is currently locked, waiting %s…",
path, FORMAT_TIMESPAN(usec_sub_unsigned(deadline, now(CLOCK_MONOTONIC)), 0));
BLOCK_SIGNALS(SIGCHLD);
r = safe_fork("(timed-flock)", FORK_DEATHSIG|FORK_LOG, &flock_pid);
if (r < 0)
return r;
if (r == 0) {
/* Child */
if (flock(fd, LOCK_EX) < 0) {
log_error_errno(errno, "Failed to lock device '%s': %m", path);
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
for (;;) {
siginfo_t si;
sigset_t ss;
usec_t n;
assert(sigemptyset(&ss) >= 0);
assert(sigaddset(&ss, SIGCHLD) >= 0);
n = now(CLOCK_MONOTONIC);
if (n >= deadline)
return log_error_errno(SYNTHETIC_ERRNO(ETIMEDOUT), "Timeout reached.");
r = sigtimedwait(&ss, NULL, TIMESPEC_STORE(deadline - n));
if (r < 0) {
if (errno != EAGAIN)
return log_error_errno(errno, "Failed to wait for SIGCHLD: %m");
return log_error_errno(SYNTHETIC_ERRNO(ETIMEDOUT), "Timeout reached.");
}
assert(r == SIGCHLD);
zero(si);
if (waitid(P_PID, flock_pid, &si, WEXITED|WNOHANG|WNOWAIT) < 0)
return log_error_errno(errno, "Failed to wait for child: %m");
if (si.si_pid != 0) {
assert(si.si_pid == flock_pid);
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
return log_error_errno(SYNTHETIC_ERRNO(EPROTO), "Unexpected exit status of file lock child.");
break;
}
log_debug("Got SIGCHLD for other child, continuing.");
}
}
}
log_debug("Successfully locked %s (%u:%u)…", path, major(devno), minor(devno));
return TAKE_FD(fd);
}
int lock_main(int argc, char *argv[], void *userdata) {
_cleanup_(fdset_freep) FDSet *fds = NULL;
_cleanup_free_ dev_t *devnos = NULL;
size_t n_devnos = 0;
usec_t deadline;
pid_t pid;
int r;
r = parse_argv(argc, argv);
if (r <= 0)
return r;
STRV_FOREACH(i, arg_devices) {
r = find_devno(&devnos, &n_devnos, *i, /* backing= */ false);
if (r < 0)
return r;
}
STRV_FOREACH(i, arg_backing) {
r = find_devno(&devnos, &n_devnos, *i, /* backing= */ true);
if (r < 0)
return r;
}
assert(n_devnos > 0);
fds = fdset_new();
if (!fds)
return log_oom();
if (IN_SET(arg_timeout_usec, 0, USEC_INFINITY))
deadline = arg_timeout_usec;
else
deadline = usec_add(now(CLOCK_MONOTONIC), arg_timeout_usec);
for (size_t i = 0; i < n_devnos; i++) {
_cleanup_free_ char *node = NULL;
r = device_path_make_canonical(S_IFBLK, devnos[i], &node);
if (r < 0)
return log_error_errno(r, "Failed to format block device path: %m");
if (arg_print)
printf("%s\n", node);
else {
_cleanup_close_ int fd = -1;
fd = lock_device(node, devnos[i], deadline);
if (fd < 0)
return fd;
r = fdset_put(fds, fd);
if (r < 0)
return log_oom();
TAKE_FD(fd);
}
}
if (arg_print)
return EXIT_SUCCESS;
/* Ignore SIGINT and allow the forked process to receive it */
(void) ignore_signals(SIGINT);
r = safe_fork("(lock)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
/* Child */
execvp(arg_cmdline[0], arg_cmdline);
log_open();
log_error_errno(errno, "Failed to execute %s: %m", arg_cmdline[0]);
_exit(EXIT_FAILURE);
}
return wait_for_terminate_and_check(arg_cmdline[0], pid, 0);
}

View File

@ -27,7 +27,6 @@ static int help(void) {
{ "test", "Test an event run" }, { "test", "Test an event run" },
{ "test-builtin", "Test a built-in command" }, { "test-builtin", "Test a built-in command" },
{ "wait", "Wait for device or device symlink" }, { "wait", "Wait for device or device symlink" },
{ "lock", "Lock a block device" },
}; };
_cleanup_free_ char *link = NULL; _cleanup_free_ char *link = NULL;
@ -104,7 +103,6 @@ static int udevadm_main(int argc, char *argv[]) {
{ "test", VERB_ANY, VERB_ANY, 0, test_main }, { "test", VERB_ANY, VERB_ANY, 0, test_main },
{ "test-builtin", VERB_ANY, VERB_ANY, 0, builtin_main }, { "test-builtin", VERB_ANY, VERB_ANY, 0, builtin_main },
{ "wait", VERB_ANY, VERB_ANY, 0, wait_main }, { "wait", VERB_ANY, VERB_ANY, 0, wait_main },
{ "lock", VERB_ANY, VERB_ANY, 0, lock_main },
{ "version", VERB_ANY, VERB_ANY, 0, version_main }, { "version", VERB_ANY, VERB_ANY, 0, version_main },
{ "help", VERB_ANY, VERB_ANY, 0, help_main }, { "help", VERB_ANY, VERB_ANY, 0, help_main },
{} {}

View File

@ -14,7 +14,6 @@ int hwdb_main(int argc, char *argv[], void *userdata);
int test_main(int argc, char *argv[], void *userdata); int test_main(int argc, char *argv[], void *userdata);
int builtin_main(int argc, char *argv[], void *userdata); int builtin_main(int argc, char *argv[], void *userdata);
int wait_main(int argc, char *argv[], void *userdata); int wait_main(int argc, char *argv[], void *userdata);
int lock_main(int argc, char *argv[], void *userdata);
static inline int print_version(void) { static inline int print_version(void) {
/* Dracut relies on the version being a single integer */ /* Dracut relies on the version being a single integer */

View File

@ -174,7 +174,10 @@ rm -r /tmp/testsuite-58.3-defs/
mkdir -p /tmp/testsuite-58-issue-21817-defs/ mkdir -p /tmp/testsuite-58-issue-21817-defs/
truncate -s 100m /var/tmp/testsuite-58-issue-21817.img truncate -s 100m /var/tmp/testsuite-58-issue-21817.img
LOOP=$(losetup -P --show -f /var/tmp/testsuite-58-issue-21817.img) LOOP=$(losetup -P --show -f /var/tmp/testsuite-58-issue-21817.img)
udevadm wait --timeout 60 --initialized=yes --settle "${LOOP:?}" while : ; do
test -e "$LOOP" && break
sleep .2
done
printf 'size=50M,type=%s\n,\n' "${root_guid}" | sfdisk -X gpt "$LOOP" printf 'size=50M,type=%s\n,\n' "${root_guid}" | sfdisk -X gpt "$LOOP"
cat >/tmp/testsuite-58-issue-21817-defs/test.conf <<EOF cat >/tmp/testsuite-58-issue-21817-defs/test.conf <<EOF
[Partition] [Partition]
@ -216,7 +219,10 @@ EOF
truncate -s 100m "/tmp/testsuite-58-sector-$1.img" truncate -s 100m "/tmp/testsuite-58-sector-$1.img"
LOOP=$(losetup -b "$1" -P --show -f "/tmp/testsuite-58-sector-$1.img" ) LOOP=$(losetup -b "$1" -P --show -f "/tmp/testsuite-58-sector-$1.img" )
udevadm wait --timeout 60 --initialized=yes --settle "${LOOP:?}" while : ; do
test -e "$LOOP" && break
sleep .2
done
systemd-repart --pretty=yes --definitions=/tmp/testsuite-58-sector/ --seed=750b6cd5c4ae4012a15e7be3c29e6a47 --empty=require --dry-run=no "$LOOP" systemd-repart --pretty=yes --definitions=/tmp/testsuite-58-sector/ --seed=750b6cd5c4ae4012a15e7be3c29e6a47 --empty=require --dry-run=no "$LOOP"
rm -rf /tmp/testsuite-58-sector rm -rf /tmp/testsuite-58-sector
sfdisk --verify "$LOOP" sfdisk --verify "$LOOP"