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.
f379362157
...
e4f92a62a8
5
TODO
5
TODO
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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',
|
||||||
|
|||||||
@ -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 <systemd/sd-device.h></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>
|
|
||||||
148
man/udevadm.xml
148
man/udevadm.xml
@ -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>
|
||||||
|
|||||||
45
meson.build
45
meson.build
@ -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',
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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_;
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
212
src/basic/virt.c
212
src/basic/virt.c
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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");
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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"
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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 };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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] */
|
||||||
|
|||||||
@ -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 */
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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',
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
@ -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 },
|
||||||
{}
|
{}
|
||||||
|
|||||||
@ -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 */
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user