1
0
mirror of https://github.com/systemd/systemd synced 2026-04-23 07:24:51 +02:00

Compare commits

..

12 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek
9b01798b98 basic/strv: avoid potential UB with references to array[-1]
"""
Given an array a[N] of N elements of type T:
- Forming a pointer &a[i] (or a + i) with 0 ≤ i ≤ N is safe.
- Forming a pointer &a[i] with i < 0 or i > N causes undefined behavior.
- Dereferencing a pointer &a[i] with 0 ≤ i < N is safe.
- Dereferencing a pointer &a[i] with i < 0 or i ≥ N causes undefined behavior.
"""

As pointed by by @medhefgo, here we were forming a pointer to a[-1]. a itself
wasn't NULL, so a > 0, and a-1 was also >= 0, and this didn't seem to cause any
problems. But it's better to be formally correct, especially if we move the
code to src/fundamental/ later on and compile it differently.

Compilation shows no size change (with -O0 -g) on build/systemd, so this should
have no effect whatsoever.
2022-03-21 13:48:00 +01:00
Zbigniew Jędrzejewski-Szmek
e7949be790 Drop unused variables to fix build
This is a merge conflict between #22740 and #20156.
2022-03-21 13:30:42 +01:00
Zbigniew Jędrzejewski-Szmek
7ff9846956
Merge pull request #20156 from poettering/sysupdate
new "systemd-sysupdate" component
2022-03-21 12:06:48 +01:00
Zbigniew Jędrzejewski-Szmek
b0a5e59622
Merge pull request #22740 from yuwata/list
tree-wide: declare iterator of LIST_FOREACH() in the loop
2022-03-21 10:52:03 +01:00
Yu Watanabe
de010b0b2e strv: make iterator in STRV_FOREACH() declaread in the loop
This also avoids multiple evaluations in STRV_FOREACH_BACKWARDS()
2022-03-19 08:33:33 +09:00
Lennart Poettering
178d3ff2aa update TODO 2022-03-19 00:14:55 +01:00
Lennart Poettering
7910ec3bcd test: add integration test for sysupdate 2022-03-19 00:13:55 +01:00
Lennart Poettering
436aa3b16f man: add sysupdate documentation 2022-03-19 00:13:55 +01:00
Lennart Poettering
4a05d7ed72 unit: add units for new "systemd-sysupdate" tool
These unit (if enabled) will try to update the OS in regular intervals.
Moreover, every day in the early morning this will attempt to reboot the
system if there's a newer version installed than running.
2022-03-19 00:13:55 +01:00
Lennart Poettering
43cc7a3ef4 sysupdate: add new component "sysupdate" 2022-03-19 00:13:55 +01:00
Yu Watanabe
80a226b26b list: make LIST_FOREACH() and LIST_FOREACH_BACKWARDS() safer 2022-03-19 08:10:29 +09:00
Yu Watanabe
03677889f0 list: declare iterator of LIST_FOREACH() in the loop 2022-03-19 08:10:29 +09:00
292 changed files with 6771 additions and 1192 deletions

17
TODO
View File

@ -251,11 +251,26 @@ Features:
that images cannot be misused.
* New udev block device symlink names:
/dev/disk/by-parttypelabel/<pttype>/<ptlabel>. Use case: if pt label is used
/dev/disk/by-parttypelabel/<pttype>-<ptlabel>. Use case: if pt label is used
as partition image version string, this is a safe way to reference a specific
version of a specific partition type, in particular where related partitions
are processed (e.g. verity + rootfs both named "LennartOS_0.7").
* sysupdate:
- add fuzzing to the pattern parser
- support casync as download mechanism
- direct TPM2 PCR change handling, possible renrolling LUKS2 media if needed.
- "systemd-sysupdate update --all" support, that iterates through all components
defined on the host, plus all images installed into /var/lib/machines/,
/var/lib/portable/ and so on.
- figure out what to do about system extensions (i.e. they need to imply an
update component, since otherwise system extenion' sysupdate.d/ files would
override the host's update files.)
- Allow invocation with a single transfer definition, i.e. with
--definitions= pointing to a file rather than a dir.
- add ability to disable implicit decompression of downloaded artifacts,
i.e. a Compress=no option in the transfer definitions
* in sd-id128: also parse UUIDs in RFC4122 URN syntax (i.e. chop off urn:uuid: prefix)
* DynamicUser= + StateDirectory= → use uid mapping mounts, too, in order to

View File

@ -987,6 +987,13 @@ manpages = [
'5',
['system.conf.d', 'systemd-user.conf', 'user.conf.d'],
''],
['systemd-sysupdate',
'8',
['systemd-sysupdate-reboot.service',
'systemd-sysupdate-reboot.timer',
'systemd-sysupdate.service',
'systemd-sysupdate.timer'],
'ENABLE_SYSUPDATE'],
['systemd-sysusers', '8', ['systemd-sysusers.service'], ''],
['systemd-sysv-generator', '8', [], 'HAVE_SYSV_COMPAT'],
['systemd-time-wait-sync.service',
@ -1058,6 +1065,7 @@ manpages = [
['systemd.time', '7', [], ''],
['systemd.timer', '5', [], ''],
['systemd.unit', '5', [], ''],
['sysupdate.d', '5', [], 'ENABLE_SYSUPDATE'],
['sysusers.d', '5', [], 'ENABLE_SYSUSERS'],
['telinit', '8', [], 'HAVE_SYSV_COMPAT'],
['timedatectl', '1', [], 'ENABLE_TIMEDATECTL'],

287
man/systemd-sysupdate.xml Normal file
View File

@ -0,0 +1,287 @@
<?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="systemd-sysupdate" conditional='ENABLE_SYSUPDATE'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd-sysupdate</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-sysupdate</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-sysupdate</refname>
<refname>systemd-sysupdate.service</refname>
<refname>systemd-sysupdate.timer</refname>
<refname>systemd-sysupdate-reboot.service</refname>
<refname>systemd-sysupdate-reboot.timer</refname>
<refpurpose>Automatically Update OS or Other Resources</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>systemd-sysupdate</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
</cmdsynopsis>
<para><filename>systemd-sysupdate.service</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd-sysupdate</command> atomically updates the host OS, container images, portable
service images or other sources, based on the transfer configuration files described in
<citerefentry><refentrytitle>sysupdate.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<para>This tool implements file, directory, or partition based update schemes, supporting multiple
parallel installed versions of specific resources in an A/B (or even: A/B/C, A/B/C/D/, …) style. A/B
updating means that when one version of a resource is currently being used, the next version can be
downloaded, unpacked, and prepared in an entirely separate location, indepdently of the first, and — once
complete — be activated, swapping the roles so that it becomes the used one and the previously used one
becomes the the one that is replaced by the next update, and so on. The resources to update are defined
in transfer files, one for each resource to be updated. For example, resources that may be updated with
this tool could be: a root file system partition, a matching Verity partition plus one kernel image. The
combination of the three would be considered a complete OS update.</para>
<para>The tool updates partitions, files or directory trees always in whole, and operates with at least
two versions of each of these resources: the <emphasis>current</emphasis> version, plus the
<emphasis>next</emphasis> version: the one that is being updated to, and which is initially incomplete as
the downloaded data is written to it; plus optionally more versions. Once the download of a newer version
is complete it becomes the current version, releasing the version previously considered current for
deletion/replacement/updating.</para>
<para>When installing new versions the tool will directly download, decompress, unpack and write the new
version into the destination. This is done in a robust fashion so that an incomplete download can be
recognized on next invocation, and flushed out before a new attempt is initiated.</para>
<para>Note that when writing updates to a partition, the partition has to exist already, as
<command>systemd-sysupdate</command> will not automatically create new partitions. Use a tool such as
<citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry> to
automatically create additional partitions to be used with <command>systemd-sysupdate</command> on
boot.</para>
<para>The tool can both be used on the running OS, to update the OS in "online" state from within itself,
and on "offline" disk images, to update them from the outside based on transfer files
embedded in the disk images. For the latter, see <option>--image=</option> below. The latter is
particularly interesting to update container images or portable service images.</para>
<para>The <filename>systemd-sysupdate.service</filename> system service will automatically update the
host OS based on the installed transfer files. It is triggered in regular intervals via
<filename>systemd-sysupdate.timer</filename>. The <filename>systemd-sysupdate-reboot.service</filename>
will automatically reboot the system after a new version is installed. It is triggered via
<filename>systemd-sysupdate-reboot.timer</filename>. The two services are separate from each other as it
is typically advisable to download updates regularly while the system is up, but delay reboots until the
appropriate time (i.e. typically at night). The two sets of service/timer units may be enabled
separately.</para>
<para>For details about transfer files and examples see
<citerefentry><refentrytitle>sysupdate.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
</refsect1>
<refsect1>
<title>Command</title>
<para>The following commands are understood:</para>
<variablelist>
<varlistentry>
<term><option>list</option> <optional><replaceable>VERSION</replaceable></optional></term>
<listitem><para>If invoked without an argument, enumerates downloadable and installed versions, and
shows a summarizing table with the discovered versions and their properties, including whether
there's a newer candidate version to update to. If a version argument is specified, shows details
about the specific version, including the individual files that need to be transferred to acquire the
version.</para>
<para>If no command is explicitly specified this command is implied.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>check-new</option></term>
<listitem><para>Checks if there's a new version available. This internally enumerates downloadable and
installed versions and returns exit status 0 if there's a new version to update to, non-zero
otherwise. If there is a new version to update to, its version identifier is written to standard
output.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>update</option> <optional><replaceable>VERSION</replaceable></optional></term>
<listitem><para>Installs (updates to) the specified version, or if none is specified to the newest
version available. If the version is already installed or no newer version available, no operation is
executed.</para>
<para>If a new version to install/update to is found, old installed versions are deleted until at
least one new version can be installed, as configured via <varname>InstanceMax=</varname> in
<citerefentry><refentrytitle>sysupdate.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>, or
via the available partition slots of the right type. This implicit operation can also be invoked
explicitly via the <command>vacuum</command> command described below.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>vacuum</option></term>
<listitem><para>Deletes old installed versions until the limits configured via
<varname>InstanceMax=</varname> in
<citerefentry><refentrytitle>sysupdate.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> are
met again. Normally, it should not be necessary to invoke this command explicitly, since it is
implicitly invoked whenever a new update is initiated.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>pending</option></term>
<listitem><para>Checks whether a newer version of the OS is installed than the one currently
running. Returns zero if so, non-zero otherwise. This compares the newest installed version's
identifier with the OS image version as reported by the <varname>IMAGE_VERSION=</varname> field in
<filename>/etc/os-release</filename>. If the former is newer than the latter, an update was
apparently completed but not activated (i.e. rebooted into) yet.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>reboot</option></term>
<listitem><para>Similar to the <option>pending</option> command but immediately reboots in case a
newer version of the OS has been installed than the one currently running. This operation can be done
implicitly together with the <command>update</command> command, after a completed update via the
<option>--reboot</option> switch, see below. This command will execute no operation (and return
success) if no update has been installed, and thus the system was not rebooted.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>components</option></term>
<listitem><para>Lists components that can be updated. This enumerates the
<filename>/etc/sysupdate.*.d/</filename>, <filename>/run/sysupdate.*.d/</filename> and
<filename>/usr/lib/sysupdate.*.d/</filename> directories that contain transfer files. This command is
useful to list possible parameters for <option>--component=</option> (see below).</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
</refsect1>
<refsect1>
<title>Options</title>
<para>The following options are understood:</para>
<variablelist>
<varlistentry>
<term><option>--component=</option></term>
<term><option>-C</option></term>
<listitem><para>Selects the component to update. Takes a component name as argument. This has the
effect of slightly altering the search logic for transfer files. If this switch is not used, the
transfer files are loaded from <filename>/etc/sysupdate.d/*.conf</filename>,
<filename>/run/sysupdate.d/*.conf</filename> and <filename>/usr/lib/sysupdate.d/*.conf</filename>. If
this switch is used, the specified component name is used to alter the directories to look in to be
<filename>/etc/sysupdate.<replaceable>component</replaceable>.d/*.conf</filename>,
<filename>/run/sysupdate.<replaceable>component</replaceable>.d/*.conf</filename> and
<filename>/usr/lib/sysupdate.<replaceable>component</replaceable>.d/*.conf</filename>, each time with
the <filename><replaceable>component</replaceable></filename> string replaced with the specified
component name.</para>
<para>Use the <command>components</command> command to list available components to update. This enumerates
the directories matching this naming rule.</para>
<para>Components may be used to define a separate set of transfer files for different components of
the OS that shall be updated separately. Do not use this concept for resources that shall always be
updated together in a synchronous fashion. Simply define multiple transfer files within the same
<filename>sysupdate.d/</filename> directory for these cases.</para>
<para>This option may not be combined with <option>--definitions=</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--definitions=</option></term>
<listitem><para>A path to a directory. If specified, the transfer <filename>*.conf</filename> files
are read from this directory instead of <filename>/usr/lib/sysupdate.d/*.conf</filename>,
<filename>/etc/sysupdate.d/*.conf</filename>, and <filename>/run/sysupdate.d/*.conf</filename>.</para>
<para>This option may not be combined with <option>--component=</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--root=</option></term>
<listitem><para>Takes a path to a directory to use as root file system when searching for
<filename>sysupdate.d/*.conf</filename> files.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--image=</option></term>
<listitem><para>Takes a path to a disk image file or device to mount and use in a similar fashion to
<option>--root=</option>, see above. If this is used and partition resources are updated this is done
inside the specified disk image.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--instances-max=</option></term>
<term><option>-m</option></term>
<listitem><para>Takes a decimal integer greater than or equal to 2. Controls how many versions to
keep at any time. This option may also be configured inside the transfer files, via the
<varname>InstancesMax=</varname> setting, see
<citerefentry><refentrytitle>sysupdate.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sync=</option></term>
<listitem><para>Takes a boolean argument, defaults to yes. This may be used to specify whether the
newly updated resource versions shall be synchronized to disk when appropriate (i.e. after the
download is complete, before it is finalized, and again after finalization). This should not be
turned off, except to improve runtime performance in testing environments.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--verify=</option></term>
<listitem><para>Takes a boolean argument, defaults to yes. Controls whether to cryptographically
verify downloads. Do not turn this off, except in testing environments.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--reboot</option></term>
<listitem><para>When used in combination with the <command>update</command> command and a new version is
installed, automatically reboots the system immediately afterwards.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="no-legend" />
<xi:include href="standard-options.xml" xpointer="json" />
</variablelist>
</refsect1>
<refsect1>
<title>Exit status</title>
<para>On success, 0 is returned, a non-zero failure code otherwise.</para>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sysupdate.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

885
man/sysupdate.d.xml Normal file
View File

@ -0,0 +1,885 @@
<?xml version='1.0'?>
<!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="sysupdate.d" conditional='ENABLE_SYSUPDATE'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sysupdate.d</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>sysupdate.d</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>sysupdate.d</refname>
<refpurpose>Transfer Definition Files for Automatic Updates</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><literallayout><filename>/etc/sysupdate.d/*.conf</filename>
<filename>/run/sysupdate.d/*.conf</filename>
<filename>/usr/lib/sysupdate.d/*.conf</filename>
</literallayout></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><filename>sysupdate.d/*.conf</filename> files describe how specific resources on the local system
shall be updated from a remote source. Each such file defines one such transfer: typically a remote
HTTP/HTTPS resource as source; and a local file, directory or partition as target. This may be used as a
simple, automatic, atomic update mechanism for the OS itself, for containers, portable services or system
extension images — but in fact may be used to update any kind of file from a remote source.</para>
<para>The
<citerefentry><refentrytitle>systemd-sysupdate</refentrytitle><manvolnum>8</manvolnum></citerefentry>
command reads these files and uses them to determine which local resources should be updated, and then
executes the update.</para>
<para>Both the remote HTTP/HTTPS source and the local target typically exist in multiple, concurrent
versions, in order to implement flexible update schemes, e.g. A/B updating (or a superset thereof,
e.g. A/B/C, A/B/C/D, …).</para>
<para>Each <filename>*.conf</filename> file defines one transfer, i.e. describes one resource to
update. Typically, multiple of these files (i.e. multiple of such transfers) are defined together, and
are bound together by a common version identifier in order to update multiple resources at once on each
update operation, for example to update a kernel, a root file system and a Verity partition in a single,
combined, synchronized operation, so that only a combined update of all three together constitutes a
complete update.</para>
<para>Each <filename>*.conf</filename> file contains three sections: [Transfer], [Source] and [Target].</para>
</refsect1>
<refsect1>
<title>Basic Mode of Operation</title>
<para>Disk-image based OS updates typically consist of multiple different resources that need to be
updated together, for example a secure OS update might consist of a root file system image to drop into a
partition, a matching Verity integrity data partition image, and a kernel image prepared to boot into the
combination of the two partitions. The first two resources are files that are downloaded and placed in a
disk partition, the latter is a file that is downloaded and placed in a regular file in the boot file
system (e.g. EFI system partition). Hence, during an update of a hypothetical operating system "foobarOS"
to a hypothetical version 47 the following operations should take place:</para>
<orderedlist>
<listitem><para>A file <literal>https://download.example.com/foobarOS_47.root.xz</literal> should be
downloaded, decompressed and written to a previously unused partition with GPT partition type UUID
4f68bce3-e8cd-4db1-96e7-fbcaf984b709 for x86-64, as per <ulink
url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions
Specification</ulink>.</para></listitem>
<listitem><para>Similarly, a file <literal>https://download.example.com/foobarOS_47.verity.xz</literal>
should be downloaded, decompressed and written to a previously empty partition with GPT partition type
UUID of 2c7357ed-ebd2-46d9-aec1-23d437ec2bf5 (i.e the partition type for Verity integrity information
for x86-64 root file systems).</para></listitem>
<listitem><para>Finally, a file <literal>https://download.example.com/foobarOS_47.efi.xz</literal> (a
unified kernel, as per <ulink url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader
Specification</ulink> Type #2) should be downloaded, decompressed and written to the ESP file system,
i.e. to <filename>EFI/Linux/foobarOS_47.efi</filename> in the ESP.</para></listitem>
</orderedlist>
<para>The version-independent generalization of this would be (using the special marker
<literal>@v</literal> as wildcard for the version identifier):</para>
<orderedlist>
<listitem><para>A transfer of a file <literal>https://download.example.com/foobarOS_@v.root.xz</literal>
→ a local, previously empty GPT partition of type 4f68bce3-e8cd-4db1-96e7-fbcaf984b709, with the label to
be set to <literal>foobarOS_@v</literal>.</para></listitem>
<listitem><para>A transfer of a file <literal>https://download.example.com/foobarOS_@v.verity.xz</literal>
→ a local, previously empty GPT partition of type 2c7357ed-ebd2-46d9-aec1-23d437ec2bf5, with the label to be
set to <literal>foobarOS_@v_verity</literal>.</para></listitem>
<listitem><para>A transfer of a file <literal>https://download.example.com/foobarOS_@v.efi.xz</literal>
→ a local file <filename>/efi/EFI/Linux/foobarOS_@v.efi</filename>.</para></listitem>
</orderedlist>
<para>An update can only complete if the relevant URLs provide their resources for the same version,
i.e. for the same value of <literal>@v</literal>.</para>
<para>The above may be translated into three <filename>*.conf</filename> files in
<filename>sysupdate.d/</filename>, one for each resource to transfer. The <filename>*.conf</filename>
files configure the type of download, and what place to write the download to (i.e. whether to a
partition or a file in the file system). Most importantly these files contain the URL, partition name and
filename patterns shown above that describe how these resources are called on the source and how they
shall be called on the target.</para>
<para>In order to enumerate available versions and figuring out candidates to update to, a mechanism is
necessary to list suitable files:</para>
<itemizedlist>
<listitem><para>For partitions: the surrounding GPT partition table contains a list of defined
partitions, including a partition type UUID and a partition label (in this scheme the partition label
plays a role for the partition similar to the filename for a regular file)</para></listitem>
<listitem><para>For regular files: the directory listing of the directory the files are contained in
provides a list of existing files in a straightforward way.</para></listitem>
<listitem><para>For HTTP/HTTPS sources a simple scheme is used: a manifest file
<filename>SHA256SUMS</filename>, following the format defined by <citerefentry
project='man-pages'><refentrytitle>sha256sum</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
lists file names and their SHA256 hashes.</para></listitem>
</itemizedlist>
<para>Transfers are done in the alphabetical order of the <filename>.conf</filename> file names they are
defined in. First, the resource data is downloaded directly into a target file/directory/partition. Once
this is completed for all defined transfers, in a second step the files/directories/partitions are
renamed to their final names as defined by the target <varname>MatchPattern=</varname>, again in the
order the <filename>.conf</filename> transfer file names dictate. This step is not atomic, however it is
guaranteed to be executed strictly in order with suitable disk synchronization in place. Typically, when
updating an OS one of the transfers defines the entry point when booting. Thus it is generally a good idea
to order the resources via the transfer configuration file names so that the entry point is written
last, ensuring that any abnormal termination does not leave an entry point around whose backing is not
established yet. In the example above it would hence make sense to establish the EFI kernel image last
and thus give its transfer configuration file the alphabetically last name.</para>
<para>See below for an extended, more specific example based on the above.</para>
</refsect1>
<refsect1>
<title>Resource Types</title>
<para>Each transfer file defines one source resource to transfer to one target resource. The following
resource types are supported:</para>
<orderedlist>
<listitem><para>Resources of type <literal>url-file</literal> encapsulate a file on a web server,
referenced via a HTTP or HTTPS URL. When an update takes place, the file is downloaded and decompressed
and then written to the target file or partition. This resource type is only available for sources, not
for targets. The list of available versions of resources of this type is encoded in
<filename>SHA256SUMS</filename> manifest files, accompanied by
<filename>SHA256SUMS.gpg</filename> detached signatures.</para></listitem>
<listitem><para>The <literal>url-tar</literal> resource type is similar, but the file must be a
<filename>.tar</filename> archive. When an update takes place, the file is decompressed and unpacked
into a directory or btrfs subvolume. This resource type is only available for sources, not for
targets. Just like <literal>url-file</literal>, <literal>url-tar</literal> version enumeration makes
use of <filename>SHA256SUMS</filename> files, authenticated via
<filename>SHA256SUMS.gpg</filename>.</para></listitem>
<listitem><para>The <literal>regular-file</literal> resource type encapsulates a local regular file on
disk. During updates the file is uncompressed and written to the target file or partition. This
resource type is available both as source and as target. When updating no integrity or authentication
verification is done for resources of this type.</para></listitem>
<listitem><para>The <literal>partition</literal> resource type is similar to
<literal>regular-file</literal>, and encapsulates a GPT partition on disk. When updating, the partition
must exist already, and have the correct GPT partition type. A partition whose GPT partition label is
set to <literal>_empty</literal> is considered empty, and a candidate to place a newly downloaded
resource in. The GPT partition label is used to store version information, once a partition is
updated. This resource type is only available for target resources.</para></listitem>
<listitem><para>The <literal>tar</literal> resource type encapsulates local <filename>.tar</filename>
archive files. When an update takes place, the files are uncompressed and unpacked into a target
directory or btrfs subvolume. Behaviour of <literal>tar</literal> and <literal>url-tar</literal> is
generally similar, but the latter downloads from remote sources, and does integrity and authentication
checks while the former does not. The <literal>tar</literal> resource type is only available for source
resources.</para></listitem>
<listitem><para>The <literal>directory</literal> resource type encapsulates local directory trees. This
type is available both for source and target resources. If an update takes place on a source resource
of this type, a recursive copy of the directory is done.</para></listitem>
<listitem><para>The <literal>subvolume</literal> resource type is identical to
<literal>directory</literal>, except when used as the target, in which case the file tree is placed in
a btrfs subvolume instead of a plain directory, if the backing file system supports it (i.e. is
btrfs).</para></listitem>
</orderedlist>
<para>As already indicated, only a subset of source and target resource type combinations are
supported:</para>
<table>
<title>Resource Types</title>
<tgroup cols='3' align='left' colsep='1' rowsep='1'>
<colspec colname="name" />
<colspec colname="explanation" />
<thead>
<row>
<entry>Identifier</entry>
<entry>Description</entry>
<entry>Usable as Source</entry>
<entry>When Used as Source: Compatible Targets</entry>
<entry>When Used as Source: Integrity + Authentication</entry>
<entry>When Used as Source: Decompression</entry>
<entry>Usable as Target</entry>
<entry>When Used as Target: Compatible Sources</entry>
</row>
</thead>
<tbody>
<row>
<entry><constant>url-file</constant></entry>
<entry>HTTP/HTTPS files</entry>
<entry>yes</entry>
<entry><constant>regular-file</constant>, <constant>partition</constant></entry>
<entry>yes</entry>
<entry>yes</entry>
<entry>no</entry>
<entry>-</entry>
</row>
<row>
<entry><constant>url-tar</constant></entry>
<entry>HTTP/HTTPS <filename>.tar</filename> archives</entry>
<entry>yes</entry>
<entry><constant>directory</constant>, <constant>subvolume</constant></entry>
<entry>yes</entry>
<entry>yes</entry>
<entry>no</entry>
<entry>-</entry>
</row>
<row>
<entry><constant>regular-file</constant></entry>
<entry>Local files</entry>
<entry>yes</entry>
<entry><constant>regular-file</constant>, <constant>partition</constant></entry>
<entry>no</entry>
<entry>yes</entry>
<entry>yes</entry>
<entry><constant>url-file</constant>, <constant>regular-file</constant></entry>
</row>
<row>
<entry><constant>partition</constant></entry>
<entry>Local GPT partitions</entry>
<entry>no</entry>
<entry>-</entry>
<entry>-</entry>
<entry>-</entry>
<entry>yes</entry>
<entry><constant>url-file</constant>, <constant>regular-file</constant></entry>
</row>
<row>
<entry><constant>tar</constant></entry>
<entry>Local <filename>.tar</filename> archives</entry>
<entry>yes</entry>
<entry><constant>directory</constant>, <constant>subvolume</constant></entry>
<entry>no</entry>
<entry>yes</entry>
<entry>no</entry>
<entry>-</entry>
</row>
<row>
<entry><constant>directory</constant></entry>
<entry>Local directories</entry>
<entry>yes</entry>
<entry><constant>directory</constant>, <constant>subvolume</constant></entry>
<entry>no</entry>
<entry>no</entry>
<entry>yes</entry>
<entry><constant>url-tar</constant>, <constant>tar</constant>, <constant>directory</constant>, <constant>subvolume</constant></entry>
</row>
<row>
<entry><constant>subvolume</constant></entry>
<entry>Local btrfs subvolumes</entry>
<entry>yes</entry>
<entry><constant>directory</constant>, <constant>subvolume</constant></entry>
<entry>no</entry>
<entry>no</entry>
<entry>yes</entry>
<entry><constant>url-tar</constant>, <constant>tar</constant>, <constant>directory</constant>, <constant>subvolume</constant></entry>
</row>
</tbody>
</tgroup>
</table>
</refsect1>
<refsect1>
<title>Match Patterns</title>
<para>Both the source and target resources typically exist in multiple versions concurrently. An update
operation is done whenever the newest of the source versions is newer than the newest of the target
versions. To determine the newest version of the resources a directory listing, partition listing or
manifest listing is used, a subset of qualifying entries selected from that, and the version identifier
extracted from the file names or partition labels of these selected entries. Subset selection and
extraction of the version identifier (plus potentially other metadata) is done via match patterns,
configured in <varname>MatchPattern=</varname> in the [Source] and [Target] sections. These patterns are
strings that describe how files or partitions are named, with named wildcards for specific fields such as
the version identifier. The following wildcards are defined:</para>
<table>
<title>Match Pattern Wildcards</title>
<tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname="name" />
<colspec colname="explanation" />
<thead>
<row>
<entry>Wildcard</entry>
<entry>Description</entry>
<entry>Format</entry>
<entry>Notes</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>@v</literal></entry>
<entry>Version identifier</entry>
<entry>Valid version string</entry>
<entry>Mandatory</entry>
</row>
<row>
<entry><literal>@u</literal></entry>
<entry>GPT partition UUID</entry>
<entry>Valid 128-Bit UUID string</entry>
<entry>Only relevant if target resource type chosen as <constant>partition</constant></entry>
</row>
<row>
<entry><literal>@f</literal></entry>
<entry>GPT partition flags</entry>
<entry>Formatted hexadecimal integer</entry>
<entry>Only relevant if target resource type chosen as <constant>partition</constant></entry>
</row>
<row>
<entry><literal>@a</literal></entry>
<entry>GPT partition flag NoAuto</entry>
<entry>Either <literal>0</literal> or <literal>1</literal></entry>
<entry>Controls NoAuto bit of the GPT partition flags, as per <ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>; only relevant if target resource type chosen as <constant>partition</constant></entry>
</row>
<row>
<entry><literal>@g</literal></entry>
<entry>GPT partition flag GrowFileSystem</entry>
<entry>Either <literal>0</literal> or <literal>1</literal></entry>
<entry>Controls GrowFileSystem bit of the GPT partition flags, as per <ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink>; only relevant if target resource type chosen as <constant>partition</constant></entry>
</row>
<row>
<entry><literal>@r</literal></entry>
<entry>Read-only flag</entry>
<entry>Either <literal>0</literal> or <literal>1</literal></entry>
<entry>Controls ReadOnly bit of the GPT partition flags, as per <ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions Specification</ulink> and other output read-only flags, see <varname>ReadOnly=</varname> below.</entry>
</row>
<row>
<entry><literal>@t</literal></entry>
<entry>File modification time</entry>
<entry>Formatted decimal integer, µs since UNIX epoch Jan 1st 1970</entry>
<entry>Only relevant if target resource type chosen as <constant>regular-file</constant></entry>
</row>
<row>
<entry><literal>@m</literal></entry>
<entry>File access mode</entry>
<entry>Formatted octal integer, in UNIX fashion</entry>
<entry>Only relevant if target resource type chosen as <constant>regular-file</constant></entry>
</row>
<row>
<entry><literal>@s</literal></entry>
<entry>File size after decompression</entry>
<entry>Formatted decimal integer</entry>
<entry>Useful for measuring progress and to improve partition allocation logic</entry>
</row>
<row>
<entry><literal>@d</literal></entry>
<entry>Tries done</entry>
<entry>Formatted decimal integer</entry>
<entry>Useful when operating with kernel image files, as per <ulink url="https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT">Automatic Boot Assessment</ulink></entry>
</row>
<row>
<entry><literal>@l</literal></entry>
<entry>Tries left</entry>
<entry>Formatted decimal integer</entry>
<entry>Useful when operating with kernel images, as per <ulink url="https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT">Automatic Boot Assessment</ulink></entry>
</row>
<row>
<entry><literal>@h</literal></entry>
<entry>SHA256 hash of compressed file</entry>
<entry>64 hexadecimal characters</entry>
<entry>The SHA256 hash of the compressed file; not useful for <constant>url-file</constant> or <constant>url-tar</constant> where the SHA256 hash is already included in the manifest file anyway.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>Of these wildcards only <literal>@v</literal> must be present in a valid pattern, all other
wildcards are optional. Each wildcard may be used at most once in each pattern. A typical wildcard
matching a file system source image could be <literal>MatchPattern=foobar_@v.raw.xz</literal>, i.e. any file
whose name begins with <literal>foobar_</literal>, followed by a version ID and suffixed by
<literal>.raw.xz</literal>.</para>
<para>Do not confuse the <literal>@</literal> pattern matching wildcard prefix with the
<literal>%</literal> specifier expansion prefix. The former encapsulate a variable part of a match
pattern string, the latter are simple shortcuts that are expanded while the drop-in files are
parsed. For details about specifiers, see below.</para>
</refsect1>
<refsect1>
<title>[Transfer] Section Options</title>
<para>This section defines general properties of this transfer.</para>
<variablelist>
<varlistentry>
<term><varname>MinVersion=</varname></term>
<listitem><para>Specifies the minimum version to require for this transfer to take place. If the
source or target patterns in this transfer definition match files older than this version they will
be considered obsolete, and never be considered for the update operation.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ProtectVersion=</varname></term>
<listitem><para>Takes one or more version strings to mark as "protected". Protected versions are
never removed while making room for new, updated versions. This is useful to ensure that the
currently booted OS version (or auxiliary resources associated with it) is not replaced/overwritten
during updates, in order to avoid runtime file system corruptions.</para>
<para>Like many of the settings in these configuration files this setting supports specifier
expansion. It's particularly useful to set this setting to one of the <literal>%A</literal>,
<literal>%B</literal> or <literal>%w</literal> specifiers to automatically refer to the current OS
version of the running system. See below for details on supported specifiers.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Verify=</varname></term>
<listitem><para>Takes a boolean, defaults to yes. Controls whether to cryptographically verify
downloaded resources (specifically: validate the GPG signatures for downloaded
<filename>SHA256SUMS</filename> manifest files, via their detached signature files
<filename>SHA256SUMS.gpg</filename> in combination with the system keyring
<filename>/usr/lib/systemd/import-pubring.gpg</filename> or
<filename>/etc/systemd/import-pubring.gpg</filename>).</para>
<para>This option is essential to provide integrity guarantees for downloaded resources and thus
should be left enabled, outside of test environments.</para>
<para>Note that the downloaded payload files are unconditionally checked against the SHA256 hashes
listed in the manifest. This option only controls whether the signatures of these manifests are
verified.</para>
<para>This option only has an effect if the source resource type is selected as
<constant>url-file</constant> or <constant>url-tar</constant>, as integrity and authentication
checking is only available for transfers from remote sources.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>[Source] Section Options</title>
<para>This section defines properties of the transfer source:</para>
<variablelist>
<varlistentry>
<term><varname>Type=</varname></term>
<listitem><para>Specifies the resource type of the source for the transfer. Takes one of
<constant>url-file</constant>, <constant>url-tar</constant>, <constant>tar</constant>,
<constant>regular-file</constant>, <constant>directory</constant> or
<constant>subvolume</constant>. For details about the resource types, see above. This option is
mandatory.</para>
<para>Note that only some combinations of source and target resource types are supported, see
above.</para></listitem>
</varlistentry>
</variablelist>
<variablelist>
<varlistentry>
<term><varname>Path=</varname></term>
<listitem><para>Specifies where to find source versions of this resource.</para>
<para>If the source type is selected as <constant>url-file</constant> or
<constant>url-tar</constant> this must be a HTTP/HTTPS URL. The URL is suffixed with
<filename>/SHA256SUMS</filename> to acquire the manifest file, with
<filename>/SHA256SUMS.gpg</filename> to acquire the detached signature file for it, and with the file
names listed in the manifest file in case an update is executed and a resource shall be
downloaded.</para>
<para>For all other source resource types this must be a local path in the file system, referring to
a local directory to find the versions of this resource in.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>MatchPattern=</varname></term>
<listitem><para>Specifies one or more file name match patterns that select the subset of files that
are update candidates as source for this transfer. See above for details on match patterns.</para>
<para>This option is mandatory. Any pattern listed must contain at least the <literal>@v</literal>
wildcard, so that a version identifier may be extracted from the filename. All other wildcards are
optional.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>[Target] Section Options</title>
<para>This section defines properties of the transfer target:</para>
<variablelist>
<varlistentry>
<term><varname>Type=</varname></term>
<listitem><para>Specifies the resource type of the target for the transfer. Takes one of
<constant>partition</constant>, <constant>regular-file</constant>, <constant>directory</constant> or
<constant>subvolume</constant>. For details about the resource types, see above. This option is
mandatory.</para>
<para>Note that only some combinations of source and target resource types are supported, see above.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Path=</varname></term>
<listitem><para>Specifies a file system path where to look for already installed versions or place
newly downloaded versions of this configured resource. If <varname>Type=</varname> is set to
<constant>partition</constant>, expects a path to a (whole) block device node, or the special string
<literal>auto</literal> in which case the block device the root file system of the currently booted
system is automatically determined and used. If <varname>Type=</varname> is set to
<constant>regular-file</constant>, <constant>directory</constant> or <constant>subvolume</constant>,
must refer to a path in the local file system referencing the directory to find or place the version
files or directories under.</para>
<para>Note that this mechanism cannot be used to create or remove partitions, in case
<varname>Type=</varname> is set to <constant>partition</constant>. Partitions must exist already, and
a special partition label <literal>_empty</literal> is used to indicate empty partitions. To
automatically generate suitable partitions on first boot, use a tool such as
<citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>MatchPattern=</varname></term>
<listitem><para>Specifies one or more file name or partition label match patterns that select the
subset of files or partitions that are update candidates as targets for this transfer. See above for
details on match patterns.</para>
<para>This option is mandatory. Any pattern listed must contain at least the <literal>@v</literal>
wildcard, so that a version identifier may be extracted from the filename. All other wildcards are
optional.</para>
<para>This pattern is both used for matching existing installed versions and for determining the name
of new versions to install. If multiple patterns are specified, the first specified is used for
naming newly installed versions.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>MatchPartitionType=</varname></term>
<listitem><para>When the target <varname>Type=</varname> is chosen as <constant>partition</constant>,
specifies the GPT partition type to look for. Only partitions of this type are considered, all other
partitions are ignored. If not specified, the GPT partition type <constant>linux-generic</constant>
is used. Accepts either a literal type UUID or a symbolic type identifier. For a list of supported
type identifiers, see the <varname>Type=</varname> setting in
<citerefentry><refentrytitle>repart.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>PartitionUUID=</varname></term>
<term><varname>PartitionFlags=</varname></term>
<term><varname>PartitionNoAuto=</varname></term>
<term><varname>PartitionGrowFileSystem=</varname></term>
<listitem><para>When the target <varname>Type=</varname> is picked as <constant>partition</constant>,
selects the GPT partition UUID and partition flags to use for the updated partition. Expects a valid
UUID string, a hexadecimal integer, or booleans, respectively. If not set, but the source match
pattern includes wildcards for these fields (i.e. <literal>@u</literal>, <literal>@f</literal>,
<literal>@a</literal>, or <literal>@g</literal>), the values from the patterns are used. If neither
configured with wildcards or these explicit settings, the values are left untouched. If both the
overall <varname>PartitionFlags=</varname> flags setting and the individual flag settings
<varname>PartitionNoAuto=</varname> and <varname>PartitionGrowFileSystem=</varname> are used (or the
wildcards for them), then the latter override the former, i.e. the individual flag bit overrides the
overall flags value. See <ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable
Partitions Specification</ulink> for details about these flags.</para>
<para>Note that these settings are not used for matching, they only have effect on newly written
partitions in case a transfer takes place.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ReadOnly=</varname></term>
<listitem><para>Controls whether to mark the resulting file, subvolume or partition read-only. If the
target type is <constant>partition</constant> this controls the ReadOnly partition flag, as per
<ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions
Specification</ulink>, similar to the <varname>PartitionNoAuto=</varname> and
<varname>PartitionGrowFileSystem=</varname> flags described above. If the target type is
<constant>regular-file</constant>, the writable bit is removed from the access mode. If the the
target type is <constant>subvolume</constant>, the subvolume will be marked read-only as a
whole. Finally, if the target <varname>Type=</varname> is selected as <constant>directory</constant>,
the "immutable" file attribute is set, see <citerefentry
project='man-pages'><refentrytitle>chattr</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
details.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Mode=</varname></term>
<listitem><para>The UNIX file access mode to use for newly created files in case the target resource
type is picked as <constant>regular-file</constant>. Expects an octal integer, in typical UNIX
fashion. If not set, but the source match pattern includes a wildcard for this field
(i.e. <literal>@t</literal>), the value from the pattern is used.</para>
<para>Note that this setting is not used for matching, it only has an effect on newly written
files when a transfer takes place.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>TriesDone=</varname></term>
<term><varname>TriesLeft=</varname></term>
<listitem><para>These options take positive, decimal integers, and control the number of attempts
done and left for this file. These settings are useful for managing kernel images, following the
scheme defined in <ulink url="https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT">Automatic Boot
Assessment</ulink>, and only have an effect if the target pattern includes the <literal>@d</literal>
or <literal>@l</literal> wildcards.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>InstancesMax=</varname></term>
<listitem><para>Takes a decimal integer equal to or greater than 2. This configures how many concurrent
versions of the resource to keep. Whenever a new update is initiated it is made sure that no more
than the number of versions specified here minus one exist in the target. Any excess versions are
deleted (in case the target <varname>Type=</varname> of <constant>regular-file</constant>,
<constant>directory</constant>, <constant>subvolume</constant> is used) or emptied (in case the
target <varname>Type=</varname> of <constant>partition</constant> is used; emptying in this case
simply means to set the partition label to the special string <literal>_empty</literal>; note that no
partitions are actually removed). After an update is completed the number of concurrent versions of
the target resources is equal to or below the number specified here.</para>
<para>Note that this setting may be set differently for each transfer. However, it generally is
advisable to keep this setting the same for all transfers, since otherwise incomplete combinations of
files or partitions will be left installed.</para>
<para>If the target <varname>Type=</varname> is selected as <constant>partition</constant>, the number
of concurrent versions to keep is additionally restricted by the number of partition slots of the
right type in the partition table. i.e. if there are only 2 partition slots for the selected
partition type, setting this value larger than 2 is without effect, since no more than 2 concurrent
versions could be stored in the image anyway.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>RemoveTemporary=</varname></term>
<listitem><para>Takes a boolean argument. If this option is enabled (which is the default) before
initiating an update, all left-over, incomplete updates from a previous attempt are removed from the
target directory. This only has an effect if the target resource <varname>Type=</varname> is selected
as <constant>regular-file</constant>, <constant>directory</constant> or
<constant>subvolume</constant>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>CurrentSymlink=</varname></term>
<listitem><para>Takes a symlink name as argument. If this option is used, as the last step of the
update a symlink under the specified name is created/updated pointing to the completed update. This
is useful in to provide a stable name always pointing to the newest version of the resource. This is
only supported if the target resource <varname>Type=</varname> is selected as
<constant>regular-file</constant>, <constant>directory</constant> or
<constant>subvolume</constant>.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Specifiers</title>
<para>Specifiers may be used in the <varname>MinVersion=</varname>, <varname>ProtectVersion=</varname>,
<varname>Path=</varname>, <varname>MatchPattern=</varname> and <varname>CurrentSymlink=</varname>
settings. The following expansions are understood:</para>
<table class='specifiers'>
<title>Specifiers available</title>
<tgroup cols='3' align='left' colsep='1' rowsep='1'>
<colspec colname="spec" />
<colspec colname="mean" />
<colspec colname="detail" />
<thead>
<row>
<entry>Specifier</entry>
<entry>Meaning</entry>
<entry>Details</entry>
</row>
</thead>
<tbody>
<xi:include href="standard-specifiers.xml" xpointer="a"/>
<xi:include href="standard-specifiers.xml" xpointer="A"/>
<xi:include href="standard-specifiers.xml" xpointer="b"/>
<xi:include href="standard-specifiers.xml" xpointer="B"/>
<xi:include href="standard-specifiers.xml" xpointer="H"/>
<xi:include href="standard-specifiers.xml" xpointer="l"/>
<xi:include href="standard-specifiers.xml" xpointer="m"/>
<xi:include href="standard-specifiers.xml" xpointer="M"/>
<xi:include href="standard-specifiers.xml" xpointer="o"/>
<xi:include href="standard-specifiers.xml" xpointer="v"/>
<xi:include href="standard-specifiers.xml" xpointer="w"/>
<xi:include href="standard-specifiers.xml" xpointer="W"/>
<xi:include href="standard-specifiers.xml" xpointer="T"/>
<xi:include href="standard-specifiers.xml" xpointer="V"/>
<xi:include href="standard-specifiers.xml" xpointer="percent"/>
</tbody>
</tgroup>
</table>
<para>Do not confuse the <literal>%</literal> specifier expansion prefix with the <literal>@</literal>
pattern matching wildcard prefix. The former are simple shortcuts that are expanded while the drop-in
files are parsed, the latter encapsulate a variable part of a match pattern string. For details about
pattern matching wildcards, see above.</para>
</refsect1>
<refsect1>
<title>Examples</title>
<example>
<title>Updates for a Verity Enabled Secure OS</title>
<para>With the following three files we define a root file system partition, a matching Verity
partition, and a unified kernel image to update as one. This example is an extension of the example
discussed earlier in this man page.</para>
<para><programlisting># /usr/lib/sysupdate.d/50-verity.conf
[Transfer]
ProtectVersion=%A
[Source]
Type=url-file
Path=https://download.example.com/
MatchPattern=foobarOS_@v_@u.verity.xz
[Target]
Type=partition
Path=auto
MatchPattern=foobarOS_@v_verity
MatchPartitionType=root-verity
PartitionFlags=0
PartitionReadOnly=1</programlisting></para>
<para>The above defines the update mechanism for the Verity partition of the root file system. Verity
partition images are downloaded from
<literal>https://download.example.com/foobarOS_@v_@u.verity.xz</literal> and written to a suitable
local partition, which is marked read-only. Under the assumption this update is run from the image
itself the current image version (i.e. the <literal>%A</literal> specifier) is marked as protected, to
ensure it is not corrupted while booted. Note that the partition UUID for the target partition is
encoded in the source file name. Fixating the partition UUID can be useful to ensure that
<literal>roothash=</literal> on the kernel command line is sufficient to pinpoint both the Verity and
root file system partition, and also encode the Verity root level hash (under the assumption the UUID
in the file names match their top-level hash, the way
<citerefentry><refentrytitle>systemd-gpt-auto-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
suggests).</para>
<para><programlisting># /usr/lib/sysupdate.d/60-root.conf
[Transfer]
ProtectVersion=%A
[Source]
Type=url-file
Path=https://download.example.com/
MatchPattern=foobarOS_@v_@u.root.xz
[Target]
Type=partition
Path=auto
MatchPattern=foobarOS_@v
MatchPartitionType=root
PartitionFlags=0
PartitionReadOnly=1</programlisting></para>
<para>The above defines a matching transfer definition for the root file system.</para>
<para><programlisting># /usr/lib/sysupdate.d/70-kernel.conf
[Transfer]
ProtectVersion=%A
[Source]
Type=url-file
Path=https://download.example.com/
MatchPattern=foobarOS_@v.efi.xz
[Target]
Type=file
Path=/efi/EFI/Linux
MatchPattern=foobarOS_@v+@l-@d.efi \
foobarOS_@v+@l.efi \
foobarOS_@v.efi
Mode=0444
TriesLeft=3
TriesDone=0
InstancesMax=2</programlisting></para>
<para>The above installs a unified kernel image into the ESP (which is mounted to
<filename>/efi/</filename>), as per <ulink url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot
Loader Specification</ulink> Type #2. This defines three possible patterns for the names of the
kernel images images, as per <ulink url="https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT">Automatic Boot
Assessment</ulink>, and ensures when installing new kernels, they are set up with 3 tries left. No
more than two parallel kernels are kept.</para>
<para>With this setup the web server would serve the following files, for a hypothetical version 7 of
the OS:</para>
<itemizedlist>
<listitem><para><filename>SHA256SUMS</filename> The manifest file, containing available files and their SHA256 hashes</para></listitem>
<listitem><para><filename>SHA256SUMS.gpg</filename> The detached cryptographic signature for the manifest file</para></listitem>
<listitem><para><filename>foobarOS_7_8b8186b1-2b4e-4eb6-ad39-8d4d18d2a8fb.verity.xz</filename> The Verity image for version 7</para></listitem>
<listitem><para><filename>foobarOS_7_f4d1234f-3ebf-47c4-b31d-4052982f9a2f.root.xz</filename> The root file system image for version 7</para></listitem>
<listitem><para><filename>foobarOS_7_efi.xz</filename> The unified kernel image for version 7</para></listitem>
</itemizedlist>
<para>For each new OS release a new set of the latter three files would be added, each time with an
updated version. The <filename>SHA256SUMS</filename> manifest should then be updated accordingly,
listing all files for all versions that shall be offered for download.</para>
</example>
<example>
<title>Updates for Plain Directory Container Image</title>
<para><programlisting>
[Source]
Type=url-tar
Path=https://download.example.com/
MatchPattern=myContainer_@v.tar.gz
[Target]
Type=subvolume
Path=/var/lib/machines
MatchPattern=myContainer_@v
CurrentSymlink=myContainer</programlisting></para>
<para>On updates this downloads <literal>https://download.example.com/myContainer_@v.tar.gz</literal>
and decompresses/unpacks it to <filename>/var/lib/machines/myContainer_@v</filename>. After each update
a symlink <filename>/var/lib/machines/myContainer</filename> is created/updated always pointing to the
most recent update.</para>
</example>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-sysupdate</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1644,6 +1644,18 @@ conf.set('DEFAULT_DNSSEC_MODE',
'DNSSEC_' + default_dnssec.underscorify().to_upper())
conf.set_quoted('DEFAULT_DNSSEC_MODE_STR', default_dnssec)
want_sysupdate = get_option('sysupdate')
if want_sysupdate != 'false'
have = (conf.get('HAVE_OPENSSL') == 1 and
conf.get('HAVE_LIBFDISK') == 1)
if want_sysupdate == 'true' and not have
error('sysupdate support was requested, but dependencies are not available')
endif
else
have = false
endif
conf.set10('ENABLE_SYSUPDATE', have)
want_importd = get_option('importd')
if want_importd != 'false'
have = (conf.get('HAVE_LIBCURL') == 1 and
@ -2006,6 +2018,7 @@ subdir('src/rpm')
subdir('src/shutdown')
subdir('src/sysext')
subdir('src/systemctl')
subdir('src/sysupdate')
subdir('src/timedate')
subdir('src/timesync')
subdir('src/tmpfiles')
@ -3074,6 +3087,22 @@ if conf.get('ENABLE_REPART') == 1
endif
endif
if conf.get('ENABLE_SYSUPDATE') == 1
exe = executable(
'systemd-sysupdate',
systemd_sysupdate_sources,
include_directories : includes,
link_with : [libshared],
dependencies : [threads,
libblkid,
libfdisk,
libopenssl],
install_rpath : rootlibexecdir,
install : true,
install_dir : rootlibexecdir)
public_programs += exe
endif
if conf.get('ENABLE_VCONSOLE') == 1
executable(
'systemd-vconsole-setup',
@ -4117,6 +4146,7 @@ foreach tuple : [
['rfkill'],
['sysext'],
['systemd-analyze', conf.get('ENABLE_ANALYZE') == 1],
['sysupdate'],
['sysusers'],
['timedated'],
['timesyncd'],

View File

@ -100,6 +100,8 @@ option('binfmt', type : 'boolean',
description : 'support for custom binary formats')
option('repart', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'install the systemd-repart tool')
option('sysupdate', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'install the systemd-sysupdate tool')
option('coredump', type : 'boolean',
description : 'install the coredump handler')
option('pstore', type : 'boolean',

View File

@ -49,7 +49,6 @@ static int add_epoll(int epoll_fd, int fd) {
}
static int open_sockets(int *epoll_fd, bool accept) {
char **address;
int n, fd, r, count = 0;
n = sd_listen_fds(true);
@ -125,7 +124,6 @@ static int open_sockets(int *epoll_fd, bool accept) {
static int exec_process(const char *name, char **argv, int start_fd, size_t n_fds) {
_cleanup_strv_free_ char **envp = NULL;
const char *var;
char **s;
int r;
if (arg_inetd && n_fds != 1)
@ -390,7 +388,6 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_FDNAME: {
_cleanup_strv_free_ char **names = NULL;
char **s;
names = strv_split(optarg, ":");
if (!names)

View File

@ -124,7 +124,6 @@ static int test_calendar_one(usec_t n, const char *p) {
int verb_calendar(int argc, char *argv[], void *userdata) {
int ret = 0, r;
char **p;
usec_t n;
if (arg_base_time != USEC_INFINITY)

View File

@ -10,7 +10,7 @@
#include "strv.h"
int verb_cat_config(int argc, char *argv[], void *userdata) {
char **arg, **list;
char **list;
int r;
pager_open(arg_pager_flags);

View File

@ -114,8 +114,6 @@ static int verify_conditions(char **lines, UnitFileScope scope, const char *unit
if (r < 0)
return r;
} else {
char **line;
r = unit_new_for_name(m, sizeof(Service), "test.service", &u);
if (r < 0)
return log_error_errno(r, "Failed to create test.service: %m");

View File

@ -76,7 +76,6 @@ static bool times_in_range(const UnitTimes *times, const BootTimes *boot) {
static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level, char ***units, unsigned branches) {
_cleanup_strv_free_ char **deps = NULL;
char **c;
int r;
usec_t service_longest = 0;
int to_print = 0;
@ -225,11 +224,10 @@ int verb_critical_chain(int argc, char *argv[], void *userdata) {
puts("The time when unit became active or started is printed after the \"@\" character.\n"
"The time the unit took to start is printed after the \"+\" character.\n");
if (argc > 1) {
char **name;
if (argc > 1)
STRV_FOREACH(name, strv_skip(argv, 1))
list_dependencies(bus, *name);
} else
else
list_dependencies(bus, SPECIAL_DEFAULT_TARGET);
h = hashmap_free(h);

View File

@ -18,9 +18,8 @@ static int graph_one_property(
char *to_patterns[]) {
_cleanup_strv_free_ char **units = NULL;
char **unit;
int r;
bool match_patterns;
int r;
assert(u);
assert(prop);
@ -84,7 +83,6 @@ static int graph_one(sd_bus *bus, const UnitInfo *u, char *patterns[], char *fro
static int expand_patterns(sd_bus *bus, char **patterns, char ***ret) {
_cleanup_strv_free_ char **expanded_patterns = NULL;
char **pattern;
int r;
STRV_FOREACH(pattern, patterns) {

View File

@ -145,7 +145,6 @@ int verb_filesystems(int argc, char *argv[], void *userdata) {
if (!set_isempty(known)) {
_cleanup_free_ char **l = NULL;
char **filesystem;
printf("\n"
"# %sUngrouped filesystems%s (known but not included in any of the groups except @known):\n",
@ -188,7 +187,6 @@ int verb_filesystems(int argc, char *argv[], void *userdata) {
log_notice_errno(k, "# Not showing unlisted filesystems, couldn't retrieve kernel filesystem list: %m");
} else if (!set_isempty(kernel)) {
_cleanup_free_ char **l = NULL;
char **filesystem;
printf("\n"
"# %sUnlisted filesystems%s (available to the local kernel, but not included in any of the groups listed above):\n",
@ -203,9 +201,7 @@ int verb_filesystems(int argc, char *argv[], void *userdata) {
STRV_FOREACH(filesystem, l)
printf("# %s\n", *filesystem);
}
} else {
char **name;
} else
STRV_FOREACH(name, strv_skip(argv, 1)) {
const FilesystemSet *set;
@ -224,7 +220,6 @@ int verb_filesystems(int argc, char *argv[], void *userdata) {
dump_filesystem_set(set);
first = false;
}
}
return 0;
}

View File

@ -12,7 +12,6 @@
#include "strv.h"
static int analyze_elf(char **filenames, JsonFormatFlags json_flags) {
char **filename;
int r;
STRV_FOREACH(filename, filenames) {

View File

@ -2666,7 +2666,6 @@ static int offline_security_checks(char **filenames,
_cleanup_free_ char *var = NULL;
int r, k;
size_t count = 0;
char **filename;
if (strv_isempty(filenames))
return 0;
@ -2789,7 +2788,6 @@ static int analyze_security(sd_bus *bus,
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_strv_free_ char **list = NULL;
size_t n = 0;
char **i;
r = sd_bus_call_method(
bus,
@ -2841,9 +2839,7 @@ static int analyze_security(sd_bus *bus,
ret = r;
}
} else {
char **i;
} else
STRV_FOREACH(i, units) {
_cleanup_free_ char *mangled = NULL, *instance = NULL;
const char *name;
@ -2875,7 +2871,6 @@ static int analyze_security(sd_bus *bus,
if (r < 0 && ret >= 0)
ret = r;
}
}
if (overview_table) {
if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)) {

View File

@ -120,7 +120,6 @@ int verb_syscall_filters(int argc, char *argv[], void *userdata) {
if (!set_isempty(known)) {
_cleanup_free_ char **l = NULL;
char **syscall;
printf("\n"
"# %sUngrouped System Calls%s (known but not included in any of the groups except @known):\n",
@ -143,7 +142,6 @@ int verb_syscall_filters(int argc, char *argv[], void *userdata) {
log_notice_errno(k, "# Not showing unlisted system calls, couldn't retrieve kernel system call list: %m");
} else if (!set_isempty(kernel)) {
_cleanup_free_ char **l = NULL;
char **syscall;
printf("\n"
"# %sUnlisted System Calls%s (supported by the local kernel, but not included in any of the groups listed above):\n",
@ -158,9 +156,7 @@ int verb_syscall_filters(int argc, char *argv[], void *userdata) {
STRV_FOREACH(syscall, l)
printf("# %s\n", *syscall);
}
} else {
char **name;
} else
STRV_FOREACH(name, strv_skip(argv, 1)) {
const SyscallFilterSet *set;
@ -179,7 +175,6 @@ int verb_syscall_filters(int argc, char *argv[], void *userdata) {
dump_syscall_filter(set);
first = false;
}
}
return 0;
}

View File

@ -9,8 +9,6 @@
#include "terminal-util.h"
int verb_timespan(int argc, char *argv[], void *userdata) {
char **input_timespan;
STRV_FOREACH(input_timespan, strv_skip(argv, 1)) {
_cleanup_(table_unrefp) Table *table = NULL;
usec_t output_usecs;

View File

@ -80,7 +80,6 @@ static int test_timestamp_one(const char *p) {
int verb_timestamp(int argc, char *argv[], void *userdata) {
int ret = 0, r;
char **p;
STRV_FOREACH(p, strv_skip(argv, 1)) {
r = test_timestamp_one(*p);

View File

@ -6,8 +6,6 @@
#include "strv.h"
static bool strv_fnmatch_strv_or_empty(char* const* patterns, char **strv, int flags) {
char **s;
STRV_FOREACH(s, strv)
if (strv_fnmatch_or_empty(patterns, *s, flags))
return true;

View File

@ -8,7 +8,6 @@
int verb_unit_paths(int argc, char *argv[], void *userdata) {
_cleanup_(lookup_paths_free) LookupPaths paths = {};
int r;
char **p;
r = lookup_paths_init(&paths, arg_scope, 0, NULL);
if (r < 0)

View File

@ -74,10 +74,8 @@ int verify_prepare_filename(const char *filename, char **ret) {
}
int verify_generate_path(char **var, char **filenames) {
const char *old;
char **filename;
_cleanup_strv_free_ char **ans = NULL;
const char *old;
int r;
STRV_FOREACH(filename, filenames) {
@ -184,7 +182,6 @@ static int verify_executables(Unit *u, const char *root) {
}
static int verify_documentation(Unit *u, bool check_man) {
char **p;
int r = 0, k;
STRV_FOREACH(p, u->documentation) {
@ -258,7 +255,6 @@ int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run
Unit *units[strv_length(filenames)];
_cleanup_free_ char *var = NULL;
int r, k, i, count = 0;
char **filename;
if (strv_isempty(filenames))
return 0;

View File

@ -9,7 +9,6 @@
static int process_aliases(char *argv[], char *tempdir, char ***ret) {
_cleanup_strv_free_ char **filenames = NULL;
char **filename;
int r;
assert(argv);

View File

@ -223,7 +223,6 @@ static int parse_argv(int argc, char *argv[]) {
static int run(int argc, char *argv[]) {
_cleanup_strv_free_erase_ char **l = NULL;
usec_t timeout;
char **p;
int r;
log_show_color(true);

View File

@ -145,7 +145,7 @@ static int conf_files_list_strv_internal(
_cleanup_hashmap_free_ Hashmap *fh = NULL;
_cleanup_set_free_free_ Set *masked = NULL;
char **files, **p;
char **files;
int r;
assert(ret);
@ -202,11 +202,8 @@ int conf_files_insert(char ***strv, const char *root, char **dirs, const char *p
int c;
c = base_cmp((char* const*) *strv + i, (char* const*) &path);
if (c == 0) {
char **dir;
if (c == 0)
/* Oh, there already is an entry with a matching name (the last component). */
STRV_FOREACH(dir, dirs) {
_cleanup_free_ char *rdir = NULL;
char *p1, *p2;
@ -233,7 +230,7 @@ int conf_files_insert(char ***strv, const char *root, char **dirs, const char *p
}
}
} else if (c > 0)
else if (c > 0)
/* Following files have lower priority, let's go insert our
* new entry. */
break;

View File

@ -537,7 +537,6 @@ static void write_env_var(FILE *f, const char *v) {
int write_env_file(const char *fname, char **l) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
char **i;
int r;
assert(fname);

View File

@ -96,8 +96,6 @@ bool env_assignment_is_valid(const char *e) {
}
bool strv_env_is_valid(char **e) {
char **p, **q;
STRV_FOREACH(p, e) {
size_t k;
@ -115,8 +113,6 @@ bool strv_env_is_valid(char **e) {
}
bool strv_env_name_is_valid(char **l) {
char **p;
STRV_FOREACH(p, l) {
if (!env_name_is_valid(*p))
return false;
@ -129,8 +125,6 @@ bool strv_env_name_is_valid(char **l) {
}
bool strv_env_name_or_assignment_is_valid(char **l) {
char **p;
STRV_FOREACH(p, l) {
if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p))
return false;
@ -272,7 +266,7 @@ static bool env_entry_has_name(const char *entry, const char *name) {
char **strv_env_delete(char **x, size_t n_lists, ...) {
size_t n, i = 0;
char **k, **r;
char **r;
va_list ap;
/* Deletes every entry from x that is mentioned in the other
@ -287,7 +281,7 @@ char **strv_env_delete(char **x, size_t n_lists, ...) {
STRV_FOREACH(k, x) {
va_start(ap, n_lists);
for (size_t v = 0; v < n_lists; v++) {
char **l, **j;
char **l;
l = va_arg(ap, char**);
STRV_FOREACH(j, l)
@ -379,7 +373,6 @@ char **strv_env_unset_many(char **l, ...) {
int strv_env_replace_consume(char ***l, char *p) {
const char *t, *name;
char **f;
int r;
assert(p);
@ -467,8 +460,6 @@ int strv_env_assign(char ***l, const char *key, const char *value) {
}
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
char **i;
assert(name);
if (k <= 0)
@ -496,7 +487,7 @@ char *strv_env_get(char **l, const char *name) {
}
char *strv_env_pairs_get(char **l, const char *name) {
char **key, **value, *result = NULL;
char *result = NULL;
assert(name);
@ -508,7 +499,6 @@ char *strv_env_pairs_get(char **l, const char *name) {
}
char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const char *p, void *userdata), void *userdata) {
char **p, **q;
int k = 0;
STRV_FOREACH(p, e) {
@ -702,7 +692,7 @@ char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) {
}
char **replace_env_argv(char **argv, char **env) {
char **ret, **i;
char **ret;
size_t k = 0, l = 0;
l = strv_length(argv);
@ -832,7 +822,6 @@ int setenv_systemd_exec_pid(bool update_only) {
int getenv_path_list(const char *name, char ***ret_paths) {
_cleanup_strv_free_ char **l = NULL;
const char *e;
char **p;
int r;
assert(name);

View File

@ -549,7 +549,6 @@ char* quote_command_line(char **argv, ShellEscapeFlags flags) {
assert(argv);
char **a;
STRV_FOREACH(a, argv) {
_cleanup_free_ char *t = NULL;

View File

@ -1042,8 +1042,6 @@ static int search_and_fopen_internal(
FILE **ret,
char **ret_path) {
char **i;
assert(path);
assert(mode);
assert(ret);

View File

@ -1864,7 +1864,6 @@ int _set_put_strdup_full(Set **s, const struct hash_ops *hash_ops, const char *p
int _set_put_strdupv_full(Set **s, const struct hash_ops *hash_ops, char **l HASHMAP_DEBUG_PARAMS) {
int n = 0, r;
char **i;
assert(s);

View File

@ -136,33 +136,39 @@
#define LIST_JUST_US(name,item) \
(!(item)->name##_prev && !(item)->name##_next)
/* The type of the iterator 'i' is automatically determined by the type of 'head', and declared in the
* loop. Hence, do not declare the same variable in the outer scope. Sometimes, we set 'head' through
* hashmap_get(). In that case, you need to explicitly cast the result. */
#define LIST_FOREACH_WITH_NEXT(name,i,n,head) \
for (typeof(*(head)) *n, *i = (head); i && (n = i->name##_next, true); i = n)
#define LIST_FOREACH(name,i,head) \
for ((i) = (head); (i); (i) = (i)->name##_next)
LIST_FOREACH_WITH_NEXT(name, i, UNIQ_T(n, UNIQ), head)
#define LIST_FOREACH_SAFE(name,i,n,head) \
for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n))
#define _LIST_FOREACH_WITH_PREV(name,i,p,start) \
for (typeof(*(start)) *p, *i = (start); i && (p = i->name##_prev, true); i = p)
#define LIST_FOREACH_BACKWARDS(name,i,p) \
for ((i) = (p); (i); (i) = (i)->name##_prev)
#define LIST_FOREACH_BACKWARDS(name,i,start) \
_LIST_FOREACH_WITH_PREV(name, i, UNIQ_T(p, UNIQ), start)
/* Iterate through all the members of the list p is included in, but skip over p */
#define LIST_FOREACH_OTHERS(name,i,p) \
for (({ \
(i) = (p); \
while ((i) && (i)->name##_prev) \
(i) = (i)->name##_prev; \
if ((i) == (p)) \
(i) = (p)->name##_next; \
}); \
(i); \
(i) = (i)->name##_next == (p) ? (p)->name##_next : (i)->name##_next)
for (typeof(*(p)) *_p = (p), *i = ({ \
typeof(*_p) *_j = _p; \
while (_j && _j->name##_prev) \
_j = _j->name##_prev; \
if (_j == _p) \
_j = _p->name##_next; \
_j; \
}); \
i; \
i = i->name##_next == _p ? _p->name##_next : i->name##_next)
/* Loop starting from p->next until p->prev.
p can be adjusted meanwhile. */
/* Loop starting from p->next until p->prev. p can be adjusted meanwhile. */
#define LIST_LOOP_BUT_ONE(name,i,head,p) \
for ((i) = (p)->name##_next ? (p)->name##_next : (head); \
(i) != (p); \
(i) = (i)->name##_next ? (i)->name##_next : (head))
for (typeof(*(p)) *i = (p)->name##_next ? (p)->name##_next : (head); \
i != (p); \
i = i->name##_next ? i->name##_next : (head))
#define LIST_IS_EMPTY(head) \
(!(head))

View File

@ -58,7 +58,6 @@ int _ordered_set_put_strdup(OrderedSet **s, const char *p HASHMAP_DEBUG_PARAMS)
int _ordered_set_put_strdupv(OrderedSet **s, char **l HASHMAP_DEBUG_PARAMS) {
int n = 0, r;
char **i;
STRV_FOREACH(i, l) {
r = _ordered_set_put_strdup(s, *i HASHMAP_DEBUG_PASS_ARGS);

View File

@ -273,7 +273,6 @@ int load_os_release_pairs(const char *root, char ***ret) {
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret) {
_cleanup_strv_free_ char **os_release_pairs = NULL, **os_release_pairs_prefixed = NULL;
char **p, **q;
int r;
r = load_os_release_pairs(root, &os_release_pairs);

View File

@ -463,7 +463,6 @@ static int patch_root_prefix(char **p, const char *root_dir) {
}
static int patch_root_prefix_strv(char **l, const char *root_dir) {
char **i;
int r;
if (!root_dir)

View File

@ -202,9 +202,9 @@ int path_make_relative(const char *from, const char *to, char **ret) {
}
char* path_startswith_strv(const char *p, char **set) {
char **s, *t;
STRV_FOREACH(s, set) {
char *t;
t = path_startswith(p, *s);
if (t)
return t;
@ -214,7 +214,6 @@ char* path_startswith_strv(const char *p, char **set) {
}
int path_strv_make_absolute_cwd(char **l) {
char **s;
int r;
/* Goes through every item in the string list and makes it
@ -236,7 +235,6 @@ int path_strv_make_absolute_cwd(char **l) {
}
char **path_strv_resolve(char **l, const char *root) {
char **s;
unsigned k = 0;
bool enomem = false;
int r;
@ -700,12 +698,12 @@ int find_executable_full(const char *name, const char *root, char **exec_search_
p = DEFAULT_PATH;
if (exec_search_path) {
char **element;
STRV_FOREACH(element, exec_search_path) {
_cleanup_free_ char *full_path = NULL;
if (!path_is_absolute(*element))
continue;
full_path = path_join(*element, name);
if (!full_path)
return -ENOMEM;
@ -754,7 +752,6 @@ int find_executable_full(const char *name, const char *root, char **exec_search_
bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool update) {
bool changed = false, originally_unset;
const char* const* i;
assert(timestamp);
@ -1339,7 +1336,7 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
_cleanup_strv_free_ char **names = NULL;
_cleanup_free_ char *path = NULL;
char *c, **name;
char *c;
path = path_join(root, pattern);
if (!path)
@ -1411,8 +1408,6 @@ bool empty_or_root(const char *path) {
}
bool path_strv_contains(char **l, const char *path) {
char **i;
STRV_FOREACH(i, l)
if (path_equal(*i, path))
return true;
@ -1421,10 +1416,9 @@ bool path_strv_contains(char **l, const char *path) {
}
bool prefixed_path_strv_contains(char **l, const char *path) {
char **i, *j;
STRV_FOREACH(i, l) {
j = *i;
const char *j = *i;
if (*j == '-')
j++;
if (*j == '+')

View File

@ -215,7 +215,6 @@ int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags
assert(!(flags & PROCESS_CMDLINE_USE_LOCALE));
_cleanup_strv_free_ char **args = NULL;
char **p;
args = strv_parse_nulstr(t, k);
if (!args)

View File

@ -17,8 +17,6 @@
#include "strv.h"
char* strv_find(char * const *l, const char *name) {
char * const *i;
assert(name);
STRV_FOREACH(i, l)
@ -29,8 +27,6 @@ char* strv_find(char * const *l, const char *name) {
}
char* strv_find_case(char * const *l, const char *name) {
char * const *i;
assert(name);
STRV_FOREACH(i, l)
@ -41,8 +37,6 @@ char* strv_find_case(char * const *l, const char *name) {
}
char* strv_find_prefix(char * const *l, const char *name) {
char * const *i;
assert(name);
STRV_FOREACH(i, l)
@ -53,14 +47,14 @@ char* strv_find_prefix(char * const *l, const char *name) {
}
char* strv_find_startswith(char * const *l, const char *name) {
char * const *i, *e;
assert(name);
/* Like strv_find_prefix, but actually returns only the
* suffix, not the whole item */
STRV_FOREACH(i, l) {
char *e;
e = startswith(*i, name);
if (e)
return e;
@ -70,8 +64,6 @@ char* strv_find_startswith(char * const *l, const char *name) {
}
char** strv_free(char **l) {
char **k;
STRV_FOREACH(k, l)
free(*k);
@ -79,8 +71,6 @@ char** strv_free(char **l) {
}
char** strv_free_erase(char **l) {
char **i;
STRV_FOREACH(i, l)
erase_and_freep(i);
@ -89,7 +79,7 @@ char** strv_free_erase(char **l) {
char** strv_copy(char * const *l) {
_cleanup_strv_free_ char **result = NULL;
char **k, * const *i;
char **k;
result = new(char*, strv_length(l) + 1);
if (!result)
@ -108,7 +98,6 @@ char** strv_copy(char * const *l) {
}
size_t strv_length(char * const *l) {
char * const *i;
size_t n = 0;
STRV_FOREACH(i, l)
@ -168,8 +157,8 @@ char** strv_new_internal(const char *x, ...) {
}
int strv_extend_strv(char ***a, char * const *b, bool filter_duplicates) {
char * const *s, **t;
size_t p, q, i = 0;
char **t;
assert(a);
@ -214,7 +203,6 @@ rollback:
}
int strv_extend_strv_concat(char ***a, char * const *b, const char *suffix) {
char * const *s;
int r;
STRV_FOREACH(s, b) {
@ -364,7 +352,6 @@ int strv_split_colon_pairs(char ***t, const char *s) {
}
char* strv_join_full(char * const *l, const char *separator, const char *prefix, bool unescape_separators) {
char * const *s;
char *r, *e;
size_t n, k, m;
@ -592,8 +579,6 @@ int strv_extend_front(char ***l, const char *value) {
}
char** strv_uniq(char **l) {
char **i;
/* Drops duplicate entries. The first identical string will be
* kept, the others dropped */
@ -604,8 +589,6 @@ char** strv_uniq(char **l) {
}
bool strv_is_uniq(char * const *l) {
char * const *i;
STRV_FOREACH(i, l)
if (strv_contains(i+1, *i))
return false;
@ -714,7 +697,6 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
*/
_cleanup_free_ char *m = NULL;
char * const *i;
size_t n = 0;
assert(ret);
@ -751,8 +733,6 @@ int strv_make_nulstr(char * const *l, char **ret, size_t *ret_size) {
}
bool strv_overlap(char * const *a, char * const *b) {
char * const *i;
STRV_FOREACH(i, a)
if (strv_contains(b, *i))
return true;
@ -792,8 +772,6 @@ int strv_compare(char * const *a, char * const *b) {
}
void strv_print(char * const *l) {
char * const *s;
STRV_FOREACH(s, l)
puts(*s);
}
@ -827,8 +805,6 @@ char** strv_reverse(char **l) {
}
char** strv_shell_escape(char **l, const char *bad) {
char **s;
/* Escapes every character in every string in l that is in bad,
* edits in-place, does not roll-back on error. */
@ -911,7 +887,6 @@ rollback:
int fputstrv(FILE *f, char * const *l, const char *separator, bool *space) {
bool b = false;
char * const *s;
int r;
/* Like fputs(), but for strv, and with a less stupid argument order */

View File

@ -122,19 +122,30 @@ static inline int strv_from_nulstr(char ***a, const char *nulstr) {
bool strv_overlap(char * const *a, char * const *b) _pure_;
#define _STRV_FOREACH(s, l, i) \
for (typeof(*(l)) *s, *i = (l); (s = i) && *i; i++)
#define STRV_FOREACH(s, l) \
for ((s) = (l); (s) && *(s); (s)++)
_STRV_FOREACH(s, l, UNIQ_T(i, UNIQ))
#define STRV_FOREACH_BACKWARDS(s, l) \
for (s = ({ \
typeof(l) _l = l; \
_l ? _l + strv_length(_l) - 1U : NULL; \
}); \
(l) && ((s) >= (l)); \
(s)--)
#define _STRV_FOREACH_BACKWARDS(s, l, h, i) \
for (typeof(*(l)) *s, *h = (l), *i = ({ \
size_t _len = strv_length(h); \
_len > 0 ? h + _len - 1 : NULL; \
}); \
(s = i); \
i > h ? i-- : (i = NULL))
#define STRV_FOREACH_PAIR(x, y, l) \
for ((x) = (l), (y) = (x) ? (x+1) : NULL; (x) && *(x) && *(y); (x) += 2, (y) = (x + 1))
#define STRV_FOREACH_BACKWARDS(s, l) \
_STRV_FOREACH_BACKWARDS(s, l, UNIQ_T(h, UNIQ), UNIQ_T(i, UNIQ))
#define _STRV_FOREACH_PAIR(x, y, l, i) \
for (typeof(*l) *x, *y, *i = (l); \
i && *(x = i) && *(y = i + 1); \
i += 2)
#define STRV_FOREACH_PAIR(x, y, l) \
_STRV_FOREACH_PAIR(x, y, l, UNIQ_T(i, UNIQ))
char** strv_sort(char **l);
void strv_print(char * const *l);
@ -185,7 +196,7 @@ void strv_print(char * const *l);
#define STARTSWITH_SET(p, ...) \
({ \
const char *_p = (p); \
char *_found = NULL, **_i; \
char *_found = NULL; \
STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \
_found = startswith(_p, *_i); \
if (_found) \
@ -197,7 +208,7 @@ void strv_print(char * const *l);
#define ENDSWITH_SET(p, ...) \
({ \
const char *_p = (p); \
char *_found = NULL, **_i; \
char *_found = NULL; \
STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \
_found = endswith(_p, *_i); \
if (_found) \

View File

@ -209,8 +209,7 @@ bool lookup_paths_timestamp_hash_same(const LookupPaths *lp, uint64_t timestamp_
siphash24_init(&state, HASH_KEY.bytes);
char **dir;
STRV_FOREACH(dir, (char**) lp->search_path) {
STRV_FOREACH(dir, lp->search_path) {
struct stat st;
if (lookup_paths_mtime_exclude(lp, *dir))
@ -281,7 +280,6 @@ int unit_file_build_name_map(
_cleanup_hashmap_free_ Hashmap *ids = NULL, *names = NULL;
_cleanup_set_free_free_ Set *paths = NULL;
uint64_t timestamp_hash;
char **dir;
int r;
/* Before doing anything, check if the timestamp hash that was passed is still valid.
@ -299,7 +297,7 @@ int unit_file_build_name_map(
return log_oom();
}
STRV_FOREACH(dir, (char**) lp->search_path) {
STRV_FOREACH(dir, lp->search_path) {
_cleanup_closedir_ DIR *d = NULL;
d = opendir(*dir);
@ -550,7 +548,7 @@ static int add_names(
Set **names,
const char *name) {
char **aliases, **alias;
char **aliases;
int r;
assert(name_type == UNIT_NAME_PLAIN || instance);

View File

@ -213,7 +213,6 @@ static int run(int argc, char *argv[]) {
}
else {
_cleanup_strv_free_ char **files = NULL;
char **f;
r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("binfmt.d"));
if (r < 0)

View File

@ -325,7 +325,6 @@ static const char *skip_slash(const char *path) {
static int verb_status(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL;
uint64_t left, done;
char **p;
int r;
r = acquire_boot_count_path(&path, &prefix, &left, &done, &suffix);
@ -402,7 +401,6 @@ static int verb_set(int argc, char *argv[], void *userdata) {
_cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL, *parent = NULL;
const char *target, *source1, *source2;
uint64_t done;
char **p;
int r;
r = acquire_boot_count_path(&path, &prefix, NULL, &done, &suffix);

View File

@ -602,7 +602,6 @@ static int boot_entry_show(
if (e->kernel)
boot_entry_file_list("linux", e->root, e->kernel, &status);
char **s;
STRV_FOREACH(s, e->initrd)
boot_entry_file_list(s == e->initrd ? "initrd" : NULL,
e->root,
@ -843,7 +842,6 @@ static const char *const dollar_boot_subdirs[] = {
};
static int create_subdirs(const char *root, const char * const *subdirs) {
const char *const *i;
int r;
STRV_FOREACH(i, subdirs) {

View File

@ -143,7 +143,7 @@ static int list_bus_names(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_hashmap_free_ Hashmap *names = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
char **i, *k;
char *k;
void *v;
int r;
@ -504,7 +504,6 @@ static int tree_one(sd_bus *bus, const char *service) {
static int tree(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
char **i;
int r;
/* Do superficial verification of arguments before even opening the bus */
@ -1208,7 +1207,6 @@ static int monitor(int argc, char **argv, int (*dump)(sd_bus_message *m, FILE *f
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char **i;
uint32_t flags = 0;
const char *unique_name;
bool is_monitor = false;
@ -2124,7 +2122,6 @@ static int emit_signal(int argc, char **argv, void *userdata) {
static int get_property(int argc, char **argv, void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
char **i;
int r;
r = acquire_bus(false, &bus);

View File

@ -201,7 +201,6 @@ static int run(int argc, char *argv[]) {
if (arg_names) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_free_ char *root = NULL;
char **name;
STRV_FOREACH(name, arg_names) {
int q;

View File

@ -605,8 +605,6 @@ int bpf_firewall_compile(Unit *u) {
}
static int load_bpf_progs_from_fs_to_set(Unit *u, char **filter_paths, Set **set) {
char **bpf_fs_path;
set_clear(*set);
STRV_FOREACH(bpf_fs_path, filter_paths) {

View File

@ -123,7 +123,6 @@ static int bpf_foreign_prepare(
int bpf_foreign_install(Unit *u) {
_cleanup_free_ char *cgroup_path = NULL;
CGroupBPFForeignProgram *p;
CGroupContext *cc;
int r;

View File

@ -27,7 +27,6 @@ static int update_rules_map(
int map_fd,
CGroupSocketBindItem *head) {
CGroupSocketBindItem *item;
uint32_t i = 0;
assert(map_fd >= 0);
@ -58,7 +57,6 @@ static int prepare_socket_bind_bpf(
_cleanup_(socket_bind_bpf_freep) struct socket_bind_bpf *obj = NULL;
size_t allow_count = 0, deny_count = 0;
int allow_map_fd, deny_map_fd, r;
CGroupSocketBindItem *item;
assert(ret_obj);

View File

@ -414,17 +414,8 @@ static char *format_cgroup_memory_limit_comparison(char *buf, size_t l, Unit *u,
void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
_cleanup_free_ char *disable_controllers_str = NULL, *cpuset_cpus = NULL, *cpuset_mems = NULL, *startup_cpuset_cpus = NULL, *startup_cpuset_mems = NULL;
CGroupIODeviceLimit *il;
CGroupIODeviceWeight *iw;
CGroupIODeviceLatency *l;
CGroupBlockIODeviceBandwidth *b;
CGroupBlockIODeviceWeight *w;
CGroupBPFForeignProgram *p;
CGroupDeviceAllow *a;
CGroupContext *c;
CGroupSocketBindItem *bi;
struct in_addr_prefix *iaai;
char **path;
char cda[FORMAT_CGROUP_DIFF_MAX];
char cdb[FORMAT_CGROUP_DIFF_MAX];
@ -1219,7 +1210,6 @@ static int cgroup_apply_devices(Unit *u) {
_cleanup_(bpf_program_freep) BPFProgram *prog = NULL;
const char *path;
CGroupContext *c;
CGroupDeviceAllow *a;
CGroupDevicePolicy policy;
int r;
@ -1440,10 +1430,6 @@ static void cgroup_context_apply(
set_io_weight(u, weight);
if (has_io) {
CGroupIODeviceLatency *latency;
CGroupIODeviceLimit *limit;
CGroupIODeviceWeight *w;
LIST_FOREACH(device_weights, w, c->io_device_weights)
cgroup_apply_io_device_weight(u, w->path, w->weight);
@ -1454,9 +1440,6 @@ static void cgroup_context_apply(
cgroup_apply_io_device_latency(u, latency->path, latency->target_usec);
} else if (has_blockio) {
CGroupBlockIODeviceWeight *w;
CGroupBlockIODeviceBandwidth *b;
LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
weight = cgroup_weight_blkio_to_io(w->weight);
@ -1509,9 +1492,7 @@ static void cgroup_context_apply(
set_blkio_weight(u, weight);
if (has_io) {
CGroupIODeviceWeight *w;
if (has_io)
LIST_FOREACH(device_weights, w, c->io_device_weights) {
weight = cgroup_weight_io_to_blkio(w->weight);
@ -1520,32 +1501,24 @@ static void cgroup_context_apply(
cgroup_apply_blkio_device_weight(u, w->path, weight);
}
} else if (has_blockio) {
CGroupBlockIODeviceWeight *w;
else if (has_blockio)
LIST_FOREACH(device_weights, w, c->blockio_device_weights)
cgroup_apply_blkio_device_weight(u, w->path, w->weight);
}
}
/* The bandwidth limits are something that make sense to be applied to the host's root but not container
* roots, as there we want the container manager to handle it */
if (is_host_root || !is_local_root) {
if (has_io) {
CGroupIODeviceLimit *l;
if (has_io)
LIST_FOREACH(device_limits, l, c->io_device_limits) {
log_cgroup_compat(u, "Applying IO{Read|Write}Bandwidth=%" PRIu64 " %" PRIu64 " as BlockIO{Read|Write}BandwidthMax= for %s",
l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX], l->path);
cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]);
}
} else if (has_blockio) {
CGroupBlockIODeviceBandwidth *b;
else if (has_blockio)
LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths)
cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps);
}
}
}

View File

@ -157,9 +157,7 @@ static int build_managed_oom_cgroups_json(Manager *m, JsonVariant **ret) {
if (r < 0)
return r;
for (size_t i = 0; i < ELEMENTSOF(supported_unit_types); i++) {
Unit *u;
for (size_t i = 0; i < ELEMENTSOF(supported_unit_types); i++)
LIST_FOREACH(units_by_type, u, m->units_by_type[supported_unit_types[i]]) {
CGroupContext *c;
@ -188,7 +186,6 @@ static int build_managed_oom_cgroups_json(Manager *m, JsonVariant **ret) {
return r;
}
}
}
r = json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("cgroups", JSON_BUILD_VARIANT(arr))));
if (r < 0)

View File

@ -112,7 +112,6 @@ static int property_get_io_device_weight(
sd_bus_error *error) {
CGroupContext *c = userdata;
CGroupIODeviceWeight *w;
int r;
assert(bus);
@ -142,7 +141,6 @@ static int property_get_io_device_limits(
sd_bus_error *error) {
CGroupContext *c = userdata;
CGroupIODeviceLimit *l;
int r;
assert(bus);
@ -178,7 +176,6 @@ static int property_get_io_device_latency(
sd_bus_error *error) {
CGroupContext *c = userdata;
CGroupIODeviceLatency *l;
int r;
assert(bus);
@ -208,7 +205,6 @@ static int property_get_blockio_device_weight(
sd_bus_error *error) {
CGroupContext *c = userdata;
CGroupBlockIODeviceWeight *w;
int r;
assert(bus);
@ -238,7 +234,6 @@ static int property_get_blockio_device_bandwidths(
sd_bus_error *error) {
CGroupContext *c = userdata;
CGroupBlockIODeviceBandwidth *b;
int r;
assert(bus);
@ -278,7 +273,6 @@ static int property_get_device_allow(
sd_bus_error *error) {
CGroupContext *c = userdata;
CGroupDeviceAllow *a;
int r;
assert(bus);
@ -364,7 +358,6 @@ static int property_get_bpf_foreign_program(
void *userdata,
sd_bus_error *error) {
CGroupContext *c = userdata;
CGroupBPFForeignProgram *p;
int r;
r = sd_bus_message_open_container(reply, 'a', "(ss)");
@ -390,7 +383,8 @@ static int property_get_socket_bind(
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
CGroupSocketBindItem **items = userdata, *i;
CGroupSocketBindItem **items = userdata;
int r;
assert(items);
@ -640,7 +634,6 @@ static int bus_cgroup_set_transient_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
char **entry;
size_t size = 0;
if (n == 0)
@ -720,7 +713,6 @@ static int bus_cgroup_set_transient_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
CGroupBPFForeignProgram *fp;
size_t size = 0;
if (n == 0)
@ -1228,14 +1220,13 @@ int bus_cgroup_set_property(
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupIODeviceLimit *a = NULL, *b;
CGroupIODeviceLimit *a = NULL;
LIST_FOREACH(device_limits, b, c->io_device_limits) {
LIST_FOREACH(device_limits, b, c->io_device_limits)
if (path_equal(path, b->path)) {
a = b;
break;
}
}
if (!a) {
CGroupIOLimitType type;
@ -1269,15 +1260,13 @@ int bus_cgroup_set_property(
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupIODeviceLimit *a;
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
size_t size = 0;
if (n == 0) {
if (n == 0)
LIST_FOREACH(device_limits, a, c->io_device_limits)
a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
}
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
@ -1287,8 +1276,8 @@ int bus_cgroup_set_property(
fprintf(f, "%s=\n", name);
LIST_FOREACH(device_limits, a, c->io_device_limits)
if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
r = fflush_and_check(f);
if (r < 0)
@ -1316,14 +1305,13 @@ int bus_cgroup_set_property(
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupIODeviceWeight *a = NULL, *b;
CGroupIODeviceWeight *a = NULL;
LIST_FOREACH(device_weights, b, c->io_device_weights) {
LIST_FOREACH(device_weights, b, c->io_device_weights)
if (path_equal(b->path, path)) {
a = b;
break;
}
}
if (!a) {
a = new0(CGroupIODeviceWeight, 1);
@ -1351,13 +1339,11 @@ int bus_cgroup_set_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
CGroupIODeviceWeight *a;
size_t size = 0;
if (n == 0) {
if (n == 0)
while (c->io_device_weights)
cgroup_context_free_io_device_weight(c, c->io_device_weights);
}
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
@ -1392,14 +1378,13 @@ int bus_cgroup_set_property(
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupIODeviceLatency *a = NULL, *b;
CGroupIODeviceLatency *a = NULL;
LIST_FOREACH(device_latencies, b, c->io_device_latencies) {
LIST_FOREACH(device_latencies, b, c->io_device_latencies)
if (path_equal(b->path, path)) {
a = b;
break;
}
}
if (!a) {
a = new0(CGroupIODeviceLatency, 1);
@ -1427,13 +1412,11 @@ int bus_cgroup_set_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
CGroupIODeviceLatency *a;
size_t size = 0;
if (n == 0) {
if (n == 0)
while (c->io_device_latencies)
cgroup_context_free_io_device_latency(c, c->io_device_latencies);
}
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
@ -1473,14 +1456,13 @@ int bus_cgroup_set_property(
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupBlockIODeviceBandwidth *a = NULL, *b;
CGroupBlockIODeviceBandwidth *a = NULL;
LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths)
if (path_equal(path, b->path)) {
a = b;
break;
}
}
if (!a) {
a = new0(CGroupBlockIODeviceBandwidth, 1);
@ -1514,19 +1496,17 @@ int bus_cgroup_set_property(
return r;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupBlockIODeviceBandwidth *a;
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
size_t size = 0;
if (n == 0) {
if (n == 0)
LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) {
if (read)
a->rbps = CGROUP_LIMIT_MAX;
else
a->wbps = CGROUP_LIMIT_MAX;
}
}
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
@ -1573,14 +1553,13 @@ int bus_cgroup_set_property(
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupBlockIODeviceWeight *a = NULL, *b;
CGroupBlockIODeviceWeight *a = NULL;
LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
LIST_FOREACH(device_weights, b, c->blockio_device_weights)
if (path_equal(b->path, path)) {
a = b;
break;
}
}
if (!a) {
a = new0(CGroupBlockIODeviceWeight, 1);
@ -1608,13 +1587,11 @@ int bus_cgroup_set_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
CGroupBlockIODeviceWeight *a;
size_t size = 0;
if (n == 0) {
if (n == 0)
while (c->blockio_device_weights)
cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
}
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
@ -1674,14 +1651,13 @@ int bus_cgroup_set_property(
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
CGroupDeviceAllow *a = NULL, *b;
CGroupDeviceAllow *a = NULL;
LIST_FOREACH(device_allow, b, c->device_allow) {
LIST_FOREACH(device_allow, b, c->device_allow)
if (path_equal(b->path, path)) {
a = b;
break;
}
}
if (!a) {
a = new0(CGroupDeviceAllow, 1);
@ -1714,13 +1690,11 @@ int bus_cgroup_set_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
CGroupDeviceAllow *a;
size_t size = 0;
if (n == 0) {
if (n == 0)
while (c->device_allow)
cgroup_context_free_device_allow(c, c->device_allow);
}
unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
@ -1995,7 +1969,6 @@ int bus_cgroup_set_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
CGroupSocketBindItem *item;
size_t size = 0;
if (n == 0)
@ -2050,7 +2023,6 @@ int bus_cgroup_set_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *joined = NULL;
char **s;
if (strv_isempty(l)) {
c->restrict_network_interfaces_is_allow_list = false;

View File

@ -74,7 +74,6 @@ static int property_get_environment_files(
sd_bus_error *error) {
ExecContext *c = userdata;
char **j;
int r;
assert(bus);
@ -960,7 +959,6 @@ static int property_get_root_image_options(
sd_bus_error *error) {
ExecContext *c = userdata;
MountOptions *m;
int r;
assert(bus);
@ -1005,8 +1003,6 @@ static int property_get_mount_images(
return r;
for (size_t i = 0; i < c->n_mount_images; i++) {
MountOptions *m;
r = sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "ssba(ss)");
if (r < 0)
return r;
@ -1060,8 +1056,6 @@ static int property_get_extension_images(
return r;
for (size_t i = 0; i < c->n_extension_images; i++) {
MountOptions *m;
r = sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "sba(ss)");
if (r < 0)
return r;
@ -1143,15 +1137,12 @@ static int bus_property_get_exec_dir_symlink(
if (r < 0)
return r;
for (size_t i = 0; i < d->n_items; i++) {
char **dst;
for (size_t i = 0; i < d->n_items; i++)
STRV_FOREACH(dst, d->items[i].symlinks) {
r = sd_bus_message_append(reply, "(sst)", d->items[i].path, *dst, 0 /* flags, unused for now */);
if (r < 0)
return r;
}
}
return sd_bus_message_close_container(reply);
}
@ -1449,7 +1440,7 @@ int bus_property_get_exec_command_list(
void *userdata,
sd_bus_error *ret_error) {
ExecCommand *c = *(ExecCommand**) userdata;
ExecCommand *exec_command = *(ExecCommand**) userdata;
int r;
assert(bus);
@ -1459,7 +1450,7 @@ int bus_property_get_exec_command_list(
if (r < 0)
return r;
LIST_FOREACH(command, c, c) {
LIST_FOREACH(command, c, exec_command) {
r = append_exec_command(reply, c);
if (r < 0)
return r;
@ -1477,7 +1468,7 @@ int bus_property_get_exec_ex_command_list(
void *userdata,
sd_bus_error *ret_error) {
ExecCommand *c, *exec_command = *(ExecCommand**) userdata;
ExecCommand *exec_command = *(ExecCommand**) userdata;
int r;
assert(bus);
@ -1587,7 +1578,6 @@ int bus_set_transient_exec_command(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL;
ExecCommand *c;
size_t size = 0;
if (n == 0)
@ -2022,7 +2012,6 @@ int bus_exec_context_set_transient_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *joined = NULL;
FilesystemParseFlags invert_flag = allow_list ? 0 : FILESYSTEM_PARSE_INVERT;
char **s;
if (strv_isempty(l)) {
c->restrict_filesystems_allow_list = false;
@ -2068,7 +2057,6 @@ int bus_exec_context_set_transient_property(
if (streq(name, "SupplementaryGroups")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
@ -2433,7 +2421,6 @@ int bus_exec_context_set_transient_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *joined = NULL;
SeccompParseFlags invert_flag = allow_list ? 0 : SECCOMP_PARSE_INVERT;
char **s;
if (strv_isempty(l)) {
c->syscall_allow_list = false;
@ -2518,7 +2505,6 @@ int bus_exec_context_set_transient_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *joined = NULL;
SeccompParseFlags invert_flag = allow_list ? 0 : SECCOMP_PARSE_INVERT;
char **s;
if (strv_isempty(l)) {
c->syscall_log_allow_list = false;
@ -2570,9 +2556,7 @@ int bus_exec_context_set_transient_property(
if (strv_isempty(l))
c->syscall_archs = set_free(c->syscall_archs);
else {
char **s;
else
STRV_FOREACH(s, l) {
uint32_t a;
@ -2585,8 +2569,6 @@ int bus_exec_context_set_transient_property(
return r;
}
}
joined = strv_join(l, " ");
if (!joined)
return -ENOMEM;
@ -2618,7 +2600,6 @@ int bus_exec_context_set_transient_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *joined = NULL;
char **s;
if (strv_isempty(l)) {
c->address_families_allow_list = allow_list;
@ -3147,7 +3128,6 @@ int bus_exec_context_set_transient_property(
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **l = NULL;
size_t size = 0;
char **i;
r = sd_bus_message_enter_container(message, 'a', "(sb)");
if (r < 0)
@ -3266,7 +3246,6 @@ int bus_exec_context_set_transient_property(
"ExtensionDirectories")) {
_cleanup_strv_free_ char **l = NULL;
char ***dirs;
char **p;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
@ -3320,16 +3299,15 @@ int bus_exec_context_set_transient_property(
} else if (streq(name, "ExecSearchPath")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
STRV_FOREACH(p, l) {
STRV_FOREACH(p, l)
if (!path_is_absolute(*p) || !path_is_normalized(*p) || strchr(*p, ':'))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
}
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (strv_isempty(l)) {
c->exec_search_path = strv_free(c->exec_search_path);
@ -3350,7 +3328,6 @@ int bus_exec_context_set_transient_property(
} else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
@ -3379,7 +3356,6 @@ int bus_exec_context_set_transient_property(
unit_write_settingf(u, flags, name, "%s=", name);
} else {
_cleanup_free_ char *joined = NULL;
char **source;
STRV_FOREACH(source, l) {
r = exec_directory_add(&d->items, &d->n_items, *source, NULL);

View File

@ -890,7 +890,6 @@ static int method_list_units_by_names(sd_bus_message *message, void *userdata, s
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
int r;
char **unit;
_cleanup_strv_free_ char **units = NULL;
assert(message);

View File

@ -22,7 +22,6 @@ static int property_get_paths(
sd_bus_error *error) {
Path *p = userdata;
PathSpec *k;
int r;
assert(bus);

View File

@ -32,7 +32,6 @@ static int property_get_listen(
sd_bus_error *error) {
Socket *s = SOCKET(userdata);
SocketPort *p;
int r;
assert(bus);
@ -326,16 +325,14 @@ static int bus_socket_set_transient_property(
if (streq(name, "Symlinks")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
STRV_FOREACH(p, l) {
STRV_FOREACH(p, l)
if (!path_is_absolute(*p))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Symlink path is not absolute: %s", *p);
}
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (strv_isempty(l)) {

View File

@ -20,7 +20,6 @@ static int property_get_monotonic_timers(
sd_bus_error *error) {
Timer *t = userdata;
TimerValue *v;
int r;
assert(bus);
@ -69,7 +68,6 @@ static int property_get_calendar_timers(
sd_bus_error *error) {
Timer *t = userdata;
TimerValue *v;
int r;
assert(bus);

View File

@ -273,7 +273,7 @@ static int property_get_conditions(
sd_bus_error *error) {
const char *(*to_string)(ConditionType type) = NULL;
Condition **list = userdata, *c;
Condition **list = userdata;
int r;
assert(bus);
@ -2242,16 +2242,14 @@ static int bus_unit_set_transient_property(
if (streq(name, "Documentation")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)
return r;
STRV_FOREACH(p, l) {
STRV_FOREACH(p, l)
if (!documentation_url_is_valid(*p))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid URL in %s: %s", name, *p);
}
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
if (strv_isempty(l)) {
@ -2307,7 +2305,6 @@ static int bus_unit_set_transient_property(
} else if (streq(name, "RequiresMountsFor")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
r = sd_bus_message_read_strv(message, &l);
if (r < 0)

View File

@ -307,13 +307,9 @@ static void device_dump(Unit *u, FILE *f, const char *prefix) {
prefix, strna(d->sysfs),
prefix, strna(s));
if (!strv_isempty(d->wants_property)) {
char **i;
STRV_FOREACH(i, d->wants_property)
fprintf(f, "%sudev SYSTEMD_WANTS: %s\n",
prefix, *i);
}
STRV_FOREACH(i, d->wants_property)
fprintf(f, "%sudev SYSTEMD_WANTS: %s\n",
prefix, *i);
}
_pure_ static UnitActiveState device_active_state(Unit *u) {
@ -419,9 +415,7 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) {
k = NULL;
}
if (d->state != DEVICE_DEAD) {
char **i;
if (d->state != DEVICE_DEAD)
/* So here's a special hack, to compensate for the fact that the udev database's reload cycles are not
* synchronized with our own reload cycles: when we detect that the SYSTEMD_WANTS property of a device
* changes while the device unit is already up, let's manually trigger any new units listed in it not
@ -431,7 +425,6 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) {
*
* We do this only if the device has been up already when we parse this, as otherwise the usual
* dependency logic that is run from the dead plugged transition will trigger these deps. */
STRV_FOREACH(i, added) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
@ -442,7 +435,6 @@ static int device_add_udev_wants(Unit *u, sd_device *dev) {
if (r < 0)
log_unit_warning_errno(u, r, "Failed to enqueue SYSTEMD_WANTS= job, ignoring: %s", bus_error_message(&error, r));
}
}
return strv_free_and_replace(d->wants_property, added);
}
@ -710,7 +702,7 @@ static void device_update_found_one(Device *d, DeviceFound found, DeviceFound ma
}
static void device_update_found_by_sysfs(Manager *m, const char *sysfs, DeviceFound found, DeviceFound mask) {
Device *d, *l, *n;
Device *l;
assert(m);
assert(sysfs);
@ -719,7 +711,7 @@ static void device_update_found_by_sysfs(Manager *m, const char *sysfs, DeviceFo
return;
l = hashmap_get(m->devices_by_sysfs, sysfs);
LIST_FOREACH_SAFE(same_sysfs, d, n, l)
LIST_FOREACH(same_sysfs, d, l)
device_update_found_one(d, found, mask);
}
@ -765,7 +757,7 @@ static bool device_is_ready(sd_device *dev) {
static Unit *device_following(Unit *u) {
Device *d = DEVICE(u);
Device *other, *first = NULL;
Device *first = NULL;
assert(d);
@ -788,7 +780,7 @@ static Unit *device_following(Unit *u) {
}
static int device_following_set(Unit *u, Set **_set) {
Device *d = DEVICE(u), *other;
Device *d = DEVICE(u);
_cleanup_set_free_ Set *set = NULL;
int r;
@ -898,14 +890,14 @@ fail:
}
static void device_propagate_reload_by_sysfs(Manager *m, const char *sysfs) {
Device *d, *l, *n;
Device *l;
int r;
assert(m);
assert(sysfs);
l = hashmap_get(m->devices_by_sysfs, sysfs);
LIST_FOREACH_SAFE(same_sysfs, d, n, l) {
LIST_FOREACH(same_sysfs, d, l) {
if (d->state == DEVICE_DEAD)
continue;

View File

@ -995,7 +995,6 @@ static int get_fixed_group(const ExecContext *c, const char **group, gid_t *gid)
static int get_supplementary_groups(const ExecContext *c, const char *user,
const char *group, gid_t gid,
gid_t **supplementary_gids, int *ngids) {
char **i;
int r, k = 0;
int ngroups_max;
bool keep_groups = false;
@ -1187,7 +1186,6 @@ static int setup_pam(
pam_handle_t *handle = NULL;
sigset_t old_ss;
int pam_code = PAM_SUCCESS, r;
char **nv;
bool close_session = false;
pid_t pam_pid = 0, parent_pid;
int flags = 0;
@ -2005,7 +2003,6 @@ static int build_environment(
static int build_pass_environment(const ExecContext *c, char ***ret) {
_cleanup_strv_free_ char **pass_env = NULL;
size_t n_env = 0;
char **i;
STRV_FOREACH(i, c->pass_environment) {
_cleanup_free_ char *x = NULL;
@ -2281,7 +2278,6 @@ static bool exec_directory_is_private(const ExecContext *context, ExecDirectoryT
static int create_many_symlinks(const char *root, const char *source, char **symlinks) {
_cleanup_free_ char *src_abs = NULL;
char **dst;
int r;
assert(source);
@ -3352,7 +3348,6 @@ static int compile_symlinks(
for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) {
for (size_t i = 0; i < context->directories[dt].n_items; i++) {
_cleanup_free_ char *private_path = NULL, *path = NULL;
char **symlink;
STRV_FOREACH(symlink, context->directories[dt].items[i].symlinks) {
_cleanup_free_ char *src_abs = NULL, *dst_abs = NULL;
@ -5349,7 +5344,6 @@ int exec_context_destroy_runtime_directory(const ExecContext *c, const char *run
* service next. */
(void) rm_rf(p, REMOVE_ROOT);
char **symlink;
STRV_FOREACH(symlink, c->directories[EXEC_DIRECTORY_RUNTIME].items[i].symlinks) {
_cleanup_free_ char *symlink_abs = NULL;
@ -5423,12 +5417,9 @@ void exec_command_reset_status_array(ExecCommand *c, size_t n) {
}
void exec_command_reset_status_list_array(ExecCommand **c, size_t n) {
for (size_t i = 0; i < n; i++) {
ExecCommand *z;
for (size_t i = 0; i < n; i++)
LIST_FOREACH(command, z, c[i])
exec_status_reset(&z->exec_status);
}
}
typedef struct InvalidEnvInfo {
@ -5523,7 +5514,6 @@ static int exec_context_named_iofds(
static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***ret) {
_cleanup_strv_free_ char **v = NULL;
char **i;
int r;
assert(c);
@ -5630,8 +5620,6 @@ bool exec_context_may_touch_console(const ExecContext *ec) {
}
static void strv_fprintf(FILE *f, char **l) {
char **g;
assert(f);
STRV_FOREACH(g, l)
@ -5651,7 +5639,6 @@ static void strv_dump(FILE* f, const char *prefix, const char *name, char **strv
}
void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
char **e, **d;
int r;
assert(c);
@ -5713,8 +5700,6 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
fprintf(f, "%sRootImage: %s\n", prefix, c->root_image);
if (c->root_image_options) {
MountOptions *o;
fprintf(f, "%sRootImageOptions:", prefix);
LIST_FOREACH(mount_options, o, c->root_image_options)
if (!isempty(o->options))
@ -6113,8 +6098,6 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
}
for (size_t i = 0; i < c->n_mount_images; i++) {
MountOptions *o;
fprintf(f, "%sMountImages: %s%s:%s", prefix,
c->mount_images[i].ignore_enoent ? "-": "",
c->mount_images[i].source,
@ -6127,8 +6110,6 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
}
for (size_t i = 0; i < c->n_extension_images; i++) {
MountOptions *o;
fprintf(f, "%sExtensionImages: %s%s", prefix,
c->extension_images[i].ignore_enoent ? "-": "",
c->extension_images[i].source);
@ -6280,7 +6261,6 @@ int exec_context_get_clean_directories(
return r;
}
char **symlink;
STRV_FOREACH(symlink, c->directories[t].items[i].symlinks) {
j = path_join(prefix[t], *symlink);
if (!j)
@ -6395,8 +6375,8 @@ void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
prefix = strempty(prefix);
LIST_FOREACH(command, c, c)
exec_command_dump(c, f, prefix);
LIST_FOREACH(command, i, c)
exec_command_dump(i, f, prefix);
}
void exec_command_append_list(ExecCommand **l, ExecCommand *e) {

View File

@ -13,7 +13,6 @@
static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suffix) {
_cleanup_strv_free_ char **paths = NULL;
char **p;
int r;
r = unit_file_find_dropin_paths(NULL,
@ -85,7 +84,6 @@ static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suff
int unit_load_dropin(Unit *u) {
_cleanup_strv_free_ char **l = NULL;
char **f;
int r;
assert(u);

View File

@ -1634,7 +1634,6 @@ int config_parse_root_image_options(
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
_cleanup_strv_free_ char **l = NULL;
char **first = NULL, **second = NULL;
ExecContext *c = data;
const Unit *u = userdata;
int r;
@ -4328,7 +4327,7 @@ int config_parse_io_limit(
void *userdata) {
_cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupIODeviceLimit *l = NULL, *t;
CGroupIODeviceLimit *l = NULL;
CGroupContext *c = data;
CGroupIOLimitType type;
const char *p = rvalue;
@ -4343,8 +4342,8 @@ int config_parse_io_limit(
assert(type >= 0);
if (isempty(rvalue)) {
LIST_FOREACH(device_limits, l, c->io_device_limits)
l->limits[type] = cgroup_io_limit_defaults[type];
LIST_FOREACH(device_limits, t, c->io_device_limits)
t->limits[type] = cgroup_io_limit_defaults[type];
return 0;
}
@ -4378,12 +4377,11 @@ int config_parse_io_limit(
}
}
LIST_FOREACH(device_limits, t, c->io_device_limits) {
LIST_FOREACH(device_limits, t, c->io_device_limits)
if (path_equal(resolved, t->path)) {
l = t;
break;
}
}
if (!l) {
CGroupIOLimitType ttype;
@ -4486,7 +4484,7 @@ int config_parse_blockio_bandwidth(
void *userdata) {
_cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupBlockIODeviceBandwidth *b = NULL, *t;
CGroupBlockIODeviceBandwidth *b = NULL;
CGroupContext *c = data;
const char *p = rvalue;
uint64_t bytes;
@ -4500,9 +4498,9 @@ int config_parse_blockio_bandwidth(
read = streq("BlockIOReadBandwidth", lvalue);
if (isempty(rvalue)) {
LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
b->rbps = CGROUP_LIMIT_MAX;
b->wbps = CGROUP_LIMIT_MAX;
LIST_FOREACH(device_bandwidths, t, c->blockio_device_bandwidths) {
t->rbps = CGROUP_LIMIT_MAX;
t->wbps = CGROUP_LIMIT_MAX;
}
return 0;
}
@ -4533,14 +4531,13 @@ int config_parse_blockio_bandwidth(
return 0;
}
LIST_FOREACH(device_bandwidths, t, c->blockio_device_bandwidths) {
LIST_FOREACH(device_bandwidths, t, c->blockio_device_bandwidths)
if (path_equal(resolved, t->path)) {
b = t;
break;
}
}
if (!t) {
if (!b) {
b = new0(CGroupBlockIODeviceBandwidth, 1);
if (!b)
return log_oom();

View File

@ -2319,7 +2319,6 @@ static void fallback_rlimit_memlock(const struct rlimit *saved_rlimit_memlock) {
}
static void setenv_manager_environment(void) {
char **p;
int r;
STRV_FOREACH(p, arg_manager_environment) {

View File

@ -1215,7 +1215,6 @@ static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
is_bad = false;
}
const UnitRef *ref;
LIST_FOREACH(refs_by_target, ref, u->refs_by_target) {
unit_gc_sweep(ref->source, gc_marker);
@ -3626,7 +3625,6 @@ void manager_check_finished(Manager *m) {
}
static bool generator_path_any(const char* const* paths) {
char **path;
bool found = false;
/* Optimize by skipping the whole process by not creating output directories

View File

@ -1957,7 +1957,6 @@ static int drain_libmount(Manager *m) {
static int mount_process_proc_self_mountinfo(Manager *m) {
_cleanup_set_free_free_ Set *around = NULL, *gone = NULL;
const char *what;
Unit *u;
int r;
assert(m);

View File

@ -314,8 +314,6 @@ static void mount_entry_done(MountEntry *p) {
}
static int append_access_mounts(MountEntry **p, char **strv, MountMode mode, bool forcibly_require_prefix) {
char **i;
assert(p);
/* Adds a list of user-supplied READWRITE/READWRITE_IMPLICIT/READONLY/INACCESSIBLE entries */
@ -350,8 +348,6 @@ static int append_access_mounts(MountEntry **p, char **strv, MountMode mode, boo
}
static int append_empty_dir_mounts(MountEntry **p, char **strv) {
char **i;
assert(p);
/* Adds tmpfs mounts to provide readable but empty directories. This is primarily used to implement the
@ -419,7 +415,6 @@ static int append_extensions(
char **extension_directories) {
_cleanup_strv_free_ char **overlays = NULL;
char **hierarchy, **extension_directory;
int r;
if (n == 0 && strv_isempty(extension_directories))
@ -1709,7 +1704,6 @@ static void drop_unused_mounts(const char *root_directory, MountEntry *mounts, s
}
static int create_symlinks_from_tuples(const char *root, char **strv_symlinks) {
char **src, **dst;
int r;
STRV_FOREACH_PAIR(src, dst, strv_symlinks) {
@ -2562,7 +2556,6 @@ MountImage* mount_image_free_many(MountImage *m, size_t *n) {
int mount_image_add(MountImage **m, size_t *n, const MountImage *item) {
_cleanup_free_ char *s = NULL, *d = NULL;
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
MountOptions *i;
MountImage *c;
assert(m);

View File

@ -292,7 +292,6 @@ static void path_done(Unit *u) {
}
static int path_add_mount_dependencies(Path *p) {
PathSpec *s;
int r;
assert(p);
@ -401,7 +400,6 @@ static int path_load(Unit *u) {
static void path_dump(Unit *u, FILE *f, const char *prefix) {
Path *p = PATH(u);
Unit *trigger;
PathSpec *s;
assert(p);
assert(f);
@ -429,8 +427,6 @@ static void path_dump(Unit *u, FILE *f, const char *prefix) {
}
static void path_unwatch(Path *p) {
PathSpec *s;
assert(p);
LIST_FOREACH(spec, s, p->specs)
@ -439,7 +435,6 @@ static void path_unwatch(Path *p) {
static int path_watch(Path *p) {
int r;
PathSpec *s;
assert(p);
@ -539,8 +534,6 @@ fail:
}
static bool path_check_good(Path *p, bool initial, bool from_trigger_notify) {
PathSpec *s;
assert(p);
LIST_FOREACH(spec, s, p->specs)
@ -591,8 +584,6 @@ fail:
}
static void path_mkdir(Path *p) {
PathSpec *s;
assert(p);
if (!p->make_directory)
@ -637,7 +628,6 @@ static int path_stop(Unit *u) {
static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
Path *p = PATH(u);
PathSpec *s;
assert(u);
assert(f);
@ -700,7 +690,6 @@ static int path_deserialize_item(Unit *u, const char *key, const char *value, FD
_cleanup_free_ char *unescaped = NULL;
ssize_t l;
PathType type;
PathSpec *s;
type = path_type_from_string(type_str);
if (type < 0) {
@ -742,7 +731,7 @@ _pure_ static const char *path_sub_state_to_string(Unit *u) {
}
static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
PathSpec *s = userdata;
PathSpec *s = userdata, *found = NULL;
Path *p;
int changed;
@ -755,18 +744,18 @@ static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING))
return 0;
/* log_debug("inotify wakeup on %s.", UNIT(p)->id); */
LIST_FOREACH(spec, s, p->specs)
if (path_spec_owns_inotify_fd(s, fd))
LIST_FOREACH(spec, i, p->specs)
if (path_spec_owns_inotify_fd(i, fd)) {
found = i;
break;
}
if (!s) {
if (!found) {
log_error("Got event on unknown fd.");
goto fail;
}
changed = path_spec_fd_event(s, revents);
changed = path_spec_fd_event(found, revents);
if (changed < 0)
goto fail;

View File

@ -434,8 +434,8 @@ static int service_add_fd_store(Service *s, int fd, const char *name, bool do_po
* Use this errno rather than E[NM]FILE to distinguish from
* the case where systemd itself hits the file limit. */
LIST_FOREACH(fd_store, fs, s->fd_store) {
r = same_fd(fs->fd, fd);
LIST_FOREACH(fd_store, i, s->fd_store) {
r = same_fd(i->fd, fd);
if (r < 0)
return r;
if (r > 0) {
@ -504,12 +504,10 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name, bo
}
static void service_remove_fd_store(Service *s, const char *name) {
ServiceFDStore *fs, *n;
assert(s);
assert(name);
LIST_FOREACH_SAFE(fd_store, fs, n, s->fd_store) {
LIST_FOREACH(fd_store, fs, s->fd_store) {
if (!streq(fs->fdname, name))
continue;
@ -567,9 +565,7 @@ static int service_verify(Service *s) {
assert(s);
assert(UNIT(s)->load_state == UNIT_LOADED);
for (ServiceExecCommand c = 0; c < _SERVICE_EXEC_COMMAND_MAX; c++) {
ExecCommand *command;
for (ServiceExecCommand c = 0; c < _SERVICE_EXEC_COMMAND_MAX; c++)
LIST_FOREACH(command, command, s->exec_command[c]) {
if (!path_is_absolute(command->path) && !filename_is_valid(command->path))
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOEXEC),
@ -581,7 +577,6 @@ static int service_verify(Service *s) {
"Service has an empty argv in %s=. Refusing.",
service_exec_command_to_string(c));
}
}
if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP] &&
UNIT(s)->success_action == EMERGENCY_ACTION_NONE)
@ -1334,7 +1329,6 @@ static int service_collect_fds(
}
if (s->n_fd_store > 0) {
ServiceFDStore *fs;
size_t n_fds;
char **nl;
int *t;
@ -2656,7 +2650,6 @@ static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command
ServiceExecCommand id;
size_t length = 0;
unsigned idx;
char **arg;
assert(s);
assert(f);
@ -2712,7 +2705,6 @@ static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command
static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
Service *s = SERVICE(u);
ServiceFDStore *fs;
int r;
assert(u);
@ -4092,7 +4084,6 @@ static void service_notify_message(
Service *s = SERVICE(u);
bool notify_dbus = false;
const char *e;
char * const *i;
int r;
assert(u);

View File

@ -208,8 +208,6 @@ static int socket_arm_timer(Socket *s, usec_t usec) {
}
static bool have_non_accept_socket(Socket *s) {
SocketPort *p;
assert(s);
if (!s->accept)
@ -228,7 +226,6 @@ static bool have_non_accept_socket(Socket *s) {
}
static int socket_add_mount_dependencies(Socket *s) {
SocketPort *p;
int r;
assert(s);
@ -368,7 +365,6 @@ static int socket_add_extras(Socket *s) {
static const char *socket_find_symlink_target(Socket *s) {
const char *found = NULL;
SocketPort *p;
LIST_FOREACH(port, p, s->ports) {
const char *f = NULL;
@ -565,7 +561,6 @@ _const_ static const char* listen_lookup(int family, int type) {
static void socket_dump(Unit *u, FILE *f, const char *prefix) {
Socket *s = SOCKET(u);
SocketPort *p;
const char *prefix2, *str;
assert(s);
@ -781,8 +776,6 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f, "%sSocketProtocol: %s\n", prefix, str);
if (!strv_isempty(s->symlinks)) {
char **q;
fprintf(f, "%sSymlinks:", prefix);
STRV_FOREACH(q, s->symlinks)
fprintf(f, " %s", *q);
@ -923,9 +916,6 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
}
static void socket_close_fds(Socket *s) {
SocketPort *p;
char **i;
assert(s);
LIST_FOREACH(port, p, s->ports) {
@ -1271,7 +1261,6 @@ static int mq_address_create(
static int socket_symlink(Socket *s) {
const char *p;
char **i;
int r;
assert(s);
@ -1624,7 +1613,6 @@ static int socket_open_fds(Socket *orig_s) {
_cleanup_(socket_close_fdsp) Socket *s = orig_s;
_cleanup_(mac_selinux_freep) char *label = NULL;
bool know_label = false;
SocketPort *p;
int r;
assert(s);
@ -1734,7 +1722,6 @@ static int socket_open_fds(Socket *orig_s) {
}
static void socket_unwatch_fds(Socket *s) {
SocketPort *p;
int r;
assert(s);
@ -1753,7 +1740,6 @@ static void socket_unwatch_fds(Socket *s) {
}
static int socket_watch_fds(Socket *s) {
SocketPort *p;
int r;
assert(s);
@ -1791,7 +1777,6 @@ enum {
static int socket_check_open(Socket *s) {
bool have_open = false, have_closed = false;
SocketPort *p;
assert(s);
@ -1995,7 +1980,6 @@ static int socket_chown(Socket *s, pid_t *_pid) {
if (r == 0) {
uid_t uid = UID_INVALID;
gid_t gid = GID_INVALID;
SocketPort *p;
/* Child */
@ -2294,7 +2278,7 @@ fail:
}
static void flush_ports(Socket *s) {
SocketPort *p;
assert(s);
/* Flush all incoming traffic, regardless if actual bytes or new connections, so that this socket isn't busy
* anymore */
@ -2563,7 +2547,6 @@ static int socket_stop(Unit *u) {
static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
Socket *s = SOCKET(u);
SocketPort *p;
int r;
assert(u);
@ -2674,7 +2657,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
}
} else if (streq(key, "fifo")) {
int fd, skip = 0;
SocketPort *p;
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse fifo value: %s", value);
@ -2695,7 +2677,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
} else if (streq(key, "special")) {
int fd, skip = 0;
SocketPort *p;
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse special value: %s", value);
@ -2716,7 +2697,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
} else if (streq(key, "mqueue")) {
int fd, skip = 0;
SocketPort *p;
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse mqueue value: %s", value);
@ -2737,7 +2717,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
} else if (streq(key, "socket")) {
int fd, type, skip = 0;
SocketPort *p;
if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse socket value: %s", value);
@ -2758,7 +2737,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
} else if (streq(key, "netlink")) {
int fd, skip = 0;
SocketPort *p;
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse socket value: %s", value);
@ -2778,7 +2756,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
} else if (streq(key, "ffs")) {
int fd, skip = 0;
SocketPort *p;
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse ffs value: %s", value);
@ -2805,7 +2782,6 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
static void socket_distribute_fds(Unit *u, FDSet *fds) {
Socket *s = SOCKET(u);
SocketPort *p;
assert(u);
@ -3227,7 +3203,6 @@ static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *use
int socket_collect_fds(Socket *s, int **fds) {
size_t k = 0, n = 0;
SocketPort *p;
int *rfds;
assert(s);

View File

@ -537,7 +537,6 @@ static void swap_process_new(Manager *m, const char *device, int prio, bool set_
static void swap_set_state(Swap *s, SwapState state) {
SwapState old_state;
Swap *other;
assert(s);
@ -745,8 +744,6 @@ static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
assert(s);
if (s->from_proc_swaps) {
Swap *other;
swap_enter_active(s, f);
LIST_FOREACH_OTHERS(same_devnode, other, s)
@ -902,7 +899,7 @@ static void swap_cycle_clear(Swap *s) {
}
static int swap_start(Unit *u) {
Swap *s = SWAP(u), *other;
Swap *s = SWAP(u);
int r;
assert(s);
@ -1207,7 +1204,6 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
}
static int swap_process_proc_swaps(Manager *m) {
Unit *u;
int r;
assert(m);
@ -1300,7 +1296,7 @@ static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, v
static Unit *swap_following(Unit *u) {
Swap *s = SWAP(u);
Swap *other, *first = NULL;
Swap *first = NULL;
assert(s);
@ -1336,7 +1332,7 @@ static Unit *swap_following(Unit *u) {
}
static int swap_following_set(Unit *u, Set **_set) {
Swap *s = SWAP(u), *other;
Swap *s = SWAP(u);
_cleanup_set_free_ Set *set = NULL;
int r;

View File

@ -83,7 +83,6 @@ static int timer_verify(Timer *t) {
static int timer_add_default_dependencies(Timer *t) {
int r;
TimerValue *v;
assert(t);
@ -236,7 +235,6 @@ static int timer_load(Unit *u) {
static void timer_dump(Unit *u, FILE *f, const char *prefix) {
Timer *t = TIMER(u);
Unit *trigger;
TimerValue *v;
trigger = UNIT_TRIGGER(u);
@ -375,7 +373,6 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
bool found_monotonic = false, found_realtime = false;
bool leave_around = false;
triple_timestamp ts;
TimerValue *v;
Unit *trigger;
int r;
@ -617,7 +614,6 @@ fail:
static int timer_start(Unit *u) {
Timer *t = TIMER(u);
TimerValue *v;
int r;
assert(t);
@ -756,7 +752,6 @@ static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
static void timer_trigger_notify(Unit *u, Unit *other) {
Timer *t = TIMER(u);
TimerValue *v;
assert(u);
assert(other);

View File

@ -46,7 +46,7 @@ void transaction_abort(Transaction *tr) {
}
static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generation) {
JobDependency *l;
assert(j);
/* A recursive sweep through the graph that marks all units
* that matter to the anchor job, i.e. are directly or
@ -71,7 +71,7 @@ static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generat
}
static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other, JobType t) {
JobDependency *l, *last;
JobDependency *last;
assert(j);
assert(other);
@ -124,8 +124,6 @@ static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other
}
_pure_ static bool job_is_conflicted_by(Job *j) {
JobDependency *l;
assert(j);
/* Returns true if this job is pulled in by a least one
@ -138,10 +136,8 @@ _pure_ static bool job_is_conflicted_by(Job *j) {
return false;
}
static int delete_one_unmergeable_job(Transaction *tr, Job *j) {
Job *k;
assert(j);
static int delete_one_unmergeable_job(Transaction *tr, Job *job) {
assert(job);
/* Tries to delete one item in the linked list
* j->transaction_next->transaction_next->... that conflicts
@ -150,7 +146,7 @@ static int delete_one_unmergeable_job(Transaction *tr, Job *j) {
/* We rely here on the fact that if a merged with b does not
* merge with c, either a or b merge with c neither */
LIST_FOREACH(transaction, j, j)
LIST_FOREACH(transaction, j, job)
LIST_FOREACH(transaction, k, j->transaction_next) {
Job *d;
@ -226,7 +222,6 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
* task conflict. If so, try to drop one of them. */
HASHMAP_FOREACH(j, tr->jobs) {
JobType t;
Job *k;
t = j->type;
LIST_FOREACH(transaction, k, j->transaction_next) {
@ -257,12 +252,12 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
/* Second step, merge the jobs. */
HASHMAP_FOREACH(j, tr->jobs) {
JobType t = j->type;
Job *k;
/* Merge all transaction jobs for j->unit */
LIST_FOREACH(transaction, k, j->transaction_next)
assert_se(job_type_merge_and_collapse(&t, k->type, j->unit) == 0);
Job *k;
while ((k = j->transaction_next)) {
if (tr->anchor_job == k) {
transaction_merge_and_delete_job(tr, k, j, t);
@ -293,7 +288,6 @@ static void transaction_drop_redundant(Transaction *tr) {
HASHMAP_FOREACH(j, tr->jobs) {
bool keep = false;
Job *k;
LIST_FOREACH(transaction, k, j)
if (tr->anchor_job == k ||
@ -314,14 +308,15 @@ static void transaction_drop_redundant(Transaction *tr) {
} while (again);
}
_pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) {
_pure_ static bool unit_matters_to_anchor(Unit *u, Job *job) {
assert(u);
assert(!j->transaction_prev);
assert(job);
assert(!job->transaction_prev);
/* Checks whether at least one of the jobs for this unit
* matters to the anchor. */
LIST_FOREACH(transaction, j, j)
LIST_FOREACH(transaction, j, job)
if (j->matters_to_anchor)
return true;
@ -329,7 +324,7 @@ _pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) {
}
static char* merge_unit_ids(const char* unit_log_field, char **pairs) {
char **unit_id, **job_type, *ans = NULL;
char *ans = NULL;
size_t size = 0, next;
STRV_FOREACH_PAIR(unit_id, job_type, pairs) {
@ -366,7 +361,6 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
if (j->generation == generation) {
Job *k, *delete = NULL;
_cleanup_free_ char **array = NULL, *unit_ids = NULL;
char **unit_id, **job_type;
/* If the marker is NULL we have been here already and decided the job was loop-free from
* here. Hence shortcut things and return right-away. */
@ -558,7 +552,7 @@ static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_erro
}
static void transaction_minimize_impact(Transaction *tr) {
Job *j;
Job *head;
assert(tr);
@ -566,8 +560,8 @@ static void transaction_minimize_impact(Transaction *tr) {
* or that stop a running service. */
rescan:
HASHMAP_FOREACH(j, tr->jobs) {
LIST_FOREACH(transaction, j, j) {
HASHMAP_FOREACH(head, tr->jobs) {
LIST_FOREACH(transaction, j, head) {
bool stops_running_service, changes_existing_job;
/* If it matters, we shouldn't drop it */
@ -804,13 +798,13 @@ static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, b
f = hashmap_get(tr->jobs, unit);
LIST_FOREACH(transaction, j, f) {
assert(j->unit == unit);
LIST_FOREACH(transaction, i, f) {
assert(i->unit == unit);
if (j->type == type) {
if (i->type == type) {
if (is_new)
*is_new = false;
return j;
return i;
}
}

View File

@ -623,7 +623,7 @@ static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependency
}
void unit_dump(Unit *u, FILE *f, const char *prefix) {
char *t, **j;
char *t;
const char *prefix2;
Unit *following;
_cleanup_set_free_ Set *following_set = NULL;

View File

@ -583,8 +583,6 @@ static void unit_clear_dependencies(Unit *u) {
}
static void unit_remove_transient(Unit *u) {
char **i;
assert(u);
if (!u->transient)
@ -3620,7 +3618,6 @@ int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask m
int unit_coldplug(Unit *u) {
int r = 0, q;
char **i;
assert(u);
@ -3693,7 +3690,6 @@ static bool fragment_mtime_newer(const char *path, usec_t mtime, bool path_maske
bool unit_need_daemon_reload(Unit *u) {
_cleanup_strv_free_ char **t = NULL;
char **path;
assert(u);
@ -4278,7 +4274,6 @@ char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf) {
char* unit_concat_strv(char **l, UnitWriteFlags flags) {
_cleanup_free_ char *result = NULL;
size_t n = 0;
char **i;
/* Takes a list of strings, escapes them, and concatenates them. This may be used to format command lines in a
* way suitable for ExecStart= stanzas */
@ -5079,7 +5074,6 @@ int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid) {
return r;
if (r == 0) {
int ret = EXIT_SUCCESS;
char **i;
STRV_FOREACH(i, paths) {
r = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_MISSING_OK);
@ -5869,7 +5863,7 @@ int unit_thaw_vtable_common(Unit *u) {
}
Condition *unit_find_failed_condition(Unit *u) {
Condition *c, *failed_trigger = NULL;
Condition *failed_trigger = NULL;
bool has_succeeded_trigger = false;
if (u->condition_result)

View File

@ -91,7 +91,6 @@ static int add_match(sd_journal *j, const char *match) {
}
static int add_matches(sd_journal *j, char **matches) {
char **match;
int r;
r = sd_journal_add_match(j, "MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR, 0);

View File

@ -311,7 +311,6 @@ static int write_blob(FILE *f, const void *data, size_t size) {
static int verb_cat(int argc, char **argv, void *userdata) {
_cleanup_(closedirp) DIR *d = NULL;
int r, ret = 0;
char **cn;
r = open_credential_directory(&d);
if (r == -ENXIO)

View File

@ -489,7 +489,6 @@ static int prepare_luks(
for (;;) {
_cleanup_strv_free_erase_ char **passwords = NULL;
char **p;
if (--i == 0)
return log_error_errno(SYNTHETIC_ERRNO(ENOKEY),

View File

@ -12,7 +12,6 @@ int find_key_file(
void **ret_key,
size_t *ret_key_size) {
char **i;
int r;
assert(key_file);

View File

@ -573,7 +573,7 @@ static int get_password(
_cleanup_free_ char *friendly = NULL, *text = NULL, *disk_path = NULL;
_cleanup_strv_free_erase_ char **passwords = NULL;
char **p, *id;
char *id;
int r = 0;
AskPasswordFlags flags = arg_ask_password_flags | ASK_PASSWORD_PUSH_CACHE;
@ -861,7 +861,6 @@ static int attach_luks2_by_fido2(
#if HAVE_LIBCRYPTSETUP_PLUGINS
AskPasswordFlags flags = ASK_PASSWORD_PUSH_CACHE | ASK_PASSWORD_ACCEPT_CACHED;
_cleanup_strv_free_erase_ char **pins = NULL;
char **p;
int r;
r = crypt_activate_by_token_pin(cd, name, "systemd-fido2", CRYPT_ANY_TOKEN, NULL, 0, usrptr, activation_flags);
@ -1547,7 +1546,6 @@ static int attach_luks_or_plain_or_bitlk_by_passphrase(
uint32_t flags,
bool pass_volume_key) {
char **p;
int r;
assert(cd);

View File

@ -89,7 +89,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
}
static int generate_mask_symlinks(void) {
char **u;
int r = 0;
if (strv_isempty(arg_mask))
@ -112,7 +111,6 @@ static int generate_mask_symlinks(void) {
}
static int generate_wants_symlinks(void) {
char **u;
int r = 0;
if (strv_isempty(arg_wants))

View File

@ -195,7 +195,6 @@ static int enumerate_dir_d(
_cleanup_free_ char *unit = NULL;
_cleanup_free_ char *path = NULL;
_cleanup_strv_free_ char **list = NULL;
char **file;
char *c;
int r;
@ -292,7 +291,6 @@ static int enumerate_dir(
_cleanup_closedir_ DIR *d = NULL;
_cleanup_strv_free_ char **files = NULL, **dirs = NULL;
size_t n_files = 0, n_dirs = 0;
char **t;
int r;
assert(top);

View File

@ -354,7 +354,6 @@ static int parse_argv(int argc, char *argv[]) {
static int strv_pair_to_json(char **l, JsonVariant **ret) {
_cleanup_strv_free_ char **jl = NULL;
char **a, **b;
STRV_FOREACH_PAIR(a, b, l) {
char *j;
@ -371,8 +370,6 @@ static int strv_pair_to_json(char **l, JsonVariant **ret) {
}
static void strv_pair_print(char **l, const char *prefix) {
char **p, **q;
assert(prefix);
STRV_FOREACH_PAIR(p, q, l) {

View File

@ -41,7 +41,6 @@ static int environment_dirs(char ***ret) {
static int load_and_print(void) {
_cleanup_strv_free_ char **dirs = NULL, **files = NULL, **env = NULL;
char **i;
int r;
r = environment_dirs(&dirs);

View File

@ -155,7 +155,6 @@ static int parse_argv(int argc, char *argv[]) {
}
static int run(int argc, char *argv[]) {
char **i;
int r;
log_setup();

View File

@ -237,7 +237,6 @@ static int write_dependency(
_cleanup_strv_free_ char **names = NULL, **units = NULL;
_cleanup_free_ char *res = NULL;
char **s;
int r;
assert(f);
@ -518,8 +517,6 @@ static int add_mount(
if (r < 0)
return r;
} else {
char **s;
STRV_FOREACH(s, wanted_by) {
r = generator_add_symlink(dest, *s, "wants", name);
if (r < 0)

View File

@ -557,7 +557,6 @@ static int acquire_passed_secrets(const char *user_name, UserRecord **ret) {
static int activate_home(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r, ret = 0;
char **i;
r = acquire_bus(&bus);
if (r < 0)
@ -606,7 +605,6 @@ static int activate_home(int argc, char *argv[], void *userdata) {
static int deactivate_home(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r, ret = 0;
char **i;
r = acquire_bus(&bus);
if (r < 0)
@ -693,7 +691,7 @@ static int inspect_home(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(strv_freep) char **mangled_list = NULL;
int r, ret = 0;
char **items, **i;
char **items;
pager_open(arg_pager_flags);
@ -777,7 +775,7 @@ static int authenticate_home(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(strv_freep) char **mangled_list = NULL;
int r, ret = 0;
char **i, **items;
char **items;
items = mangle_user_list(strv_skip(argv, 1), &mangled_list);
if (!items)
@ -1087,7 +1085,6 @@ static int add_disposition(JsonVariant **v) {
static int acquire_new_home_record(UserRecord **ret) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
_cleanup_(user_record_unrefp) UserRecord *hr = NULL;
char **i;
int r;
assert(ret);
@ -1370,7 +1367,6 @@ static int create_home(int argc, char *argv[], void *userdata) {
static int remove_home(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r, ret = 0;
char **i;
r = acquire_bus(&bus);
if (r < 0)
@ -1408,7 +1404,6 @@ static int acquire_updated_home_record(
_cleanup_(json_variant_unrefp) JsonVariant *json = NULL;
_cleanup_(user_record_unrefp) UserRecord *hr = NULL;
char **i;
int r;
assert(ret);
@ -1858,7 +1853,6 @@ static int resize_home(int argc, char *argv[], void *userdata) {
static int lock_home(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r, ret = 0;
char **i;
r = acquire_bus(&bus);
if (r < 0)
@ -1890,7 +1884,6 @@ static int lock_home(int argc, char *argv[], void *userdata) {
static int unlock_home(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r, ret = 0;
char **i;
r = acquire_bus(&bus);
if (r < 0)

View File

@ -39,7 +39,6 @@ static int property_get_auto_login(
HASHMAP_FOREACH(h, m->homes_by_name) {
_cleanup_(strv_freep) char **seats = NULL;
_cleanup_free_ char *home_path = NULL;
char **s;
r = home_auto_login(h, &seats);
if (r < 0) {

View File

@ -1551,7 +1551,6 @@ static int manager_load_public_key_one(Manager *m, const char *path) {
static int manager_load_public_keys(Manager *m) {
_cleanup_strv_free_ char **files = NULL;
char **i;
int r;
assert(m);

View File

@ -282,7 +282,6 @@ int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, VarlinkMet
if (p.user_name) {
const char *last = NULL;
char **i;
h = hashmap_get(m->homes_by_name, p.user_name);
if (!h)
@ -335,9 +334,7 @@ int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, VarlinkMet
} else {
const char *last_user_name = NULL, *last_group_name = NULL;
HASHMAP_FOREACH(h, m->homes_by_name) {
char **j;
HASHMAP_FOREACH(h, m->homes_by_name)
STRV_FOREACH(j, h->record->member_of) {
if (last_user_name) {
@ -353,7 +350,6 @@ int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, VarlinkMet
last_user_name = h->user_name;
last_group_name = *j;
}
}
if (last_user_name) {
assert(last_group_name);

View File

@ -20,7 +20,6 @@ int home_setup_cifs(
HomeSetup *setup) {
_cleanup_free_ char *chost = NULL, *cservice = NULL, *cdir = NULL, *chost_and_service = NULL, *j = NULL;
char **pw;
int r;
assert(h);

View File

@ -197,7 +197,6 @@ static int fscrypt_slot_try_many(
const uint8_t match_key_descriptor[static FS_KEY_DESCRIPTOR_SIZE],
void **ret_decrypted, size_t *ret_decrypted_size) {
char **i;
int r;
STRV_FOREACH(i, passwords) {
@ -499,7 +498,6 @@ int home_create_fscrypt(
_cleanup_free_ char *d = NULL;
uint32_t nr = 0;
const char *ip;
char **i;
int r;
assert(h);
@ -649,7 +647,6 @@ int home_passwd_fscrypt(
size_t volume_key_size = 0;
uint32_t slot = 0;
const char *xa;
char **p;
int r;
assert(h);

View File

@ -304,7 +304,6 @@ static int luks_try_passwords(
size_t *volume_key_size,
key_serial_t *ret_key_serial) {
char **pp;
int r;
assert(h);
@ -1718,7 +1717,6 @@ static int luks_format(
_cleanup_free_ char *text = NULL;
size_t volume_key_size;
int slot = 0, r;
char **pp;
assert(node);
assert(dm_name);
@ -3659,7 +3657,6 @@ static int luks_try_resume(
const char *dm_name,
char **password) {
char **pp;
int r;
assert(cd);

View File

@ -20,7 +20,6 @@ int pkcs11_callback(
CK_TOKEN_INFO updated_token_info;
size_t decrypted_key_size;
CK_OBJECT_HANDLE object;
char **i;
CK_RV rv;
int r;

View File

@ -97,9 +97,7 @@ int user_record_authenticate(
log_info("None of the supplied plaintext passwords unlock the user record's hashed recovery keys.");
/* Second, test cached PKCS#11 passwords */
for (size_t n = 0; n < h->n_pkcs11_encrypted_key; n++) {
char **pp;
for (size_t n = 0; n < h->n_pkcs11_encrypted_key; n++)
STRV_FOREACH(pp, cache->pkcs11_passwords) {
r = test_password_one(h->pkcs11_encrypted_key[n].hashed_password, *pp);
if (r < 0)
@ -109,12 +107,9 @@ int user_record_authenticate(
return 1;
}
}
}
/* Third, test cached FIDO2 passwords */
for (size_t n = 0; n < h->n_fido2_hmac_salt; n++) {
char **pp;
for (size_t n = 0; n < h->n_fido2_hmac_salt; n++)
/* See if any of the previously calculated passwords work */
STRV_FOREACH(pp, cache->fido2_passwords) {
r = test_password_one(h->fido2_hmac_salt[n].hashed_password, *pp);
@ -125,7 +120,6 @@ int user_record_authenticate(
return 1;
}
}
}
/* Fourth, let's see if any of the PKCS#11 security tokens are plugged in and help us */
for (size_t n = 0; n < h->n_pkcs11_encrypted_key; n++) {
@ -1096,7 +1090,6 @@ static int user_record_compile_effective_passwords(
_cleanup_(strv_free_erasep) char **effective = NULL;
size_t n;
char **i;
int r;
assert(h);
@ -1116,7 +1109,6 @@ static int user_record_compile_effective_passwords(
STRV_FOREACH(i, h->hashed_password) {
bool found = false;
char **j;
log_debug("Looking for plaintext password for: %s", *i);
@ -1144,7 +1136,6 @@ static int user_record_compile_effective_passwords(
for (n = 0; n < h->n_recovery_key; n++) {
bool found = false;
char **j;
log_debug("Looking for plaintext recovery key for: %s", h->recovery_key[n].hashed_password);

View File

@ -17,7 +17,7 @@ int user_record_quality_check_password(
sd_bus_error *error) {
_cleanup_(sym_pwquality_free_settingsp) pwquality_settings_t *pwq = NULL;
char buf[PWQ_MAX_ERROR_MESSAGE_LEN], **pp;
char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
void *auxerror;
int r;
@ -37,7 +37,6 @@ int user_record_quality_check_password(
/* Iterate through all new passwords */
STRV_FOREACH(pp, secret->password) {
bool called = false;
char **old;
r = test_password_many(hr->hashed_password, *pp);
if (r < 0)

View File

@ -563,7 +563,6 @@ int user_record_test_image_path_and_warn(UserRecord *h) {
}
int user_record_test_password(UserRecord *h, UserRecord *secret) {
char **i;
int r;
assert(h);
@ -585,7 +584,6 @@ int user_record_test_password(UserRecord *h, UserRecord *secret) {
}
int user_record_test_recovery_key(UserRecord *h, UserRecord *secret) {
char **i;
int r;
assert(h);
@ -779,7 +777,6 @@ int user_record_update_last_changed(UserRecord *h, bool with_password) {
int user_record_make_hashed_password(UserRecord *h, char **secret, bool extend) {
_cleanup_(json_variant_unrefp) JsonVariant *priv = NULL;
_cleanup_strv_free_ char **np = NULL;
char **i;
int r;
assert(h);

View File

@ -102,7 +102,6 @@ static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first
static int verb_show(int argc, char **argv, void *userdata) {
_cleanup_(table_unrefp) Table *table = NULL;
char **p;
int r;
argv = strv_skip(argv, 1);

View File

@ -594,7 +594,6 @@ static int create_remoteserver(
const char* trust) {
int r, n, fd;
char **file;
r = journal_remote_server_init(s, arg_output, arg_split_mode, arg_compress, arg_seal);
if (r < 0)

View File

@ -151,18 +151,17 @@ static int log_enable_gnutls_category(const char *cat) {
}
int setup_gnutls_logger(char **categories) {
char **cat;
int r;
gnutls_global_set_log_function(log_func_gnutls);
if (categories) {
if (categories)
STRV_FOREACH(cat, categories) {
r = log_enable_gnutls_category(*cat);
if (r < 0)
return r;
}
} else
else
log_reset_gnutls_level();
return 0;

View File

@ -1146,7 +1146,6 @@ static int parse_argv(int argc, char *argv[]) {
}
static int add_matches(sd_journal *j, char **args) {
char **i;
bool have_term = false;
assert(j);
@ -1334,7 +1333,7 @@ static int get_boots(
bool skip_once;
int r, count = 0;
BootId *head = NULL, *tail = NULL, *id;
BootId *head = NULL, *tail = NULL;
const bool advance_older = boot_id && offset <= 0;
sd_id128_t previous_boot_id;
@ -1449,7 +1448,7 @@ finish:
static int list_boots(sd_journal *j) {
_cleanup_(table_unrefp) Table *table = NULL;
BootId *id, *all_ids;
BootId *all_ids;
int count, i, r;
assert(j);
@ -1584,7 +1583,7 @@ static int get_possible_units(
return r;
SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
char **pattern, *eq;
char *eq;
size_t prefix;
_cleanup_free_ char *u = NULL;
@ -1637,7 +1636,6 @@ static int get_possible_units(
static int add_units(sd_journal *j) {
_cleanup_strv_free_ char **patterns = NULL;
int r, count = 0;
char **i;
assert(j);
@ -1782,7 +1780,6 @@ static int add_facilities(sd_journal *j) {
static int add_syslog_identifier(sd_journal *j) {
int r;
char **i;
assert(j);

View File

@ -185,10 +185,10 @@ static unsigned burst_modulate(unsigned burst, uint64_t available) {
}
int journal_ratelimit_test(JournalRateLimit *r, const char *id, usec_t rl_interval, unsigned rl_burst, int priority, uint64_t available) {
uint64_t h;
JournalRateLimitGroup *g;
JournalRateLimitGroup *g, *found = NULL;
JournalRateLimitPool *p;
unsigned burst;
uint64_t h;
usec_t ts;
assert(id);
@ -208,23 +208,25 @@ int journal_ratelimit_test(JournalRateLimit *r, const char *id, usec_t rl_interv
h = siphash24_string(id, r->hash_key);
g = r->buckets[h % BUCKETS_MAX];
LIST_FOREACH(bucket, g, g)
if (streq(g->id, id))
LIST_FOREACH(bucket, i, g)
if (streq(i->id, id)) {
found = i;
break;
}
if (!g) {
g = journal_ratelimit_group_new(r, id, rl_interval, ts);
if (!g)
if (!found) {
found = journal_ratelimit_group_new(r, id, rl_interval, ts);
if (!found)
return -ENOMEM;
} else
g->interval = rl_interval;
found->interval = rl_interval;
if (rl_interval == 0 || rl_burst == 0)
return 1;
burst = burst_modulate(rl_burst, available);
p = &g->pools[priority_map[priority]];
p = &found->pools[priority_map[priority]];
if (p->begin <= 0) {
p->suppressed = 0;

View File

@ -58,7 +58,6 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
case SD_DHCP_OPTION_USER_CLASS: {
size_t total = 0;
char **s;
if (strv_isempty((char **) optval))
return -EINVAL;

View File

@ -328,7 +328,6 @@ static int option_append_pd_prefix(uint8_t **buf, size_t *buflen, const struct i
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
struct ia_header header;
const DHCP6Address *addr;
size_t ia_buflen;
uint8_t *ia_hdr;
uint16_t len;
@ -418,7 +417,6 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char * const *user_class) {
_cleanup_free_ uint8_t *p = NULL;
size_t total = 0, offset = 0;
char * const *s;
assert(buf);
assert(*buf);
@ -451,7 +449,6 @@ int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const
_cleanup_free_ uint8_t *p = NULL;
uint32_t enterprise_identifier;
size_t total, offset;
char * const *s;
assert(buf);
assert(*buf);

Some files were not shown because too many files have changed in this diff Show More