+++ /dev/null
-### Submission type
-
-<!-- Delete the inappropriate option below: -->
-
- - Bug report
- - Request for enhancement (RFE)
-
-<!-- **NOTE:** Do not submit anything other than bug reports or RFEs via the issue tracker! -->
-
-### systemd version the issue has been seen with
-
-> …
-
-<!-- **NOTE:** Do not submit bug reports about anything but the two most recently released systemd versions upstream! -->
-<!-- For older version please use distribution trackers (see https://github.com/systemd/systemd/blob/master/.github/CONTRIBUTING.md#filing-issues). -->
-
-### Used distribution
-
-> …
-
-### In case of bug report: Expected behaviour you didn't see
-
-> …
-
-### In case of bug report: Unexpected behaviour you saw
-
-> …
-
-### In case of bug report: Steps to reproduce the problem
-
-> …
--- /dev/null
+---
+name: Bug report
+about: A report of an error in a recent systemd version
+
+---
+
+**systemd version the issue has been seen with**
+> ...
+
+<!-- **NOTE:** Do not submit bug reports about anything but the two most recently released systemd versions upstream! -->
+<!-- For older version please use distribution trackers (see https://github.com/systemd/systemd/blob/master/.github/CONTRIBUTING.md#filing-issues). -->
+
+**Used distribution**
+ > …
+
+**Expected behaviour you didn't see**
+ > …
+
+**Unexpected behaviour you saw**
+ > …
+
+**Steps to reproduce the problem**
--- /dev/null
+---
+name: Feature request
+about: Suggest an improvement
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
services:
- docker
+
+cache: ccache
jobs:
include:
- MACHINE_ID=$(cat /var/lib/dbus/machine-id)
before_script: *update
script:
- - docker run -dit --name travis_build ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT} bash
+ - docker run -v $HOME/.ccache:$HOME/.ccache -dit --name travis_build ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT} bash
- docker exec -u 0 -ti travis_build bash -c "echo ${MACHINE_ID} > /etc/machine-id"
- docker exec -ti travis_build meson build
- docker exec -ti travis_build ninja -C build
compiler: gcc
before_script: *update
script:
- - docker run --privileged --net=host -dit --name travis_test ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT} bash
+ - docker run -v $HOME/.ccache:$HOME/.ccache --privileged --net=host -dit --name travis_test ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT} bash
- docker exec -ti travis_test ninja -C build test
- docker commit -m "systemd test state" -a "${AUTHOR_NAME}" travis_test ${DOCKER_REPOSITORY}:${TRAVIS_COMMIT}
- docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}"
and udev may generate names based on PCI slot number in some cases
where it previously did not.
+ * AF_INET and AF_INET6 are dropped from RestrictAddressFamilies= in
+ systemd-logind.service. Since v235, IPAddressDeny=any has been set to
+ the unit. So, it is expected that the default behavior of systemd-logind
+ is not changed. However, if distribution packagers or administrators
+ disabled or modified IPAddressDeny= setting by a drop-in config file,
+ then it may be necessary to update the file to re-enable AF_INET and
+ AF_INET6 to support network user name services, e.g. NIS.
+
CHANGES WITH 238:
* The MemoryAccounting= unit property now defaults to on. After
docbook-xsl (optional, required for documentation)
xsltproc (optional, required for documentation)
python-lxml (optional, required to build the indices)
- python, meson, ninja
+ python >= 3.4, meson >= 0.44, ninja
gcc, awk, sed, grep, m4, and similar tools
During runtime, you need the following additional
For more information on this issue consult
https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
- To run systemd under valgrind, compile with VALGRIND defined
- (e.g. CPPFLAGS='... -DVALGRIND=1' meson <options>) and have valgrind
- development headers installed (i.e. valgrind-devel or
- equivalent). Otherwise, false positives will be triggered by code which
- violates some rules but is actually safe. Note that valgrind generates
- nice output only on exit(), hence on shutdown we don't execve()
- systemd-shutdown.
+ To run systemd under valgrind, compile with meson option
+ -Dvalgrind=true and have valgrind development headers installed
+ (i.e. valgrind-devel or equivalent). Otherwise, false positives will be
+ triggered by code which violates some rules but is actually safe. Note
+ that valgrind generates nice output only on exit(), hence on shutdown
+ we don't execve() systemd-shutdown.
STABLE BRANCHES AND BACKPORTS
Features:
+* add O_TMPFILE support to copy_file_atomic()
+
+* nspawn: greater control over selinux label?
+
* the error paths in usbffs_dispatch_ep() leak memory
* cgroups: figure out if we can somehow communicate in a cleaner way whether a
* add --vacuum-xyz options to coredumpctl, matching those journalctl already has.
-* list the exit codes from the BSD/glibc <sysexits.h> in our own
- exit-codes.[ch] tables.
-
* SuccessExitStatus= and friends should probably also accept symbolic exit
codes names, i.e. error codes from the list maintained in exit-codes.[ch]
* rework fopen_temporary() to make use of open_tmpfile_linkable() (problem: the
kernel doesn't support linkat() that replaces existing files, currently)
-* check if DeviceAllow= should split first, resolve specifiers later
-
* transient units: don't bother with actually setting unit properties, we
reload the unit file anyway
- document chaining of signal handler for SIGCHLD and child handlers
- define more intervals where we will shift wakeup intervals around in, 1h, 6h, 24h, ...
- generate a failure of a default event loop is executed out-of-thread
- - maybe add support for inotify events
+ - maybe add support for inotify events (which we can do safely now, with O_PATH)
* investigate endianness issues of UUID vs. GUID
cgroup tree of systemd itself is out of limits for you. It's fine to *read*
from any attribute you like however. That's totally OK and welcome.
-4. 🚫 When not using `CLONE_NEWCGROUP` when delegating a sub-tree to a container
- payload running systemd, then don't get the idea that you can bind mount
- only a sub-tree of the host's cgroup tree into the container. Part of the
- cgroup API is that `/proc/$PID/cgroup` reports the cgroup path of every
+4. 🚫 When not using `CLONE_NEWCGROUP` when delegating a sub-tree to a
+ container payload running systemd, then don't get the idea that you can bind
+ mount only a sub-tree of the host's cgroup tree into the container. Part of
+ the cgroup API is that `/proc/$PID/cgroup` reports the cgroup path of every
process, and hence any path below `/sys/fs/cgroup/` needs to match what
`/proc/$PID/cgroup` of the payload processes reports. What you can do safely
- however, is mount the upper parts of the cgroup tree read-only or even
- replace it with an intermediary `tmpfs`, as long as the path to the
- delegated sub-tree remains accessible as-is.
+ however, is mount the upper parts of the cgroup tree read-only (or even
+ replace the middle bits with an intermediary `tmpfs` — but be careful not to
+ break the `statfs()` detection logic discussed above), as long as the path
+ to the delegated sub-tree remains accessible as-is.
5. ⚡ Currently, the algorithm for mapping between slice/scope/service unit
naming and their cgroup paths is not considered public API of systemd, and
pre-defined purposes between Linux, generic low-level distributions and
`systemd`. There might very well be other packages that allocate from these
ranges.
+
+## Notes on resolvability of user and group names
+
+User names, UIDs, group names and GIDs don't have to be resolvable using NSS
+(i.e. getpwuid() and getpwnam() and friends) all the time. However, systemd
+makes the following requirements:
+
+System users generally have to be resolvable during early boot already. This
+means they should not be provided by any networked service (as those usually
+become available during late boot only), except if a local cache is kept that
+makes them available during early boot too (i.e. before networking is
+up). Specifically, system users need to be resolvable at least before
+`systemd-udevd.service` and `systemd-tmpfiles.service` are started, as both
+need to resolve system users — but note that there might be more services
+requiring full resolvability of system users than just these two.
+
+Regular users do not need to be resolvable during early boot, it is sufficient
+if they become resolvable during late boot. Specifically, regular users need to
+be resolvable at the point in time the `nss-user-lookup.target` unit is
+reached. This target unit is generally used as synchronization point between
+providers of the user database and consumers of it. Services that require that
+the user database is fully available (for example, the login service
+`systemd-logind.service`) are ordered *after* it, while services that provide
+parts of the user database (for example an LDAP user database client) are
+ordered *before* it. Note that `nss-user-lookup.target` is a *passive* unit: in
+order to minimize synchronization points on systems that don't need it the unit
+is pulled into the initial transaction only if there's at least one service
+that really needs it, and that means only if there's a service providing the
+local user database somehow through IPC or suchlike. Or in other words: if you
+hack on some networked user database project, then make sure you order your
+service `Before=nss-user-lookup.target` and that you pull it in with
+`Wants=nss-user-lookup.target`. However, if you hack on some project that needs
+the user database to be up in full, then order your service
+`After=nss-user-lookup.target`, but do *not* pull it in via a `Wants=`
+dependency.
<listitem><para>Controls where to store cores. One of <literal>none</literal>,
<literal>external</literal>, and <literal>journal</literal>. When
- <literal>none</literal>, the core dumps will be logged (including the backtrace if
+ <literal>none</literal>, the core dumps may be logged (including the backtrace if
possible), but not stored permanently. When <literal>external</literal> (the
default), cores will be stored in <filename>/var/lib/systemd/coredump/</filename>.
When <literal>journal</literal>, cores will be stored in the journal and rotated
<listitem><para>The maximum size in bytes of a core
which will be processed. Core dumps exceeding this size
- will be logged, but the backtrace will not be generated
- and the core will not be stored.</para></listitem>
+ may be stored, but the backtrace will not be generated.
+ </para>
+
+ <para>Setting <varname>Storage=none</varname> and <varname>ProcessSizeMax=0</varname>
+ disables all coredump handling except for a log entry.</para>
+ </listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>ServerCertificateFile=</varname></term>
- <listitem><para>SSL CA certificate in PEM format.</para></listitem>
+ <listitem><para>SSL certificate in PEM format.</para></listitem>
</varlistentry>
<varlistentry>
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
<listitem><para>The URL to upload the journal entries to. See the description
of <varname>--url=</varname> option in
<citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- for the description of possible values.</para></listitem>
+ for the description of possible values. There is no default value, so either this
+ option or the command-line option must be always present to make an upload.</para></listitem>
</varlistentry>
<varlistentry>
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>
<example>
<title>Retrieve the addresses of the <literal>www.0pointer.net</literal> domain</title>
- <programlisting>$ resolvectl www.0pointer.net
+ <programlisting>$ resolvectl query www.0pointer.net
www.0pointer.net: 2a01:238:43ed:c300:10c3:bcf3:3266:da74
85.214.157.71
<example>
<title>Retrieve the domain of the <literal>85.214.157.71</literal> IP address</title>
- <programlisting>$ resolvectl 85.214.157.71
+ <programlisting>$ resolvectl query 85.214.157.71
85.214.157.71: gardel.0pointer.net
-- Information acquired via protocol DNS in 1.2997s.
<example>
<title>Retrieve the MX record of the <literal>yahoo.com</literal> domain</title>
- <programlisting>$ resolvectl -t MX yahoo.com --legend=no
+ <programlisting>$ resolvectl --legend=no -t MX query yahoo.com
yahoo.com. IN MX 1 mta7.am0.yahoodns.net
yahoo.com. IN MX 1 mta6.am0.yahoodns.net
yahoo.com. IN MX 1 mta5.am0.yahoodns.net
'8',
['systemd-journal-gatewayd', 'systemd-journal-gatewayd.socket'],
'HAVE_MICROHTTPD'],
- ['systemd-journal-remote', '8', [], 'HAVE_MICROHTTPD'],
- ['systemd-journal-upload', '8', [], 'HAVE_MICROHTTPD'],
+ ['systemd-journal-remote.service',
+ '8',
+ ['systemd-journal-remote', 'systemd-journal-remote.socket'],
+ 'HAVE_MICROHTTPD'],
+ ['systemd-journal-upload.service',
+ '8',
+ ['systemd-journal-upload'],
+ 'HAVE_MICROHTTPD'],
['systemd-journald.service',
'8',
['systemd-journald',
footer with hints.</para>
</listitem>
</varlistentry>
+
+ <varlistentry id='cat-config'>
+ <term><option>--cat-config</option></term>
+
+ <listitem>
+ <para>Copy the contents of config files to standard output.
+ Before each file, the filename is printed as a comment.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
<para><emphasis>NEXT</emphasis> shows the next time the timer will run.</para>
<para><emphasis>LEFT</emphasis> shows how long till the next time the timer runs.</para>
<para><emphasis>LAST</emphasis> shows the last time the timer ran.</para>
- <para><emphasis>PASSED</emphasis> shows has long as passed since the timer laset ran.</para>
+ <para><emphasis>PASSED</emphasis> shows how long has passed since the timer last ran.</para>
<para><emphasis>UNIT</emphasis> shows the name of the timer</para>
<para><emphasis>ACTIVATES</emphasis> shows the name the service the timer activates when it runs.</para>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="plain">dump</arg>
</cmdsynopsis>
+ <cmdsynopsis>
+ <command>systemd-analyze</command>
+ <arg choice="opt" rep="repeat">OPTIONS</arg>
+ <arg choice="plain">cat-config</arg>
+ <arg choice="plain" rep="repeat"><replaceable>NAME</replaceable>|<replaceable>PATH</replaceable></arg>
+ </cmdsynopsis>
<cmdsynopsis>
<command>systemd-analyze</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
state. Its format is subject to change without notice and should
not be parsed by applications.</para>
+ <para><command>systemd-analyze cat-config</command> is similar
+ to <command>systemctl cat</command>, but operates on config files.
+ It will copy the contents of a config file and any drop-ins to standard
+ output, using the usual systemd set of directories and rules for
+ precedence. Each argument must be either an absolute path including
+ the prefix (such as <filename>/etc/systemd/logind.conf</filename> or
+ <filename>/usr/lib/systemd/logind.conf</filename>), or a name
+ relative to the prefix (such as <filename>systemd/logind.conf</filename>).
+ </para>
+
+ <example>
+ <title>Showing logind configuration</title>
+ <programlisting>$ systemd-analyze cat-config systemd/logind.conf
+# /etc/systemd/logind.conf
+# This file is part of systemd.
+...
+[Login]
+NAutoVTs=8
+...
+
+# /usr/lib/systemd/logind.conf.d/20-test.conf
+... some override from another package
+
+# /etc/systemd/logind.conf.d/50-override.conf
+... some adminstrator override
+ </programlisting>
+ </example>
+
<para><command>systemd-analyze unit-paths</command> outputs a list of all
directories from which unit files, <filename>.d</filename> overrides, and
<filename>.wants</filename>, <filename>.requires</filename> symlinks may be
generators enabled will generally result in some warnings.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--root=<replaceable>PATH</replaceable></option></term>
+
+ <listitem><para>With <command>cat-files</command>, show config files underneath
+ the specified root path <replaceable>PATH</replaceable>.</para></listitem>
+ </varlistentry>
+
<xi:include href="user-system-options.xml" xpointer="host" />
<xi:include href="user-system-options.xml" xpointer="machine" />
<varlistentry>
<term><option>--no-output</option></term>
- <listitem><para>Do not print passwords to standard output.
- This is useful if you want to store a password in kernel
- keyring with <option>--keyname</option> but do not want it
- to show up on screen or in logs.</para></listitem>
+ <listitem><para>Do not print passwords to standard output.
+ This is useful if you want to store a password in kernel
+ keyring with <option>--keyname</option> but do not want it
+ to show up on screen or in logs.</para></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
Copyright 2012 Lennart Poettering
-->
-<refentry id="systemd-binfmt.service" conditional='ENABLE_BINFMT'>
+<refentry id="systemd-binfmt.service" conditional='ENABLE_BINFMT'
+ xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd-binfmt.service</title>
for information about the configuration of this service.</para>
</refsect1>
+ <refsect1><title>Options</title>
+ <variablelist>
+ <xi:include href="standard-options.xml" xpointer="cat-config" />
+ <xi:include href="standard-options.xml" xpointer="help" />
+ <xi:include href="standard-options.xml" xpointer="version" />
+ </variablelist>
+ </refsect1>
+
<refsect1>
<title>See Also</title>
<para>
<term><option>-r</option></term>
<term><option>--raw</option></term>
- <listitem><para>Format byte counts (as in memory usage and I/O metrics)
- with raw numeric values rather than human-readable
+ <listitem><para>Format byte counts (as in memory usage and I/O metrics)
+ with raw numeric values rather than human-readable
numbers.</para></listitem>
</varlistentry>
core dumps and files can be set in files <filename>/etc/systemd/coredump.conf</filename> and snippets mentioned
above. In addition the storage time of core dump files is restricted by <command>systemd-tmpfiles</command>,
corresponding settings are by default in <filename>/usr/lib/tmpfiles.d/systemd.conf</filename>.</para>
+
+ <refsect2>
+ <title>Disabling coredump processing</title>
+
+ <para>To disable potentially resource-intensive processing by <command>systemd-coredump</command>,
+ set <programlisting>Storage=none
+ProcessSizeMax=0</programlisting> in
+ <citerefentry><refentrytitle>coredump.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para>
+ </refsect2>
</refsect1>
<refsect1>
technology identifier.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--list</option></term>
+
+ <listitem><para>Output all currently known and detectable container and VM environments.</para></listitem>
+ </varlistentry>
+
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
<varlistentry>
<term><option>--unescape</option></term>
+ <term><option>-u</option></term>
<listitem><para>Instead of escaping the specified strings,
undo the escaping, reversing the operation. May not be used in
<varlistentry>
<term><option>--mangle</option></term>
+ <term><option>-m</option></term>
<listitem><para>Like <option>--escape</option>, but only
escape characters that are obviously not escaped yet, and
acquiring one.</para></listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
doing so.</para>
</refsect1>
+ <xi:include href="less-variables.xml" />
+
<refsect1>
<title>See Also</title>
<para>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
- <title>systemd-journal-remote</title>
+ <title>systemd-journal-remote.service</title>
<productname>systemd</productname>
<authorgroup>
</refentryinfo>
<refmeta>
- <refentrytitle>systemd-journal-remote</refentrytitle>
+ <refentrytitle>systemd-journal-remote.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
+ <refname>systemd-journal-remote.service</refname>
+ <refname>systemd-journal-remote.socket</refname>
<refname>systemd-journal-remote</refname>
<refpurpose>Receive journal messages over the network</refpurpose>
</refnamediv>
<refsynopsisdiv>
+ <para><filename>systemd-journal-remote.service</filename></para>
+ <para><filename>systemd-journal-remote.socket</filename></para>
<cmdsynopsis>
- <command>systemd-journal-remote</command>
+ <command>/usr/lib/systemd/systemd-journal-remote</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="opt" rep="norepeat">-o/--output=<replaceable>DIR</replaceable>|<replaceable>FILE</replaceable></arg>
<arg choice="opt" rep="repeat">SOURCES</arg>
<refsect1>
<title>Description</title>
- <para>
- <filename>systemd-journal-remote</filename> is a command to
- receive serialized journal events and store them to the journal.
- Input streams are in the
- <ulink url="https://www.freedesktop.org/wiki/Software/systemd/export">
- Journal Export Format
- </ulink>,
- i.e. like the output from
- <command>journalctl --output=export</command>. For transport over
- the network, this serialized stream is usually carried over an
- HTTPS connection.
- </para>
+ <para><command>systemd-journal-remote</command> is a command to receive serialized journal
+ events and store them to journal files. Input streams are in the
+ <ulink url="https://www.freedesktop.org/wiki/Software/systemd/export">Journal Export Format</ulink>,
+ i.e. like the output from <command>journalctl --output=export</command>. For transport over the
+ network, this serialized stream is usually carried over an HTTPS connection.</para>
+
+ <para><filename>systemd-journal-remote.service</filename> is a system service that uses
+ <command>systemd-journal-remote</command> to listen for connections.
+ <filename>systemd-journal-remote.socket</filename> configures the network address that
+ <filename>systemd-journal-remote.service</filename> listens on. By default this is port 19532.
+ What connections are accepted and how the received data is stored can be configured through the
+ <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ configuration file.</para>
</refsect1>
<refsect1>
interpreted as the (negated) file descriptor number, or an
address suitable for <option>ListenStream=</option> (c.f.
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
- In the first case, matching file descriptor must be inherited
- through
+ In the first case, the server listens on port 19532 by default,
+ and the matching file descriptor must be inherited through
<varname>$LISTEN_FDS</varname>/<varname>$LISTEN_PID</varname>.
In the second case, an HTTP or HTTPS server will be spawned on
this port, respectively for <option>--listen-http=</option> and
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemd-journal-gatewayd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
- <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd-journal-gatewayd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
- <title>systemd-journal-upload</title>
+ <title>systemd-journal-upload.service</title>
<productname>systemd</productname>
<authorgroup>
</refentryinfo>
<refmeta>
- <refentrytitle>systemd-journal-upload</refentrytitle>
+ <refentrytitle>systemd-journal-upload.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
+ <refname>systemd-journal-upload.service</refname>
<refname>systemd-journal-upload</refname>
<refpurpose>Send journal messages over the network</refpurpose>
</refnamediv>
<refsynopsisdiv>
+ <para><filename>systemd-journal-upload.service</filename></para>
<cmdsynopsis>
- <command>systemd-journal-upload</command>
+ <command>/usr/lib/systemd/systemd-journal-upload</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="opt" rep="norepeat">-u/--url=<replaceable>URL</replaceable></arg>
<arg choice="opt" rep="repeat">SOURCES</arg>
Unless limited by one of the options specified below, all journal entries accessible to the user
the program is running as will be uploaded, and then the program will wait and send new entries
as they become available.</para>
+
+ <para><filename>systemd-journal-upload.service</filename> is a system service that uses
+ <command>systemd-journal-upload</command> to upload journal entries to a server. It uses the
+ configuration in
+ <citerefentry><refentrytitle>journal-upload.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ At least the <varname>URL=</varname> option must be specified.</para>
</refsect1>
<refsect1>
<variablelist>
<varlistentry>
<term><option>-u</option></term>
- <term><option>--url=<optional>https://</optional><replaceable>URL</replaceable></option></term>
- <term><option>--url=<optional>http://</optional><replaceable>URL</replaceable></option></term>
+ <term><option>--url=<optional>https://</optional><replaceable>URL</replaceable>[:<replaceable>PORT</replaceable>]</option></term>
+ <term><option>--url=<optional>http://</optional><replaceable>URL</replaceable>[:<replaceable>PORT</replaceable>]</option></term>
<listitem><para>Upload to the specified
address. <replaceable>URL</replaceable> may specify either
just the hostname or both the protocol and
hostname. <constant>https</constant> is the default.
+ The port number may be specified after a colon (<literal>:</literal>),
+ otherwise <constant>19532</constant> will be used by default.
</para></listitem>
</varlistentry>
legitimate, and vice versa, that the client is trusted.</para>
<para>A suitable set of certificates can be generated with
- <command>openssl</command>:</para>
+ <command>openssl</command>. Note, 2048 bits of key length
+ is minimally recommended to use for security reasons:</para>
<programlisting>openssl req -newkey rsa:2048 -days 3650 -x509 -nodes \
-out ca.pem -keyout ca.key -subj '/CN=Certificate authority/'
SERVER=server
CLIENT=client
-openssl req -newkey rsa:1024 -nodes -out $SERVER.csr -keyout $SERVER.key -subj "/CN=$SERVER/"
+openssl req -newkey rsa:2048 -nodes -out $SERVER.csr -keyout $SERVER.key -subj "/CN=$SERVER/"
openssl ca -batch -config ca.conf -notext -in $SERVER.csr -out $SERVER.pem
-openssl req -newkey rsa:1024 -nodes -out $CLIENT.csr -keyout $CLIENT.key -subj "/CN=$CLIENT/"
+openssl req -newkey rsa:2048 -nodes -out $CLIENT.csr -keyout $CLIENT.key -subj "/CN=$CLIENT/"
openssl ca -batch -config ca.conf -notext -in $CLIENT.csr -out $CLIENT.pem
</programlisting>
<refsect1>
<title>See Also</title>
<para>
- <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>journal-upload.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-journal-gatewayd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
<refentry id="systemd-networkd-wait-online.service" conditional='ENABLE_NETWORKD'>
<refentryinfo>
- <title>systemd-networkd.service</title>
+ <title>systemd-networkd-wait-online.service</title>
<productname>systemd</productname>
<authorgroup>
<title>Description</title>
<para><command>systemd-networkd-wait-online</command> is a
- one-shot system service that waits for the network to be
+ oneshot system service (see <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>), that waits for the network to be
configured. By default, it will wait for all links it is aware of
and which are managed by
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
</para>
</refsect1>
instead.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--hostname=</option></term>
+
+ <listitem><para>Controls the hostname to set within the container, if different from the machine name. Expects
+ a valid hostname as argument. If this option is used, the kernel hostname of the container will be set to this
+ value, otherwise it will be initialized to the machine name as controlled by the <option>--machine=</option>
+ option described above. The machine name is used for various aspect of identification of the container from the
+ outside, the kernel hostname configurable with this option is useful for the container to identify itself from
+ the inside. It is usually a good idea to keep both forms of identification synchronized, in order to avoid
+ confusion. It is hence recommended to avoid usage of this option, and use <option>--machine=</option>
+ exclusively. Note that regardless whether the container's hostname is initialized from the name set with
+ <option>--hostname=</option> or the one set with <option>--machine=</option>, the container can later override
+ its kernel hostname freely on its own as well.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--uuid=</option></term>
above).</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--no-new-privileges=</option></term>
+
+ <listitem><para>Takes a boolean argument. Specifies the value of the <constant>PR_SET_NO_NEW_PRIVS</constant>
+ flag for the container payload. Defaults to off. When turned on the payload code of the container cannot
+ acquire new privileges, i.e. the "setuid" file bit as well as file system capabilities will not have an effect
+ anymore. See <citerefentry
+ project='man-pages'><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry> for details
+ about this flag. </para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--system-call-filter=</option></term>
<listitem><para>Alter the system call filter applied to containers. Takes a space-separated list of system call
names or group names (the latter prefixed with <literal>@</literal>, as listed by the
- <command>syscall-filter</command> command of <citerefentry
- project='man-pages'><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>). Passed
+ <command>syscall-filter</command> command of
+ <citerefentry><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>). Passed
system calls will be permitted. The list may optionally be prefixed by <literal>~</literal>, in which case all
listed system calls are prohibited. If this command line option is used multiple times the configured lists are
combined. If both a positive and a negative list (that is one system call list without and one with the
capabilities are passed using the <command>--capabilities=</command>.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--rlimit=</option></term>
+
+ <listitem><para>Sets the specified POSIX resource limit for the container payload. Expects an assignment of the
+ form
+ <literal><replaceable>LIMIT</replaceable>=<replaceable>SOFT</replaceable>:<replaceable>HARD</replaceable></literal>
+ or <literal><replaceable>LIMIT</replaceable>=<replaceable>VALUE</replaceable></literal>, where
+ <replaceable>LIMIT</replaceable> should refer to a resource limit type, such as
+ <constant>RLIMIT_NOFILE</constant> or <constant>RLIMIT_NICE</constant>. The <replaceable>SOFT</replaceable> and
+ <replaceable>HARD</replaceable> fields should refer to the numeric soft and hard resource limit values. If the
+ second form is used, <replaceable>VALUE</replaceable> may specifiy a value that is used both as soft and hard
+ limit. In place of a numeric value the special string <literal>infinity</literal> may be used to turn off
+ resource limiting for the specific type of resource. This command line option may be used multiple times to
+ control limits on multiple limit types. If used multiple times for the same limit type, the last last use
+ wins. For details about resource limits see <citerefentry
+ project='man-pages'><refentrytitle>setrlimit</refentrytitle><manvolnum>2</manvolnum></citerefentry>. By default
+ resource limits for the container's init process (PID 1) are set to the same values the Linux kernel originally
+ passed to the host init system. Note that some resource limits are enforced on resources counted per user, in
+ particular <constant>RLIMIT_NPROC</constant>. This means that unless user namespacing is deployed
+ (i.e. <option>--private-users=</option> is used, see above), any limits set will be applied to the resource
+ usage of the same user on all local containers as well as the host. This means particular care needs to be
+ taken with these limits as they might be triggered by possibly less trusted code. Example:
+ <literal>--rlimit=RLIMIT_NOFILE=8192:16384</literal>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--oom-score-adjust=</option></term>
+
+ <listitem><para>Changes the OOM ("Out Of Memory") score adjustment value for the container payload. This controls
+ <filename>/proc/self/oom_score_adj</filename> which influences the preference with which this container is
+ terminated when memory becomes scarce. For details see <citerefentry
+ project='man-pages'><refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum></citerefentry>. Takes an
+ integer in the range -1000…1000.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--cpu-affinity=</option></term>
+
+ <listitem><para>Controls the CPU affinity of the container payload. Takes a comma separated list of CPU numbers
+ or number ranges (the latter's start and end value separated by dashes). See <citerefentry
+ project='man-pages'><refentrytitle>sched_setaffinity</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--kill-signal=</option></term>
- <listitem><para>Specify the process signal to send to the
- container's PID 1 when nspawn itself receives SIGTERM, in
- order to trigger an orderly shutdown of the
- container. Defaults to SIGRTMIN+3 if <option>--boot</option>
- is used (on systemd-compatible init systems SIGRTMIN+3
- triggers an orderly shutdown). For a list of valid signals, see
- <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para></listitem>
+ <listitem><para>Specify the process signal to send to the container's PID 1 when nspawn itself receives
+ <constant>SIGTERM</constant>, in order to trigger an orderly shutdown of the container. Defaults to
+ <constant>SIGRTMIN+3</constant> if <option>--boot</option> is used (on systemd-compatible init systems
+ <constant>SIGRTMIN+3</constant> triggers an orderly shutdown). If <option>--boot</option> is not used and this
+ option is not specified the container's processes are terminated abrubtly via <constant>SIGKILL</constant>. For
+ a list of valid signals, see <citerefentry
+ project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para></listitem>
</varlistentry>
<varlistentry>
<option>--link-journal=try-guest</option>.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--resolv-conf=</option></term>
+
+ <listitem><para>Configures how <filename>/etc/resolv.conf</filename> inside of the container (i.e. DNS
+ configuration synchronization from host to container) shall be handled. Takes one of <literal>off</literal>,
+ <literal>copy-host</literal>, <literal>copy-static</literal>, <literal>bind-host</literal>,
+ <literal>bind-static</literal>, <literal>delete</literal> or <literal>auto</literal>. If set to
+ <literal>off</literal> the <filename>/etc/resolv.conf</filename> file in the container is left as it is
+ included in the image, and neither modified nor bind mounted over. If set to <literal>copy-host</literal>, the
+ <filename>/etc/resolv.conf</filename> file from the host is copied into the container. Similar, if
+ <literal>bind-host</literal> is used, the file is bind mounted from the host into the container. If set to
+ <literal>copy-static</literal> the static <filename>resolv.conf</filename> file supplied with
+ <citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> is
+ copied into the container, and correspondingly <literal>bind-static</literal> bind mounts it there. If set to
+ <literal>delete</literal> the <filename>/etc/resolv.conf</filename> file in the container is deleted if it
+ exists. Finally, if set to <literal>auto</literal> the file is left as it is if private networking is turned on
+ (see <option>--private-network</option>). Otherwise, if <filename>systemd-resolved.service</filename> is
+ connectible its static <filename>resolv.conf</filename> file is used, and if not the host's
+ <filename>/etc/resolv.conf</filename> file is used. In the latter cases the file is copied if the image is
+ writable, and bind mounted otherwise. It's recommended to use <literal>copy</literal> if the container shall be
+ able to make changes to the DNS configuration on its own, deviating from the host's settings. Otherwise
+ <literal>bind</literal> is preferable, as it means direct changes to <filename>/etc/resolv.conf</filename> in
+ the container are not allowed, as it is a read-only bind mount (but note that if the container has enough
+ privileges, it might simply go ahead and unmount the bind mount anyway). Note that both if the file is bind
+ mounted and if it is copied no further propagation of configuration is generally done after the one-time early
+ initialization (this is because the file is usually updated through copying and renaming). Defaults to
+ <literal>auto</literal>.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--timezone=</option></term>
+
+ <listitem><para>Configures how <filename>/etc/localtime</filename> inside of the container (i.e. local timezone
+ synchronization from host to container) shall be handled. Takes one of <literal>off</literal>,
+ <literal>copy</literal>, <literal>bind</literal>, <literal>symlink</literal>, <literal>delete</literal> or
+ <literal>auto</literal>. If set to <literal>off</literal> the <filename>/etc/localtime</filename> file in the
+ container is left as it is included in the image, and neither modified nor bind mounted over. If set to
+ <literal>copy</literal> the <filename>/etc/localtime</filename> file of the host is copied into the
+ container. Similar, if <literal>bind</literal> is used, it is bind mounted from the host into the container. If
+ set to <literal>symlink</literal> a symlink from <filename>/etc/localtime</filename> in the container is
+ created pointing to the matching the timezone file of the container that matches the timezone setting on the
+ host. If set to <literal>delete</literal> the file in the container is deleted, should it exist. If set to
+ <literal>auto</literal> and the <filename>/etc/localtime</filename> file of the host is a symlink, then
+ <literal>symlink</literal> mode is used, and <literal>copy</literal> otherwise, except if the image is
+ read-only in which case <literal>bind</literal> is used instead. Defaults to
+ <literal>auto</literal>.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--read-only</option></term>
</listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="cat-config" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
line instead of a file name.</para></listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="cat-config" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
</para></listitem>
</varlistentry>
+ <xi:include href="standard-options.xml" xpointer="cat-config" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
<filename>/usr/include/sysexits.h</filename>). If the configuration was syntactically valid, but
could not be executed (lack of permissions, creation of files in missing directories, invalid
contents when writing to <filename>/sys/</filename> values, …), <constant>73</constant> is
- returned (<constant>EX_DATAERR</constant> from <filename>/usr/include/sysexits.h</filename>).
+ returned (<constant>EX_CANTCREAT</constant> from <filename>/usr/include/sysexits.h</filename>).
Otherwise, <constant>1</constant> is returned (<constant>EXIT_FAILURE</constant> from
<filename>/usr/include/stdlib.h</filename>).
</para>
<para>The <option>file:<replaceable>path</replaceable></option> option may be used to connect a specific file
system object to standard output. The semantics are similar to the same option of
- <varname>StandardInputText=</varname>, see above. If standard input and output are directed to the same file
- path, it is opened only once, for reading as well as writing and duplicated. This is particular useful when the
+ <varname>StandardInput=</varname>, see above. If standard input and output are directed to the same file path,
+ it is opened only once, for reading as well as writing and duplicated. This is particular useful when the
specified path refers to an <constant>AF_UNIX</constant> socket in the file system, as in that case only a
single stream connection is created for both input and output.</para>
<varlistentry>
<term><varname>MACAddress=</varname></term>
<listitem>
- <para>The hardware address.</para>
+ <para>A whitespace-separated list of hardware addresses. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example below.
+ This option may appear more than once, in which case the lists are merged. If the empty string is assigned to this option, the list
+ of hardware addresses defined prior to this is reset.</para>
+
+ <para>Example:
+ <programlisting>MACAddress=01:23:45:67:89:ab 00-11-22-33-44-55 AABB.CCDD.EEFF</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
Defaults to "unset".</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>RxChannels=</varname></term>
+ <listitem>
+ <para>Sets the number of receive channels (a number between 1 and 4294967295) .</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>TxChannels=</varname></term>
+ <listitem>
+ <para>Sets the number of transmit channels (a number between 1 and 4294967295).</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>OtherChannels=</varname></term>
+ <listitem>
+ <para>Sets the number of other channels (a number between 1 and 4294967295).</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>CombinedChannels=</varname></term>
+ <listitem>
+ <para>Sets the number of combined set channels (a number between 1 and 4294967295).</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<varlistentry>
<term><varname>MACAddress=</varname></term>
<listitem>
- <para>The hardware address of the interface (use full colon-delimited hexadecimal, e.g.,
- 01:23:45:67:89:ab).</para>
+ <para>A whitespace-separated list of hardware addresses. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example below.
+ This option may appear more than one, in which case the lists are merged. If the empty string is assigned to this option, the list
+ of hardware addresses defined prior to this is reset.</para>
+
+ <para>Example:
+ <programlisting>MACAddress=01:23:45:67:89:ab 00-11-22-33-44-55 AABB.CCDD.EEFF</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
</para>
</listitem>
</varlistentry>
-
+ <varlistentry>
+ <term><varname>MTUBytes=</varname></term>
+ <listitem>
+ <para>The maximum transmission unit in bytes to set for the
+ route. The usual suffixes K, M, G, are supported and are
+ understood to the base of 1024.</para>
+ <para>Note that if IPv6 is enabled on the interface, and the MTU is chosen
+ below 1280 (the minimum MTU for IPv6) it will automatically be increased to this value.</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>UserClass=</varname></term>
+ <listitem>
+ <para>A DHCPv4 client can use UserClass option to identify the type or category of user or applications
+ it represents. The information contained in this option is a string that represents the user class of which
+ the client is a member. Each class sets an identifying string of information to be used by the DHCP
+ service to classify clients. Takes a whitespace-separated list of strings.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>DUIDType=</varname></term>
<listitem>
all cases.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>NoNewPrivileges=</varname></term>
+
+ <listitem><para>Takes a boolean argument that controls the <constant>PR_SET_NO_NEW_PRIVS</constant> flag for
+ the container payload. This is equivalent to the
+ <option>--no-new-privileges=</option> command line switch. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>KillSignal=</varname></term>
details.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>LimitCPU=</varname></term>
+ <term><varname>LimitFSIZE=</varname></term>
+ <term><varname>LimitDATA=</varname></term>
+ <term><varname>LimitSTACK=</varname></term>
+ <term><varname>LimitCORE=</varname></term>
+ <term><varname>LimitRSS=</varname></term>
+ <term><varname>LimitNOFILE=</varname></term>
+ <term><varname>LimitAS=</varname></term>
+ <term><varname>LimitNPROC=</varname></term>
+ <term><varname>LimitMEMLOCK=</varname></term>
+ <term><varname>LimitLOCKS=</varname></term>
+ <term><varname>LimitSIGPENDING=</varname></term>
+ <term><varname>LimitMSGQUEUE=</varname></term>
+ <term><varname>LimitNICE=</varname></term>
+ <term><varname>LimitRTPRIO=</varname></term>
+ <term><varname>LimitRTTIME=</varname></term>
+
+ <listitem><para>Configures various types of resource limits applied to containers. This is equivalent to the
+ <option>--rlimit=</option> command line switch, and takes the same arguments. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>OOMScoreAdjust=</varname></term>
+
+ <listitem><para>Configures the OOM score adjustment value. This is equivalent to the
+ <option>--oom-score-adjust=</option> command line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>CPUAffinity=</varname></term>
+
+ <listitem><para>Configures the CPU affinity. This is equivalent to the <option>--cpu-affinity=</option> command
+ line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>Hostname=</varname></term>
+
+ <listitem><para>Configures the kernel hostname set for the container. This is equivalent to the
+ <option>--hostname=</option> command line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>ResolvConf=</varname></term>
+
+ <listitem><para>Configures how <filename>/etc/resolv.conf</filename> in the container shall be handled. This is
+ equivalent to the <option>--resolv-conf=</option> command line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>Timezone=</varname></term>
+
+ <listitem><para>Configures how <filename>/etc/localtime</filename> in the container shall be handled. This is
+ equivalent to the <option>--localtime=</option> command line switch, and takes the same argument. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><varname>LinkJournal=</varname></term>
+
+ <listitem><para>Configures how to link host and container journal setups. This is equivalent to the
+ <option>--link-journal=</option> command line switch, and takes the same parameter. See
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+ details.</para></listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
must occur before <varname>RuntimeMaxSec=</varname> is exceeded, and once the runtime has exended beyond
<varname>RuntimeMaxSec=</varname>, the service manager will allow the service to continue to run, provided
the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified until the service
- shutdown is acheived by <literal>STOPPING=1</literal> (or termination). (see
+ shutdown is achieved by <literal>STOPPING=1</literal> (or termination). (see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
</para></listitem>
</varlistentry>
passed to the service manager from a specific service are passed back to the service's main process on the next
service restart. Any file descriptors passed to the service manager are automatically closed when
<constant>POLLHUP</constant> or <constant>POLLERR</constant> is seen on them, or when the service is fully
- stopped and no job is queued or being executed for it.</para></listitem>
+ stopped and no job is queued or being executed for it. If this option is used, <varname>NotifyAccess=</varname>
+ (see above) should be set to open access to the notification socket provided by systemd. If
+ <varname>NotifyAccess=</varname> is not set, it will be implicitly set to
+ <option>main</option>.</para></listitem>
</varlistentry>
<varlistentry>
functionality to other hosts generally do not need to pull
this in.</para>
+ <para>systemd automatically adds dependencies of type <varname>Wants=</varname> and <varname>After=</varname>
+ for this target unit to all SysV init script service units with an LSB header referring to the
+ <literal>$network</literal> facility.</para>
+
<para>Note that this unit is only useful during the original system start-up logic. After the system has
completed booting up, it will not track the online state of the system anymore. Due to this it cannot be used
as a network connection monitor concept, it is purely a one-time system start-up concept.</para>
information. Also see
<filename>network-online.target</filename> described
above.</para>
-
- <para>systemd automatically adds dependencies of type
- <varname>After=</varname> for this target unit to all SysV
- init script service units with an LSB header referring to
- the <literal>$network</literal> facility.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><filename>nss-lookup.target</filename></term>
<listitem>
- <para>A target that should be used as synchronization point
- for all host/network name service lookups. Note that this is
- independent of user/group name lookups for which
- <filename>nss-user-lookup.target</filename> should be used.
- All services for which the availability of full host/network
- name resolution is essential should be ordered after this
- target, but not pull it in. systemd automatically adds
- dependencies of type <varname>After=</varname> for this
- target unit to all SysV init script service units with an
- LSB header referring to the <literal>$named</literal>
- facility.</para>
+ <para>A target that should be used as synchronization point for all host/network name service lookups. Note
+ that this is independent of UNIX user/group name lookups for which <filename>nss-user-lookup.target</filename>
+ should be used. All services for which the availability of full host/network name resolution is essential
+ should be ordered after this target, but not pull it in. systemd automatically adds dependencies of type
+ <varname>After=</varname> for this target unit to all SysV init script service units with an LSB header
+ referring to the <literal>$named</literal> facility.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>nss-user-lookup.target</filename></term>
<listitem>
- <para>A target that should be used as synchronization point
- for all user/group name service lookups. Note that this is
- independent of host/network name lookups for which
- <filename>nss-lookup.target</filename> should be used. All
- services for which the availability of the full user/group
- database is essential should be ordered after this target,
- but not pull it in. Note that system users are always
- resolvable, and hence do not require any special ordering
- against this target.</para>
+ <para>A target that should be used as synchronization point for all regular UNIX user/group name service
+ lookups. Note that this is independent of host/network name lookups for which
+ <filename>nss-lookup.target</filename> should be used. All services for which the availability of the full
+ user/group database is essential should be ordered after this target, but not pull it in. All services which
+ provide parts of the user/group database should be ordered before this target, and pull it in. Note that this
+ unit is only relevant for regular users and groups — system users and groups are required to be resolvable
+ during earliest boot already, and hence do not need any special ordering against this target.</para>
</listitem>
</varlistentry>
<varlistentry>
<para>The set of load paths for the user manager instance may be augmented or
changed using various environment variables. And environment variables may in
turn be set using environment generators, see
- <citerefentry><refentrytitle>system.environment-generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+ <citerefentry><refentrytitle>systemd.environment-generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
In particular, <varname>$XDG_DATA_HOME</varname> and
<varname>$XDG_DATA_DIRS</varname> may be easily set using
<citerefentry><refentrytitle>systemd-environment-d-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
<term><option>-d</option></term>
<term><option>--debug</option></term>
<listitem>
- <para>Print debug messages to standard error.</para>
+ <para>Print debug messages to standard error. This option is implied in <command>udevadm test</command> and
+ <command>udevadm test-builtin</command> commands.</para>
</listitem>
</varlistentry>
<filename><optional>/sys</optional>/class/block/sda</filename>.
Note that this option usually is not very useful, since
<command>udev</command> can guess the type of the
- argument, so <command>udevadm
- --devpath=/class/block/sda</command> is equivalent to
- <command>udevadm /sys/class/block/sda</command>.</para>
+ argument, so <command>udevadm info
+ --path=/class/block/sda</command> is equivalent to
+ <command>udevadm info /sys/class/block/sda</command>.</para>
</listitem>
</varlistentry>
<varlistentry>
e.g. <filename><optional>/dev</optional>/sda</filename>.
Note that this option usually is not very useful, since
<command>udev</command> can guess the type of the
- argument, so <command>udevadm --name=sda</command> is
- equivalent to <command>udevadm /dev/sda</command>.</para>
+ argument, so <command>udevadm info --name=sda</command> is
+ equivalent to <command>udevadm info /dev/sda</command>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-y</option></term>
<term><option>--sysname-match=<replaceable>PATH</replaceable></option></term>
<listitem>
- <para>Trigger events for devices for which the last component
- (i.e. the filename) of the <filename>/sys</filename> path matches
- the specified <replaceable>PATH</replaceable>. This option can be
- specified multiple times and also supports shell style pattern
- matching.</para>
+ <para>Trigger events for devices for which the last component
+ (i.e. the filename) of the <filename>/sys</filename> path matches
+ the specified <replaceable>PATH</replaceable>. This option can be
+ specified multiple times and also supports shell style pattern
+ matching.</para>
</listitem>
</varlistentry>
<varlistentry>
'sysconfdir=/etc',
'localstatedir=/var',
],
- meson_version : '>= 0.41',
+ meson_version : '>= 0.44',
)
libsystemd_version = '0.22.0'
libudev_version = '1.6.10'
-# We need the same data in three different formats, ugh!
+# We need the same data in two different formats, ugh!
# Also, for hysterical reasons, we use different variable
# names, sometimes. Not all variables are included in every
# set. Ugh, ugh, ugh!
substs.set('PACKAGE_URL', 'https://www.freedesktop.org/wiki/Software/systemd')
substs.set('PACKAGE_VERSION', meson.project_version())
-m4_defines = []
-
#####################################################################
# Try to install the git pre-commit hook
sysvinit_path = get_option('sysvinit-path')
sysvrcnd_path = get_option('sysvrcnd-path')
-have = sysvinit_path != '' and sysvrcnd_path != ''
-conf.set10('HAVE_SYSV_COMPAT', have,
+conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '',
description : 'SysV init scripts and rcN.d links are supported')
-m4_defines += have ? ['-DHAVE_SYSV_COMPAT'] : []
# join_paths ignore the preceding arguments if an absolute component is
# encountered, so this should canonicalize various paths when they are
substs.set('udevhwdbdir', udevhwdbdir)
substs.set('udevrulesdir', udevrulesdir)
substs.set('udevlibexecdir', udevlibexecdir)
+substs.set('environmentdir', environmentdir)
substs.set('catalogdir', catalogdir)
substs.set('tmpfilesdir', tmpfilesdir)
substs.set('sysusersdir', sysusersdir)
substs.set('sysctldir', sysctldir)
substs.set('binfmtdir', binfmtdir)
substs.set('modulesloaddir', modulesloaddir)
+substs.set('modprobedir', modprobedir)
substs.set('systemgeneratordir', systemgeneratordir)
substs.set('usergeneratordir', usergeneratordir)
substs.set('systemenvgeneratordir', systemenvgeneratordir)
fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine')
endif
-foreach arg : ['-Wextra',
- '-Werror=undef',
- '-Wlogical-op',
- '-Wmissing-include-dirs',
- '-Wold-style-definition',
- '-Wpointer-arith',
- '-Winit-self',
- '-Wdeclaration-after-statement',
- '-Wfloat-equal',
- '-Wsuggest-attribute=noreturn',
- '-Werror=missing-prototypes',
- '-Werror=implicit-function-declaration',
- '-Werror=missing-declarations',
- '-Werror=return-type',
- '-Werror=incompatible-pointer-types',
- '-Werror=format=2',
- '-Wstrict-prototypes',
- '-Wredundant-decls',
- '-Wmissing-noreturn',
- '-Wimplicit-fallthrough=5',
- '-Wshadow',
- '-Wendif-labels',
- '-Wstrict-aliasing=2',
- '-Wwrite-strings',
- '-Werror=overflow',
- '-Wdate-time',
- '-Wnested-externs',
- '-ffast-math',
- '-fno-common',
- '-fdiagnostics-show-option',
- '-fno-strict-aliasing',
- '-fvisibility=hidden',
- '-fstack-protector',
- '-fstack-protector-strong',
- '--param=ssp-buffer-size=4',
- ]
- if cc.has_argument(arg)
- add_project_arguments(arg, language : 'c')
- endif
-endforeach
+possible_cc_flags = [
+ '-Wextra',
+ '-Werror=undef',
+ '-Wlogical-op',
+ '-Wmissing-include-dirs',
+ '-Wold-style-definition',
+ '-Wpointer-arith',
+ '-Winit-self',
+ '-Wdeclaration-after-statement',
+ '-Wfloat-equal',
+ '-Wsuggest-attribute=noreturn',
+ '-Werror=missing-prototypes',
+ '-Werror=implicit-function-declaration',
+ '-Werror=missing-declarations',
+ '-Werror=return-type',
+ '-Werror=incompatible-pointer-types',
+ '-Werror=format=2',
+ '-Wstrict-prototypes',
+ '-Wredundant-decls',
+ '-Wmissing-noreturn',
+ '-Wimplicit-fallthrough=5',
+ '-Wshadow',
+ '-Wendif-labels',
+ '-Wstrict-aliasing=2',
+ '-Wwrite-strings',
+ '-Werror=overflow',
+ '-Wdate-time',
+ '-Wnested-externs',
+ '-ffast-math',
+ '-fno-common',
+ '-fdiagnostics-show-option',
+ '-fno-strict-aliasing',
+ '-fvisibility=hidden',
+ '-fstack-protector',
+ '-fstack-protector-strong',
+ '--param=ssp-buffer-size=4',
+]
+
+# --as-needed and --no-undefined are provided by meson by default,
+# run mesonconf to see what is enabled
+possible_link_flags = [
+ '-Wl,-z,relro',
+ '-Wl,-z,now',
+]
# the oss-fuzz fuzzers are not built with -fPIE, so don't
# enable it when we are linking against them
if not fuzzer_build
- if cc.has_argument('-fPIE')
- add_project_arguments('-fPIE', language : 'c')
- endif
+ possible_cc_flags += '-fPIE'
+ possible_link_flags += '-pie'
+endif
+
+if cc.get_id() == 'clang'
+ possible_cc_flags += [
+ '-Wno-typedef-redefinition',
+ '-Wno-gnu-variable-sized-type-not-at-end',
+ ]
+endif
+
+if get_option('buildtype') != 'debug'
+ possible_cc_flags += [
+ '-ffunction-sections',
+ '-fdata-sections',
+ ]
+
+ possible_link_flags += '-Wl,--gc-sections'
endif
+add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'c')
+
# "negative" arguments: gcc on purpose does not return an error for "-Wno-"
# arguments, just emits a warnings. So test for the "positive" version instead.
foreach arg : ['unused-parameter',
add_project_arguments('-Werror=shadow', language : 'c')
endif
-if cc.get_id() == 'clang'
- foreach arg : ['-Wno-typedef-redefinition',
- '-Wno-gnu-variable-sized-type-not-at-end',
- ]
- if cc.has_argument(arg)
- add_project_arguments(arg, language : 'c')
- endif
- endforeach
-endif
-
link_test_c = files('tools/meson-link-test.c')
-# --as-needed and --no-undefined are provided by meson by default,
-# run mesonconf to see what is enabled
-foreach arg : ['-Wl,-z,relro',
- '-Wl,-z,now',
- '-pie',
- ]
-
+foreach arg : possible_link_flags
have = run_command(check_compilation_sh,
cc.cmd_array(), '-x', 'c', arg,
'-include', link_test_c).returncode() == 0
message('Linking with @0@ supported: @1@'.format(arg, have ? 'yes' : 'no'))
- if have and (arg != '-pie' or not fuzzer_build)
+ if have
add_project_link_arguments(arg, language : 'c')
endif
endforeach
-if get_option('buildtype') != 'debug'
- foreach arg : ['-ffunction-sections',
- '-fdata-sections']
- if cc.has_argument(arg)
- add_project_arguments(arg, language : 'c')
- endif
- endforeach
-
- foreach arg : ['-Wl,--gc-sections']
- have = run_command(check_compilation_sh,
- cc.cmd_array(), '-x', 'c', arg,
- '-include', link_test_c).returncode() == 0
- message('Linking with @0@ supported: @1@'.format(arg, have ? 'yes' : 'no'))
- if have
- add_project_link_arguments(arg, language : 'c')
- endif
- endforeach
-endif
-
cpp = ' '.join(cc.cmd_array()) + ' -E'
#####################################################################
if getent_result.returncode() == 0
name = getent_result.stdout().split(':')[0]
if name != nobody_user
- message('WARNING:\n' +
- ' The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) +
- ' Your build will result in an user table setup that is incompatible with the local system.')
+ warning('\n' +
+ 'The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) +
+ 'Your build will result in an user table setup that is incompatible with the local system.')
endif
endif
id_result = run_command('id', '-u', nobody_user)
if id_result.returncode() == 0
id = id_result.stdout().to_int()
if id != 65534
- message('WARNING:\n' +
- ' The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) +
- ' Your build will result in an user table setup that is incompatible with the local system.')
+ warning('\n' +
+ 'The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) +
+ 'Your build will result in an user table setup that is incompatible with the local system.')
endif
endif
if getent_result.returncode() == 0
name = getent_result.stdout().split(':')[0]
if name != nobody_group
- message('WARNING:\n' +
- ' The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) +
- ' Your build will result in an group table setup that is incompatible with the local system.')
+ warning('\n' +
+ 'The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) +
+ 'Your build will result in an group table setup that is incompatible with the local system.')
endif
endif
id_result = run_command('id', '-g', nobody_group)
if id_result.returncode() == 0
id = id_result.stdout().to_int()
if id != 65534
- message('WARNING:\n' +
- ' The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) +
- ' Your build will result in an group table setup that is incompatible with the local system.')
+ warning('\n' +
+ 'The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) +
+ 'Your build will result in an group table setup that is incompatible with the local system.')
endif
endif
if nobody_user != nobody_group and not (nobody_user == 'nobody' and nobody_group == 'nogroup')
- message('WARNING:\n' +
- ' The configured user name "@0@" and group name "@0@" of the nobody user/group are not equivalent.\n'.format(nobody_user, nobody_group) +
- ' Please re-check that both "nobody-user" and "nobody-group" options are correctly set.')
+ warning('\n' +
+ 'The configured user name "@0@" and group name "@0@" of the nobody user/group are not equivalent.\n'.format(nobody_user, nobody_group) +
+ 'Please re-check that both "nobody-user" and "nobody-group" options are correctly set.')
endif
conf.set_quoted('NOBODY_USER_NAME', nobody_user)
endif
substs.set('USERS_GID', users_gid)
-if get_option('adm-group')
- m4_defines += ['-DENABLE_ADM_GROUP']
-endif
-
-if get_option('wheel-group')
- m4_defines += ['-DENABLE_WHEEL_GROUP']
-endif
+conf.set10('ENABLE_ADM_GROUP', get_option('adm-group'))
+conf.set10('ENABLE_WHEEL_GROUP', get_option('wheel-group'))
substs.set('DEV_KVM_MODE', get_option('dev-kvm-mode'))
substs.set('GROUP_RENDER_MODE', get_option('group-render-mode'))
substs.set('SUSHELL', get_option('debug-shell'))
substs.set('DEBUGTTY', get_option('debug-tty'))
-debug = get_option('debug')
enable_debug_hashmap = false
enable_debug_mmap_cache = false
-if debug != ''
- foreach name : debug.split(',')
- if name == 'hashmap'
- enable_debug_hashmap = true
- elif name == 'mmap-cache'
- enable_debug_mmap_cache = true
- else
- message('unknown debug option "@0@", ignoring'.format(name))
- endif
- endforeach
-endif
+foreach name : get_option('debug')
+ if name == 'hashmap'
+ enable_debug_hashmap = true
+ elif name == 'mmap-cache'
+ enable_debug_mmap_cache = true
+ else
+ message('unknown debug option "@0@", ignoring'.format(name))
+ endif
+endforeach
conf.set10('ENABLE_DEBUG_HASHMAP', enable_debug_hashmap)
conf.set10('ENABLE_DEBUG_MMAP_CACHE', enable_debug_mmap_cache)
+conf.set10('VALGRIND', get_option('valgrind'))
+
#####################################################################
threads = dependency('threads')
libseccomp = []
endif
conf.set10('HAVE_SECCOMP', have)
-m4_defines += have ? ['-DHAVE_SECCOMP'] : []
want_selinux = get_option('selinux')
if want_selinux != 'false' and not fuzzer_build
libselinux = []
endif
conf.set10('HAVE_SELINUX', have)
-m4_defines += have ? ['-DHAVE_SELINUX'] : []
want_apparmor = get_option('apparmor')
if want_apparmor != 'false' and not fuzzer_build
libapparmor = []
endif
conf.set10('HAVE_APPARMOR', have)
-m4_defines += have ? ['-DHAVE_APPARMOR'] : []
smack_run_label = get_option('smack-run-label')
if smack_run_label != ''
conf.set_quoted('SMACK_RUN_LABEL', smack_run_label)
- m4_defines += ['-DHAVE_SMACK_RUN_LABEL']
endif
want_polkit = get_option('polkit')
libacl = []
endif
conf.set10('HAVE_ACL', have)
-m4_defines += have ? ['-DHAVE_ACL'] : []
want_audit = get_option('audit')
if want_audit != 'false' and not fuzzer_build
libpam_misc = []
endif
conf.set10('HAVE_PAM', have)
-m4_defines += have ? ['-DHAVE_PAM'] : []
want_microhttpd = get_option('microhttpd')
if want_microhttpd != 'false' and not fuzzer_build
libmicrohttpd = []
endif
conf.set10('HAVE_MICROHTTPD', have)
-m4_defines += have ? ['-DHAVE_MICROHTTPD'] : []
want_libcryptsetup = get_option('libcryptsetup')
if want_libcryptsetup != 'false' and not fuzzer_build
libcurl = []
endif
conf.set10('HAVE_LIBCURL', have)
-m4_defines += have ? ['-DHAVE_LIBCURL'] : []
want_libidn = get_option('libidn')
want_libidn2 = get_option('libidn2')
libidn = []
endif
conf.set10('HAVE_LIBIDN', have)
-m4_defines += have ? ['-DHAVE_LIBIDN'] : []
if not have and want_libidn2 != 'false' and not fuzzer_build
# libidn is used for both libidn and libidn2 objects
libidn = dependency('libidn2',
have = false
endif
conf.set10('HAVE_LIBIDN2', have)
-m4_defines += have ? ['-DHAVE_LIBIDN2'] : []
want_libiptc = get_option('libiptc')
if want_libiptc != 'false' and not fuzzer_build
libiptc = []
endif
conf.set10('HAVE_LIBIPTC', have)
-m4_defines += have ? ['-DHAVE_LIBIPTC'] : []
want_qrencode = get_option('qrencode')
if want_qrencode != 'false' and not fuzzer_build
have = get_option(term)
name = 'ENABLE_' + term.underscorify().to_upper()
conf.set10(name, have)
- m4_defines += have ? ['-D' + name] : []
endforeach
-if get_option('timedated') or get_option('timesyncd')
- conf.set10('ENABLE_TIMEDATECTL', true)
- m4_defines += ['-DENABLE_TIMEDATECTL']
-else
- conf.set10('ENABLE_TIMEDATECTL', false)
-endif
+conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesyncd'))
want_tests = get_option('tests')
install_tests = get_option('install-tests')
output : 'config.h',
configuration : conf)
+meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
+
includes = include_directories('src/basic',
'src/shared',
'src/systemd',
install : true,
install_dir : rootlibdir)
+static_libsystemd = get_option('static-libsystemd')
+static_libsystemd_pic = static_libsystemd == 'true' or static_libsystemd == 'pic'
+
+install_libsystemd_static = static_library(
+ 'systemd',
+ libsystemd_sources,
+ journal_client_sources,
+ basic_sources,
+ basic_gcrypt_sources,
+ include_directories : includes,
+ build_by_default : static_libsystemd != 'false',
+ install : static_libsystemd != 'false',
+ install_dir : rootlibdir,
+ pic : static_libsystemd == 'true' or static_libsystemd == 'pic',
+ dependencies : [threads,
+ librt,
+ libxz,
+ liblz4,
+ libcap,
+ libblkid,
+ libmount,
+ libselinux,
+ libgcrypt],
+ c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC']))
+
############################################################
# binaries that have --help and are intended for use by humans,
endif
endforeach
-test_libsystemd_sym = executable(
+exe = executable(
'test-libsystemd-sym',
test_libsystemd_sym_c,
include_directories : includes,
link_with : [libsystemd],
install : install_tests,
install_dir : testsdir)
-test('test-libsystemd-sym',
- test_libsystemd_sym)
+test('test-libsystemd-sym', exe)
+
+exe = executable(
+ 'test-libsystemd-static-sym',
+ test_libsystemd_sym_c,
+ include_directories : includes,
+ link_with : [install_libsystemd_static],
+ dependencies : [threads], # threads is already included in dependencies on the library,
+ # but does not seem to get propagated. Add here as a work-around.
+ build_by_default : static_libsystemd_pic,
+ install : install_tests and static_libsystemd_pic,
+ install_dir : testsdir)
+if static_libsystemd_pic
+ test('test-libsystemd-static-sym', exe)
+endif
-test_libudev_sym = executable(
+exe = executable(
'test-libudev-sym',
test_libudev_sym_c,
include_directories : includes,
link_with : [libudev],
install : install_tests,
install_dir : testsdir)
-test('test-libudev-sym',
- test_libudev_sym)
+test('test-libudev-sym', exe)
+
+exe = executable(
+ 'test-libudev-static-sym',
+ test_libudev_sym_c,
+ include_directories : includes,
+ c_args : ['-Wno-deprecated-declarations'],
+ link_with : [install_libudev_static],
+ build_by_default : static_libudev_pic,
+ install : install_tests and static_libudev_pic,
+ install_dir : testsdir)
+if static_libudev_pic
+ test('test-libudev-static-sym', exe)
+endif
############################################################
'tags',
output : 'tags',
command : [env, 'etags', '-o', '@0@/TAGS'.format(meson.current_source_dir())] + all_files)
- custom_target(
+ run_target(
'ctags',
- output : 'ctags',
command : [env, 'ctags', '-o', '@0@/tags'.format(meson.current_source_dir())] + all_files)
endif
['gshadow'],
['debug hashmap'],
['debug mmap cache'],
+ ['valgrind', conf.get('VALGRIND') == 1],
]
if tuple.length() >= 2
message('\n '.join(status))
if rootprefixdir != rootprefix_default
- message('WARNING:\n' +
- ' Note that the installation prefix was changed to "@0@".\n'.format(rootprefixdir) +
- ' systemd used fixed names for unit file directories and other paths, so anything\n' +
- ' except the default ("@0@") is strongly discouraged.'.format(rootprefix_default))
+ warning('\n' +
+ 'Note that the installation prefix was changed to "@0@".\n'.format(rootprefixdir) +
+ 'systemd used fixed names for unit file directories and other paths, so anything\n' +
+ 'except the default ("@0@") is strongly discouraged.'.format(rootprefix_default))
endif
description : '''override the root prefix''')
option('link-udev-shared', type : 'boolean',
description : 'link systemd-udev and its helpers to libsystemd-shared.so')
+option('static-libsystemd', type : 'combo',
+ choices : ['false', 'true', 'pic', 'no-pic'],
+ description : '''install a static library for libsystemd''')
+option('static-libudev', type : 'combo',
+ choices : ['false', 'true', 'pic', 'no-pic'],
+ description : '''install a static library for libudev''')
option('sysvinit-path', type : 'string', value : '/etc/init.d',
description : 'the directory where the SysV init scripts are located')
description : 'path to debug shell binary')
option('debug-tty', type : 'string', value : '/dev/tty9',
description : 'specify the tty device for debug shell')
-option('debug', type : 'string',
- description : 'enable extra debugging (hashmap,mmap-cache)')
+option('debug', type : 'array', choices : ['hashmap', 'mmap-cache'], value : [],
+ description : 'enable extra debugging')
option('memory-accounting-default', type : 'boolean',
description : 'enable MemoryAccounting= by default')
+option('valgrind', type : 'boolean', value : false,
+ description : 'do extra operations to avoid valgrind warnings')
option('utmp', type : 'boolean',
description : 'support for utmp/wtmp log handling')
# SPDX-License-Identifier: LGPL-2.1+
-#
# Ukrainian translation for systemd.
# Copyright (C) 2014 systemd's COPYRIGHT HOLDER
# This file is distributed under the same license as the systemd package.
# Eugene Melnik <jeka7js@gmail.com>, 2014.
-# Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016.
+# Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016, 2018.
msgid ""
msgstr ""
"Project-Id-Version: systemd master\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-01-11 09:21+0200\n"
-"PO-Revision-Date: 2016-01-11 11:00+0300\n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
+"POT-Creation-Date: 2018-03-27 03:26+0000\n"
+"PO-Revision-Date: 2018-05-11 23:16+0300\n"
"Last-Translator: Daniel Korostil <ted.korostiled@gmail.com>\n"
"Language-Team: linux.org.ua\n"
"Language: uk\n"
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Virtaal 0.7.1\n"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1
+#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
msgstr "Надіслати пароль назад у систему"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2
+#: src/core/org.freedesktop.systemd1.policy.in:23
msgid ""
"Authentication is required to send the entered passphrase back to the system."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб надіслати введений пароль назад у систему."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб надіслати введений пароль назад у систему."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3
+#: src/core/org.freedesktop.systemd1.policy.in:33
msgid "Manage system services or other units"
-msgstr "Керувати системними службами й іншими одиницями"
+msgstr "Керувати системними службами й іншими одиницями systemd"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4
+#: src/core/org.freedesktop.systemd1.policy.in:34
msgid "Authentication is required to manage system services or other units."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, Ñ\89об кеÑ\80Ñ\83ваÑ\82и Ñ\81иÑ\81Ñ\82емними Ñ\81лÑ\83жбами й Ñ\96нÑ\88ими одиниÑ\86Ñ\8fми."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, Ñ\89об кеÑ\80Ñ\83ваÑ\82и Ñ\81иÑ\81Ñ\82емними Ñ\81лÑ\83жбами й Ñ\96нÑ\88ими одиниÑ\86Ñ\8fми systemd."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5
+#: src/core/org.freedesktop.systemd1.policy.in:43
msgid "Manage system service or unit files"
-msgstr "Керувати системними службами й файлами одиниць"
+msgstr "Керувати системними службами й одиницями systemd"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6
+#: src/core/org.freedesktop.systemd1.policy.in:44
msgid "Authentication is required to manage system service or unit files."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, Ñ\89об кеÑ\80Ñ\83ваÑ\82и Ñ\81иÑ\81Ñ\82емними Ñ\81лÑ\83жбами й Ñ\84айлами одиниÑ\86Ñ\8c."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, Ñ\89об кеÑ\80Ñ\83ваÑ\82и Ñ\81иÑ\81Ñ\82емними Ñ\81лÑ\83жбами й одиниÑ\86Ñ\8fми systemd."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7
+#: src/core/org.freedesktop.systemd1.policy.in:53
msgid "Set or unset system and service manager environment variables"
msgstr ""
"Встановити або забрати змінну середовища з керування службами і системою"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8
+#: src/core/org.freedesktop.systemd1.policy.in:54
msgid ""
"Authentication is required to set or unset system and service manager "
"environment variables."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб установити або забрати змінні середовища з "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб установити або забрати змінні середовища з "
"керування службами і системою."
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9
+#: src/core/org.freedesktop.systemd1.policy.in:63
msgid "Reload the systemd state"
msgstr "Перезапустити стан системи"
-#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10
+#: src/core/org.freedesktop.systemd1.policy.in:64
msgid "Authentication is required to reload the systemd state."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб перезапустити стан системи."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб перезапустити стан системи."
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1
+#: src/hostname/org.freedesktop.hostname1.policy:22
msgid "Set host name"
msgstr "Встановити назву вузла"
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2
+#: src/hostname/org.freedesktop.hostname1.policy:23
msgid "Authentication is required to set the local host name."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб встановити назву локального вузла."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб встановити назву локального вузла."
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3
+#: src/hostname/org.freedesktop.hostname1.policy:32
msgid "Set static host name"
msgstr "Встановити статичну назву вузла"
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4
+#: src/hostname/org.freedesktop.hostname1.policy:33
msgid ""
"Authentication is required to set the statically configured local host name, "
"as well as the pretty host name."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб вказати статично налаштовану назву локального "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вказати статично налаштовану назву локального "
"вузла, так само й форматовану."
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5
+#: src/hostname/org.freedesktop.hostname1.policy:43
msgid "Set machine information"
msgstr "Встановити інформацію про машину"
-#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6
+#: src/hostname/org.freedesktop.hostname1.policy:44
msgid "Authentication is required to set local machine information."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб вказати локальну інформацію про машини."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вказати локальну інформацію про машини."
-#: ../src/import/org.freedesktop.import1.policy.in.h:1
+#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
msgstr "Імпортувати образ контейнера або віртуальної машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:2
+#: src/import/org.freedesktop.import1.policy:23
msgid "Authentication is required to import a VM or container image"
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб імпортувати образ контейнера або віртуальної машини"
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб імпортувати образ контейнера або віртуальної машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:3
+#: src/import/org.freedesktop.import1.policy:32
msgid "Export a VM or container image"
msgstr "Експортувати образ контейнера або віртуальної машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:4
+#: src/import/org.freedesktop.import1.policy:33
msgid "Authentication is required to export a VM or container image"
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб експортувати образ контейнера або віртуальної "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб експортувати образ контейнера або віртуальної "
"машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:5
+#: src/import/org.freedesktop.import1.policy:42
msgid "Download a VM or container image"
msgstr "Звантажити образ контейнера або віртуальної машини"
-#: ../src/import/org.freedesktop.import1.policy.in.h:6
+#: src/import/org.freedesktop.import1.policy:43
msgid "Authentication is required to download a VM or container image"
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб звантажити образ контейнера або віртуальної машини"
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб звантажити образ контейнера або віртуальної машини"
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:1
+#: src/locale/org.freedesktop.locale1.policy:22
msgid "Set system locale"
msgstr "Вказати системну локаль"
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:2
+#: src/locale/org.freedesktop.locale1.policy:23
msgid "Authentication is required to set the system locale."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб встановити системну локаль."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб встановити системну локаль."
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:3
+#: src/locale/org.freedesktop.locale1.policy:33
msgid "Set system keyboard settings"
msgstr "Вказати налаштування системної клавіатури"
-#: ../src/locale/org.freedesktop.locale1.policy.in.h:4
+#: src/locale/org.freedesktop.locale1.policy:34
msgid "Authentication is required to set the system keyboard settings."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб вказати налаштування системної клавіатури."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вказати налаштування системної клавіатури."
-#: ../src/login/org.freedesktop.login1.policy.in.h:1
+#: src/login/org.freedesktop.login1.policy:22
msgid "Allow applications to inhibit system shutdown"
msgstr "Дозволити програмам перешкоджати вимкненню системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:2
+#: src/login/org.freedesktop.login1.policy:23
msgid ""
"Authentication is required for an application to inhibit system shutdown."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити програмам перешкоджати вимкненню системи."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити програмам перешкоджати вимкненню системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:3
+#: src/login/org.freedesktop.login1.policy:33
msgid "Allow applications to delay system shutdown"
msgstr "Дозволити програмам затримувати вимкнення системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:4
+#: src/login/org.freedesktop.login1.policy:34
msgid "Authentication is required for an application to delay system shutdown."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити програмам затримувати вимкнення системи."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити програмам затримувати вимкнення системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:5
+#: src/login/org.freedesktop.login1.policy:44
msgid "Allow applications to inhibit system sleep"
msgstr "Дозволити програмам перешкоджати засинанню системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:6
+#: src/login/org.freedesktop.login1.policy:45
msgid "Authentication is required for an application to inhibit system sleep."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити програмам перешкоджати засинанню системи."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити програмам перешкоджати засинанню системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:7
+#: src/login/org.freedesktop.login1.policy:55
msgid "Allow applications to delay system sleep"
msgstr "Дозволити програмами затримувати засинання системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:8
+#: src/login/org.freedesktop.login1.policy:56
msgid "Authentication is required for an application to delay system sleep."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити програмам затримувати засинання системи."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити програмам затримувати засинання системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:9
+#: src/login/org.freedesktop.login1.policy:65
msgid "Allow applications to inhibit automatic system suspend"
msgstr "Дозволити програмам перешкоджати автоматичному призупиненню системи"
-#: ../src/login/org.freedesktop.login1.policy.in.h:10
+#: src/login/org.freedesktop.login1.policy:66
msgid ""
"Authentication is required for an application to inhibit automatic system "
"suspend."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити програмам перешкоджати автоматичному "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити програмам перешкоджати автоматичному "
"призупиненню системи."
-#: ../src/login/org.freedesktop.login1.policy.in.h:11
+#: src/login/org.freedesktop.login1.policy:75
msgid "Allow applications to inhibit system handling of the power key"
msgstr "Дозволити програмам перешкоджати обробленню системою клавіші живлення"
-#: ../src/login/org.freedesktop.login1.policy.in.h:12
+#: src/login/org.freedesktop.login1.policy:76
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the power key."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити програмам перешкоджати обробленню "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити програмам перешкоджати обробленню "
"системою клавіші живлення."
-#: ../src/login/org.freedesktop.login1.policy.in.h:13
+#: src/login/org.freedesktop.login1.policy:86
msgid "Allow applications to inhibit system handling of the suspend key"
msgstr ""
"Дозволити програмам перешкоджати обробленню системою клавіші призупинення"
-#: ../src/login/org.freedesktop.login1.policy.in.h:14
+#: src/login/org.freedesktop.login1.policy:87
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the suspend key."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити програмам перешкоджати обробленню "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити програмам перешкоджати обробленню "
"системою клавіші призупинення."
-#: ../src/login/org.freedesktop.login1.policy.in.h:15
+#: src/login/org.freedesktop.login1.policy:97
msgid "Allow applications to inhibit system handling of the hibernate key"
msgstr ""
"Дозволити програмам перешкоджати обробленню системою клавіші присипання"
-#: ../src/login/org.freedesktop.login1.policy.in.h:16
+#: src/login/org.freedesktop.login1.policy:98
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the hibernate key."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити програмам перешкоджати обробленню "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити програмам перешкоджати обробленню "
"системою клавіші присипання."
-#: ../src/login/org.freedesktop.login1.policy.in.h:17
+#: src/login/org.freedesktop.login1.policy:107
msgid "Allow applications to inhibit system handling of the lid switch"
msgstr ""
"Дозволити програмам перешкоджати обробленню системою клавіші перемикання "
"кришки"
-#: ../src/login/org.freedesktop.login1.policy.in.h:18
+#: src/login/org.freedesktop.login1.policy:108
msgid ""
"Authentication is required for an application to inhibit system handling of "
"the lid switch."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити програмам перешкоджати обробленню "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити програмам перешкоджати обробленню "
"системою клавіші перемикання кришки."
-#: ../src/login/org.freedesktop.login1.policy.in.h:19
+#: src/login/org.freedesktop.login1.policy:117
+#| msgid "Allow non-logged-in users to run programs"
+msgid "Allow non-logged-in user to run programs"
+msgstr "Дозволити незареєстрованим користувачам запускати програми"
+
+#: src/login/org.freedesktop.login1.policy:118
+#| msgid "Authentication is required to run programs as a non-logged-in user."
+msgid "Explicit request is required to run programs as a non-logged-in user."
+msgstr ""
+"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам запускати "
+"програми."
+
+#: src/login/org.freedesktop.login1.policy:127
msgid "Allow non-logged-in users to run programs"
msgstr "Дозволити незареєстрованим користувачам запускати програми"
-#: ../src/login/org.freedesktop.login1.policy.in.h:20
+#: src/login/org.freedesktop.login1.policy:128
msgid "Authentication is required to run programs as a non-logged-in user."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб дозволити незареєстрованим користувачам запускати "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити незареєстрованим користувачам запускати "
"програми."
-#: ../src/login/org.freedesktop.login1.policy.in.h:21
+#: src/login/org.freedesktop.login1.policy:137
msgid "Allow attaching devices to seats"
msgstr "Дозволити під'єднання пристроїв до місць"
-#: ../src/login/org.freedesktop.login1.policy.in.h:22
+#: src/login/org.freedesktop.login1.policy:138
msgid "Authentication is required for attaching a device to a seat."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб під'єднувати пристрої до місць."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб під'єднувати пристрої до місць."
-#: ../src/login/org.freedesktop.login1.policy.in.h:23
+#: src/login/org.freedesktop.login1.policy:148
msgid "Flush device to seat attachments"
msgstr "Очисний пристрій для під'єднань до місця"
-#: ../src/login/org.freedesktop.login1.policy.in.h:24
+#: src/login/org.freedesktop.login1.policy:149
msgid ""
"Authentication is required for resetting how devices are attached to seats."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб перезапустити спосіб під'єднання до місць."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб перезапустити спосіб під'єднання до місць."
-#: ../src/login/org.freedesktop.login1.policy.in.h:25
+#: src/login/org.freedesktop.login1.policy:158
msgid "Power off the system"
msgstr "Вимкнути систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:26
+#: src/login/org.freedesktop.login1.policy:159
msgid "Authentication is required for powering off the system."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб вимкнути систему."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вимкнути систему."
-#: ../src/login/org.freedesktop.login1.policy.in.h:27
+#: src/login/org.freedesktop.login1.policy:169
msgid "Power off the system while other users are logged in"
msgstr "Вимкнути систему, коли інші користувачі ще в ній"
-#: ../src/login/org.freedesktop.login1.policy.in.h:28
+#: src/login/org.freedesktop.login1.policy:170
msgid ""
"Authentication is required for powering off the system while other users are "
"logged in."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб вимкнути систему, коли інші користувачі в ній."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вимкнути систему, коли інші користувачі в ній."
-#: ../src/login/org.freedesktop.login1.policy.in.h:29
+#: src/login/org.freedesktop.login1.policy:180
msgid "Power off the system while an application asked to inhibit it"
msgstr "Вимкнути систему, коли програми намагаються перешкодити цьому"
-#: ../src/login/org.freedesktop.login1.policy.in.h:30
+#: src/login/org.freedesktop.login1.policy:181
msgid ""
"Authentication is required for powering off the system while an application "
"asked to inhibit it."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб вимкнути систему, коли програми намагаються "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вимкнути систему, коли програми намагаються "
"перешкодити цьому."
-#: ../src/login/org.freedesktop.login1.policy.in.h:31
+#: src/login/org.freedesktop.login1.policy:191
msgid "Reboot the system"
msgstr "Перезавантажити систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:32
+#: src/login/org.freedesktop.login1.policy:192
msgid "Authentication is required for rebooting the system."
msgstr "Для перезавантаження системи необхідна ідентифікація."
-#: ../src/login/org.freedesktop.login1.policy.in.h:33
+#: src/login/org.freedesktop.login1.policy:202
msgid "Reboot the system while other users are logged in"
msgstr "Перезавантажити, якщо інші користувачі в системі"
-#: ../src/login/org.freedesktop.login1.policy.in.h:34
+#: src/login/org.freedesktop.login1.policy:203
msgid ""
"Authentication is required for rebooting the system while other users are "
"logged in."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб перезапустити систему, коли інші користувачі в ній."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб перезапустити систему, коли інші користувачі в ній."
-#: ../src/login/org.freedesktop.login1.policy.in.h:35
+#: src/login/org.freedesktop.login1.policy:213
msgid "Reboot the system while an application asked to inhibit it"
msgstr "Перезапустити систему, коли програми намагаються перешкодити цьому"
-#: ../src/login/org.freedesktop.login1.policy.in.h:36
+#: src/login/org.freedesktop.login1.policy:214
msgid ""
"Authentication is required for rebooting the system while an application "
"asked to inhibit it."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб перезапустити систему, коли програми намагаються "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб перезапустити систему, коли програми намагаються "
"перешкодити цьому."
-#: ../src/login/org.freedesktop.login1.policy.in.h:37
+#: src/login/org.freedesktop.login1.policy:224
+#| msgid "Hibernate the system"
+msgid "Halt the system"
+msgstr "Зупинити систему"
+
+#: src/login/org.freedesktop.login1.policy:225
+#| msgid "Authentication is required for hibernating the system."
+msgid "Authentication is required for halting the system."
+msgstr "Потрібна автентифікація, щоб зупинити систему."
+
+#: src/login/org.freedesktop.login1.policy:235
+#| msgid "Hibernate the system while other users are logged in"
+msgid "Halt the system while other users are logged in"
+msgstr "Зупинити систему, коли інші користувачі в ній"
+
+#: src/login/org.freedesktop.login1.policy:236
+#| msgid ""
+#| "Authentication is required for hibernating the system while other users "
+#| "are logged in."
+msgid ""
+"Authentication is required for halting the system while other users are "
+"logged in."
+msgstr ""
+"Потрібна автентифікація, щоб зупинити систему, коли інші користувачі в ній."
+
+#: src/login/org.freedesktop.login1.policy:246
+#| msgid "Hibernate the system while an application asked to inhibit it"
+msgid "Halt the system while an application asked to inhibit it"
+msgstr "Зупинити систему, коли програми намагаються перешкодити цьому"
+
+#: src/login/org.freedesktop.login1.policy:247
+#| msgid ""
+#| "Authentication is required for hibernating the system while an "
+#| "application asked to inhibit it."
+msgid ""
+"Authentication is required for halting the system while an application asked "
+"to inhibit it."
+msgstr ""
+"Потрібна автентифікація, щоб зупинити систему, коли програми намагаються "
+"перешкодити цьому."
+
+#: src/login/org.freedesktop.login1.policy:257
msgid "Suspend the system"
msgstr "Призупинити систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:38
+#: src/login/org.freedesktop.login1.policy:258
msgid "Authentication is required for suspending the system."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб призупинити систему."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб призупинити систему."
-#: ../src/login/org.freedesktop.login1.policy.in.h:39
+#: src/login/org.freedesktop.login1.policy:267
msgid "Suspend the system while other users are logged in"
msgstr "Призупинити систему, коли інші користувачі в ній"
-#: ../src/login/org.freedesktop.login1.policy.in.h:40
+#: src/login/org.freedesktop.login1.policy:268
msgid ""
"Authentication is required for suspending the system while other users are "
"logged in."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб призупинити систему, коли інші користувачі в ній."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб призупинити систему, коли інші користувачі в ній."
-#: ../src/login/org.freedesktop.login1.policy.in.h:41
+#: src/login/org.freedesktop.login1.policy:278
msgid "Suspend the system while an application asked to inhibit it"
msgstr "Призупинити систему, коли програми намагаються перешкодити цьому"
-#: ../src/login/org.freedesktop.login1.policy.in.h:42
+#: src/login/org.freedesktop.login1.policy:279
msgid ""
"Authentication is required for suspending the system while an application "
"asked to inhibit it."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб призупинити систему, коли програми намагаються "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб призупинити систему, коли програми намагаються "
"перешкодити цьому."
-#: ../src/login/org.freedesktop.login1.policy.in.h:43
+#: src/login/org.freedesktop.login1.policy:289
msgid "Hibernate the system"
msgstr "Приспати систему"
-#: ../src/login/org.freedesktop.login1.policy.in.h:44
+#: src/login/org.freedesktop.login1.policy:290
msgid "Authentication is required for hibernating the system."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб приспати систему."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб приспати систему."
-#: ../src/login/org.freedesktop.login1.policy.in.h:45
+#: src/login/org.freedesktop.login1.policy:299
msgid "Hibernate the system while other users are logged in"
msgstr "Приспати систему, коли інші користувачі в ній"
-#: ../src/login/org.freedesktop.login1.policy.in.h:46
+#: src/login/org.freedesktop.login1.policy:300
msgid ""
"Authentication is required for hibernating the system while other users are "
"logged in."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб присипання систему, коли інші користувачі в ній."
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб присипання систему, коли інші користувачі в ній."
-#: ../src/login/org.freedesktop.login1.policy.in.h:47
+#: src/login/org.freedesktop.login1.policy:310
msgid "Hibernate the system while an application asked to inhibit it"
msgstr "Приспати систему, коли програми намагаються перешкодити цьому"
-#: ../src/login/org.freedesktop.login1.policy.in.h:48
+#: src/login/org.freedesktop.login1.policy:311
msgid ""
"Authentication is required for hibernating the system while an application "
"asked to inhibit it."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб приспати систему, коли програми намагаються "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб приспати систему, коли програми намагаються "
"перешкодити цьому."
-#: ../src/login/org.freedesktop.login1.policy.in.h:49
+#: src/login/org.freedesktop.login1.policy:321
msgid "Manage active sessions, users and seats"
msgstr "Керувати сеансами, користувачами і робочими місцями"
-#: ../src/login/org.freedesktop.login1.policy.in.h:50
+#: src/login/org.freedesktop.login1.policy:322
msgid ""
"Authentication is required for managing active sessions, users and seats."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб керувати сеансами, користувачами і робочими "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб керувати сеансами, користувачами і робочими "
"місцями."
-#: ../src/login/org.freedesktop.login1.policy.in.h:51
+#: src/login/org.freedesktop.login1.policy:331
msgid "Lock or unlock active sessions"
msgstr "Заблокувати або розблокувати сеанси"
-#: ../src/login/org.freedesktop.login1.policy.in.h:52
+#: src/login/org.freedesktop.login1.policy:332
msgid "Authentication is required to lock or unlock active sessions."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб заблокувати або розблокувати сеанси."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб заблокувати або розблокувати сеанси."
-#: ../src/login/org.freedesktop.login1.policy.in.h:53
+#: src/login/org.freedesktop.login1.policy:341
msgid "Allow indication to the firmware to boot to setup interface"
msgstr "Дозволити мікрокоду визначати, чи завантажувати інтерфейс встановлення"
-#: ../src/login/org.freedesktop.login1.policy.in.h:54
+#: src/login/org.freedesktop.login1.policy:342
msgid ""
"Authentication is required to indicate to the firmware to boot to setup "
"interface."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб дозволити мікрокоду визначати, чи завантажувати "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб дозволити мікрокоду визначати, чи завантажувати "
"інтерфейс встановлення."
-#: ../src/login/org.freedesktop.login1.policy.in.h:55
+#: src/login/org.freedesktop.login1.policy:351
msgid "Set a wall message"
msgstr "Вказати повідомлення на стіні"
-#: ../src/login/org.freedesktop.login1.policy.in.h:56
+#: src/login/org.freedesktop.login1.policy:352
msgid "Authentication is required to set a wall message"
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб вказати повідомлення на стіні"
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вказати повідомлення на стіні"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:1
+#: src/machine/org.freedesktop.machine1.policy:22
msgid "Log into a local container"
msgstr "Увійти в локальний контейнер"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:2
+#: src/machine/org.freedesktop.machine1.policy:23
msgid "Authentication is required to log into a local container."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб увійти в локальний контейнер."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб увійти в локальний контейнер."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:3
+#: src/machine/org.freedesktop.machine1.policy:32
msgid "Log into the local host"
msgstr "Увійти в локальний вузол"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:4
+#: src/machine/org.freedesktop.machine1.policy:33
msgid "Authentication is required to log into the local host."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб увійти в локальний вузол."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб увійти в локальний вузол."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:5
+#: src/machine/org.freedesktop.machine1.policy:42
msgid "Acquire a shell in a local container"
msgstr "Перейняти оболонку в локальному контейнері"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:6
+#: src/machine/org.freedesktop.machine1.policy:43
msgid "Authentication is required to acquire a shell in a local container."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб перейняти оболонку в локальному контейнері."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб перейняти оболонку в локальному контейнері."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:7
+#: src/machine/org.freedesktop.machine1.policy:53
msgid "Acquire a shell on the local host"
msgstr "Перейняти оболонку на локальному вузлі"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:8
+#: src/machine/org.freedesktop.machine1.policy:54
msgid "Authentication is required to acquire a shell on the local host."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб перейняти оболонку на локальному вузлі."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб перейняти оболонку на локальному вузлі."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:9
+#: src/machine/org.freedesktop.machine1.policy:64
msgid "Acquire a pseudo TTY in a local container"
msgstr "Перейняти псевдо TTY в локальному контейнері"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:10
+#: src/machine/org.freedesktop.machine1.policy:65
msgid ""
"Authentication is required to acquire a pseudo TTY in a local container."
-msgstr "Засвідчення потрібне, щоб перейняти псевдо TTY в локальному контейнері."
+msgstr ""
+"Потрібна автентифікація, щоб перейняти псевдо TTY в локальному контейнері."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:11
+#: src/machine/org.freedesktop.machine1.policy:74
msgid "Acquire a pseudo TTY on the local host"
msgstr "Перейняти псевдо TTY на локальному вузлі"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:12
+#: src/machine/org.freedesktop.machine1.policy:75
msgid "Authentication is required to acquire a pseudo TTY on the local host."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб перейняти псевдо TTY на локальному вузлі."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб перейняти псевдо TTY на локальному вузлі."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:13
+#: src/machine/org.freedesktop.machine1.policy:84
msgid "Manage local virtual machines and containers"
msgstr "Керувати локальними віртуальними машинами і контейнерами"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:14
+#: src/machine/org.freedesktop.machine1.policy:85
msgid ""
"Authentication is required to manage local virtual machines and containers."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб керувати локальними віртуальними машинами і "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб керувати локальними віртуальними машинами і "
"контейнерами."
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:15
+#: src/machine/org.freedesktop.machine1.policy:95
msgid "Manage local virtual machine and container images"
msgstr "Керувати локальними образами віртуальних машин і контейнерів"
-#: ../src/machine/org.freedesktop.machine1.policy.in.h:16
+#: src/machine/org.freedesktop.machine1.policy:96
msgid ""
"Authentication is required to manage local virtual machine and container "
"images."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб керувати локальними образами віртуальних машин і "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб керувати локальними образами віртуальних машин і "
"контейнерів."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1
+#: src/resolve/org.freedesktop.resolve1.policy:22
+msgid "Register a DNS-SD service"
+msgstr "Зареєструвати службу DNS-SD"
+
+#: src/resolve/org.freedesktop.resolve1.policy:23
+#| msgid "Authentication is required to set a wall message"
+msgid "Authentication is required to register a DNS-SD service"
+msgstr "Потрібна автентифікація, щоб зареєструвати службу DNS-SD"
+
+#: src/resolve/org.freedesktop.resolve1.policy:33
+msgid "Unregister a DNS-SD service"
+msgstr "Зняти з реєстрації службу DNS-SD"
+
+#: src/resolve/org.freedesktop.resolve1.policy:34
+#| msgid "Authentication is required to set a wall message"
+msgid "Authentication is required to unregister a DNS-SD service"
+msgstr "Потрібна автентифікація, щоб зняти з реєстрації службу DNS-SD"
+
+#: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time"
msgstr "Вказати системний час"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2
+#: src/timedate/org.freedesktop.timedate1.policy:23
msgid "Authentication is required to set the system time."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб вказати системний час."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вказати системний час."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3
+#: src/timedate/org.freedesktop.timedate1.policy:33
msgid "Set system timezone"
msgstr "Вказати системний часовий пояс"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4
+#: src/timedate/org.freedesktop.timedate1.policy:34
msgid "Authentication is required to set the system timezone."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб вказати системний часовий пояс."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вказати системний часовий пояс."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5
+#: src/timedate/org.freedesktop.timedate1.policy:43
msgid "Set RTC to local timezone or UTC"
msgstr "Вкажіть RTC для локального часового поясу або UTC"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6
+#: src/timedate/org.freedesktop.timedate1.policy:44
msgid ""
"Authentication is required to control whether the RTC stores the local or "
"UTC time."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб контролювати, чи RTC зберігає час, чи UTC."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб контролювати, чи RTC зберігає час, чи UTC."
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7
+#: src/timedate/org.freedesktop.timedate1.policy:54
msgid "Turn network time synchronization on or off"
-msgstr "Увімкнути або вимкнути синхронізування через мережу"
+msgstr "УвÑ\96мкнÑ\83Ñ\82и або вимкнÑ\83Ñ\82и Ñ\81инÑ\85Ñ\80онÑ\96зÑ\83ваннÑ\8f Ñ\87аÑ\81Ñ\83 Ñ\87еÑ\80ез меÑ\80ежÑ\83"
-#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8
+#: src/timedate/org.freedesktop.timedate1.policy:55
msgid ""
"Authentication is required to control whether network time synchronization "
"shall be enabled."
msgstr ""
-"Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб контролювати, чи синхронізування часу через мережу "
+"Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб контролювати, чи синхронізування часу через мережу "
"запущено."
-#: ../src/core/dbus-unit.c:449
+#: src/core/dbus-unit.c:496
msgid "Authentication is required to start '$(unit)'."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб запустити «$(unit)»."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб запустити «$(unit)»."
-#: ../src/core/dbus-unit.c:450
+#: src/core/dbus-unit.c:497
msgid "Authentication is required to stop '$(unit)'."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб зупинити «$(unit)»."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб зупинити «$(unit)»."
-#: ../src/core/dbus-unit.c:451
+#: src/core/dbus-unit.c:498
msgid "Authentication is required to reload '$(unit)'."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб перезавантажити «$(unit)»."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб перезавантажити «$(unit)»."
-#: ../src/core/dbus-unit.c:452 ../src/core/dbus-unit.c:453
+#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500
msgid "Authentication is required to restart '$(unit)'."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб перезапустити «$(unit)»."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб перезапустити «$(unit)»."
-#: ../src/core/dbus-unit.c:556
+#: src/core/dbus-unit.c:607
msgid "Authentication is required to kill '$(unit)'."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб вбити «$(unit)»."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вбити «$(unit)»."
-#: ../src/core/dbus-unit.c:586
+#: src/core/dbus-unit.c:638
msgid "Authentication is required to reset the \"failed\" state of '$(unit)'."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бне, щоб скинути «пошкоджений» стан з «$(unit)»."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб скинути «пошкоджений» стан з «$(unit)»."
-#: ../src/core/dbus-unit.c:618
+#: src/core/dbus-unit.c:671
msgid "Authentication is required to set properties on '$(unit)'."
-msgstr "Ð\97аÑ\81вÑ\96дÑ\87еннÑ\8f поÑ\82Ñ\80Ñ\96бно, щоб вказати властивості на «$(unit)»."
+msgstr "Ð\9fоÑ\82Ñ\80Ñ\96бна авÑ\82енÑ\82иÑ\84Ñ\96каÑ\86Ñ\96Ñ\8f, щоб вказати властивості на «$(unit)»."
# by-label/by-uuid links (filesystem metadata)
ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}"
-ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}"
+ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}"
# by-id (World Wide Name)
ENV{DEVTYPE}=="disk", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}"
__get_machines() {
local a b
- machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; };
+ machinectl list --no-legend --no-pager 2>/dev/null |
+ { while read a b; do echo " $a"; done; };
}
__get_busnames() {
local mode=$1
local a b
- busctl $mode list --no-legend --no-pager | { while read a b; do echo " $a"; done; };
+ busctl $mode list --no-legend --no-pager 2>/dev/null |
+ { while read a b; do echo " $a"; done; };
}
__get_objects() {
local mode=$1
local busname=$2
local a b
- busctl $mode tree --list --no-legend --no-pager $busname | { while read a b; do echo " $a"; done; };
+ busctl $mode tree --list --no-legend --no-pager $busname 2>/dev/null |
+ { while read a b; do echo " $a"; done; };
}
__get_interfaces() {
local busname=$2
local path=$3
local a b c
- busctl $mode introspect --list --no-legend --no-pager $busname $path | { while read a b c; do [[ "$b" == "interface" ]] && echo " $a"; done; };
+ busctl $mode introspect --list --no-legend --no-pager $busname $path 2>/dev/null |
+ { while read a b c; do [[ "$b" == "interface" ]] && echo " $a"; done; };
}
__get_members() {
local type=$5
local flags=$6
local a b c d e
- busctl $mode introspect --list --no-legend --no-pager $busname $path $interface | sed -e 's/^\.//' | { while read a b c d e; do [[ "$b" == "$type" && ( -z $flags || "$e" == "$flags" ) ]] && echo " $a"; done; };
+ busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null |
+ sed -e 's/^\.//' |
+ { while read a b c d e; do [[ "$b" == "$type" && ( -z $flags || "$e" == "$flags" ) ]] && echo " $a"; done; };
}
__get_signature() {
local interface=$4
local member=$5
local a b c d
- busctl $mode introspect --list --no-legend --no-pager $busname $path $interface | sed -e 's/^\.//' | { while read a b c d; do [[ "$a" == "$member" && "$c" != '-' ]] && echo " \"$c\""; done; };
+ busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null |
+ sed -e 's/^\.//' | { while read a b c d; do [[ "$a" == "$member" && "$c" != '-' ]] && echo " \"$c\""; done; };
}
_busctl() {
local -A OPTS=(
[STANDALONE]='-h --help --version --system --user --global --order --require --no-pager
--man=no --generators=yes'
- [ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern'
+ [ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern --root'
)
local -A VERBS=(
[VERIFY]='verify'
[SECCOMP_FILTER]='syscall-filter'
[SERVICE_WATCHDOGS]='service-watchdogs'
+ [CAT_CONFIG]='cat-config'
)
+ local CONFIGS='systemd/bootchart.conf systemd/coredump.conf systemd/journald.conf
+ systemd/journal-remote.conf systemd/journal-upload.conf systemd/logind.conf
+ systemd/resolved.conf systemd/networkd.conf systemd/resolved.conf
+ systemd/sleep.conf systemd/system.conf systemd/timedated.conf
+ systemd/timesyncd.conf systemd/user.conf udev/udev.conf'
+
_init_completion || return
for ((i=0; i < COMP_CWORD; i++)); do
elif __contains_word "$verb" ${VERBS[STANDALONE]}; then
if [[ $cur = -* ]]; then
- comps='--help --version --system --user --global'
+ comps='--help --version --system --user --global --no-pager'
fi
elif __contains_word "$verb" ${VERBS[CRITICAL_CHAIN]}; then
if [[ $cur = -* ]]; then
- comps='--help --version --system --user --fuzz'
+ comps='--help --version --system --user --fuzz --no-pager'
fi
elif __contains_word "$verb" ${VERBS[DOT]}; then
elif __contains_word "$verb" ${VERBS[SECCOMP_FILTER]}; then
if [[ $cur = -* ]]; then
- comps='--help --version'
+ comps='--help --version --no-pager'
fi
elif __contains_word "$verb" ${VERBS[VERIFY]}; then
comps='on off'
fi
+ elif __contains_word "$verb" ${VERBS[CAT_CONFIG]}; then
+ if [[ $cur = -* ]]; then
+ comps='--help --version --root --no-pager'
+ elif [[ -z $cur ]]; then
+ comps="$CONFIGS"
+ compopt -o filenames
+ else
+ comps="$CONFIGS $( compgen -A file -- "$cur" )"
+ compopt -o filenames
+ fi
fi
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
local i verb comps
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
local OPTS='-h --help --version --adjust-system-clock --no-pager
- --no-ask-password -H --host -M --machine'
+ --no-ask-password -H --host -M --machine --monitor
+ -p --property -a --all --value'
if __contains_word "$prev" $OPTS; then
case $prev in
local -A VERBS=(
[BOOLEAN]='set-local-rtc set-ntp'
- [STANDALONE]='status list-timezones'
+ [STANDALONE]='status list-timezones timesync-status show-timesync'
[TIMEZONES]='set-timezone'
[TIME]='set-time'
)
#include <stdlib.h>
#include "alloc-util.h"
+#include "all-units.h"
#include "analyze-verify.h"
#include "bus-error.h"
#include "bus-util.h"
#include "bus-unit-util.h"
#include "bus-util.h"
#include "calendarspec.h"
+#include "def.h"
+#include "conf-files.h"
+#include "copy.h"
+#include "fd-util.h"
#include "glob-util.h"
#include "hashmap.h"
#include "locale-util.h"
#include "log.h"
#include "pager.h"
#include "parse-util.h"
+#include "path-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
static bool arg_man = true;
static bool arg_generators = false;
+static const char *arg_root = NULL;
struct boot_times {
usec_t firmware_time;
char *architecture;
};
-static int acquire_systemd_bus(sd_bus **bus) {
- bool user = arg_scope != UNIT_FILE_SYSTEM;
-
- return bus_connect_transport_systemd(arg_transport, arg_host, user, bus);
-}
-
-static int acquire_full_bus(bool *use_full_bus, sd_bus **bus) {
+static int acquire_bus(sd_bus **bus, bool *use_full_bus) {
bool user = arg_scope != UNIT_FILE_SYSTEM;
+ int r;
- if (*use_full_bus) {
- if (bus_connect_transport(arg_transport, arg_host, user, bus) == 0)
- return 0;
+ if (use_full_bus && *use_full_bus) {
+ r = bus_connect_transport(arg_transport, arg_host, user, bus);
+ if (IN_SET(r, 0, -EHOSTDOWN))
+ return r;
*use_full_bus = false;
}
- return acquire_systemd_bus(bus);
+ return bus_connect_transport_systemd(arg_transport, arg_host, user, bus);
}
static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
_cleanup_free_ char *pretty_times = NULL;
struct unit_times *u;
- r = acquire_full_bus(&use_full_bus, &bus);
+ r = acquire_bus(&bus, &use_full_bus);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
Hashmap *h;
int n, r;
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
unsigned i;
int n, r;
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
_cleanup_free_ char *buf = NULL;
int r;
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
int r;
UnitInfo u;
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
return 0;
}
+static int dump_fallback(sd_bus *bus) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ const char *text = NULL;
+ int r;
+
+ assert(bus);
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "Dump",
+ &error,
+ &reply,
+ NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to issue method call Dump: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_read(reply, "s", &text);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ fputs(text, stdout);
+ return 0;
+}
+
static int dump(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- const char *text = NULL;
+ int fd = -1;
int r;
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
(void) pager_open(arg_no_pager, false);
+ if (!sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD))
+ return dump_fallback(bus);
+
r = sd_bus_call_method(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
- "Dump",
+ "DumpByFileDescriptor",
&error,
&reply,
NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r));
+ if (r < 0) {
+ /* fall back to Dump if DumpByFileDescriptor is not supported */
+ if (!IN_SET(r, -EACCES, -EBADR))
+ return log_error_errno(r, "Failed to issue method call DumpByFileDescriptor: %s", bus_error_message(&error, r));
- r = sd_bus_message_read(reply, "s", &text);
+ return dump_fallback(bus);
+ }
+
+ r = sd_bus_message_read(reply, "h", &fd);
if (r < 0)
return bus_log_parse_error(r);
- fputs(text, stdout);
+ fflush(stdout);
+ return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0);
+}
+
+static int cat_config(int argc, char *argv[], void *userdata) {
+ char **arg;
+ int r;
+
+ (void) pager_open(arg_no_pager, false);
+
+ STRV_FOREACH(arg, argv + 1) {
+ const char *t = NULL;
+
+ if (arg != argv + 1)
+ print_separator();
+
+ if (path_is_absolute(*arg)) {
+ const char *dir;
+
+ NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) {
+ t = path_startswith(*arg, dir);
+ if (t)
+ break;
+ }
+
+ if (!t) {
+ log_error("Path %s does not start with any known prefix.", *arg);
+ return -EINVAL;
+ }
+ } else
+ t = *arg;
+
+ r = conf_files_cat(arg_root, t);
+ if (r < 0)
+ return r;
+ }
+
return 0;
}
assert(argc == 2);
assert(argv);
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
_cleanup_free_ char *level = NULL;
int r;
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
assert(argc == 2);
assert(argv);
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
_cleanup_free_ char *target = NULL;
int r;
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
assert(IN_SET(argc, 1, 2));
assert(argv);
- r = acquire_systemd_bus(&bus);
+ r = acquire_bus(&bus, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create bus connection: %m");
" log-level [LEVEL] Get/set logging threshold for manager\n"
" log-target [TARGET] Get/set logging target for manager\n"
" dump Output state serialization of service manager\n"
+ " cat-config Show configuration file and drop-ins\n"
" unit-paths List load directories for units\n"
" syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
" verify FILE... Check unit files for correctness\n"
ARG_VERSION = 0x100,
ARG_ORDER,
ARG_REQUIRE,
+ ARG_ROOT,
ARG_SYSTEM,
ARG_USER,
ARG_GLOBAL,
{ "version", no_argument, NULL, ARG_VERSION },
{ "order", no_argument, NULL, ARG_ORDER },
{ "require", no_argument, NULL, ARG_REQUIRE },
+ { "root", required_argument, NULL, ARG_ROOT },
{ "system", no_argument, NULL, ARG_SYSTEM },
{ "user", no_argument, NULL, ARG_USER },
{ "global", no_argument, NULL, ARG_GLOBAL },
case ARG_VERSION:
return version();
+ case ARG_ROOT:
+ arg_root = optarg;
+ break;
+
case ARG_SYSTEM:
arg_scope = UNIT_FILE_SYSTEM;
break;
return -EINVAL;
}
+ if (arg_root && !streq_ptr(argv[optind], "cat-config")) {
+ log_error("Option --root is only supported for cat-config right now.");
+ return -EINVAL;
+ }
+
return 1; /* work to do */
}
{ "set-log-target", 2, 2, 0, set_log_target },
{ "get-log-target", VERB_ANY, 1, 0, get_log_target },
{ "dump", VERB_ANY, 1, 0, dump },
+ { "cat-config", 2, VERB_ANY, 0, cat_config },
{ "unit-paths", 1, 1, 0, dump_unit_paths },
{ "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters },
{ "verify", 2, VERB_ANY, 0, do_verify },
// Other compilers
-#else // defined(_MSC_VER)
+#else // defined(_MSC_VER)
#define BIG_CONSTANT(x) (x##LLU)
// Other compilers
-#else // defined(_MSC_VER)
+#else // defined(_MSC_VER)
#include <stdint.h>
int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
const char *utc;
- CalendarSpec *c;
+ _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
int r;
assert(p);
const char *last_space;
last_space = strrchr(p, ' ');
- if (last_space != NULL && timezone_is_valid(last_space + 1)) {
+ if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG)) {
c->timezone = strdup(last_space + 1);
- if (!c->timezone) {
- r = -ENOMEM;
- goto fail;
- }
+ if (!c->timezone)
+ return -ENOMEM;
p = strndupa(p, last_space - p);
}
}
}
- if (isempty(p)) {
- r = -EINVAL;
- goto fail;
- }
+ if (isempty(p))
+ return -EINVAL;
if (strcaseeq(p, "minutely")) {
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "hourly")) {
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "daily")) {
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "monthly")) {
r = const_chain(1, &c->day);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "annually") ||
strcaseeq(p, "yearly") ||
r = const_chain(1, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(1, &c->day);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "weekly")) {
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "quarterly")) {
r = const_chain(1, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(4, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(7, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(10, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(1, &c->day);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else if (strcaseeq(p, "biannually") ||
strcaseeq(p, "bi-annually") ||
r = const_chain(1, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(7, &c->month);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(1, &c->day);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->hour);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->minute);
if (r < 0)
- goto fail;
+ return r;
r = const_chain(0, &c->microsecond);
if (r < 0)
- goto fail;
+ return r;
} else {
r = parse_weekdays(&p, c);
if (r < 0)
- goto fail;
+ return r;
r = parse_date(&p, c);
if (r < 0)
- goto fail;
+ return r;
if (r == 0) {
r = parse_calendar_time(&p, c);
if (r < 0)
- goto fail;
+ return r;
}
- if (*p != 0) {
- r = -EINVAL;
- goto fail;
- }
+ if (*p != 0)
+ return -EINVAL;
}
r = calendar_spec_normalize(c);
if (r < 0)
- goto fail;
+ return r;
- if (!calendar_spec_valid(c)) {
- r = -EINVAL;
- goto fail;
- }
+ if (!calendar_spec_valid(c))
+ return -EINVAL;
- *spec = c;
+ *spec = TAKE_PTR(c);
return 0;
-
-fail:
- calendar_spec_free(c);
- return r;
}
static int find_end_of_month(struct tm *tm, bool utc, int day) {
#include <string.h>
#include "conf-files.h"
+#include "def.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "hashmap.h"
#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
#include "util.h"
static int files_add(Hashmap *h, const char *suffix, const char *root, unsigned flags, const char *path) {
return conf_files_list_strv_internal(strv, suffix, root, flags, d);
}
+
+int conf_files_list_with_replacement(
+ const char *root,
+ char **config_dirs,
+ const char *replacement,
+ char ***files,
+ char **replace_file) {
+
+ _cleanup_strv_free_ char **f = NULL;
+ _cleanup_free_ char *p = NULL;
+ int r;
+
+ assert(config_dirs);
+ assert(files);
+ assert(replace_file || !replacement);
+
+ r = conf_files_list_strv(&f, ".conf", root, 0, (const char* const*) config_dirs);
+ if (r < 0)
+ return log_error_errno(r, "Failed to enumerate config files: %m");
+
+ if (replacement) {
+ r = conf_files_insert(&f, root, config_dirs, replacement);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extend config file list: %m");
+
+ p = path_join(root, replacement, NULL);
+ if (!p)
+ return log_oom();
+ }
+
+ *files = TAKE_PTR(f);
+ if (replace_file)
+ *replace_file = TAKE_PTR(p);
+ return 0;
+}
+
+int conf_files_cat(const char *root, const char *name) {
+ _cleanup_strv_free_ char **dirs = NULL, **files = NULL;
+ _cleanup_free_ char *path = NULL;
+ const char *dir;
+ char **t;
+ int r;
+
+ NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) {
+ assert(endswith(dir, "/"));
+ r = strv_extendf(&dirs, "%s%s.d", dir, name);
+ if (r < 0)
+ return log_error("Failed to build directory list: %m");
+ }
+
+ r = conf_files_list_strv(&files, ".conf", root, 0, (const char* const*) dirs);
+ if (r < 0)
+ return log_error_errno(r, "Failed to query file list: %m");
+
+ path = path_join(root, "/etc", name);
+ if (!path)
+ return log_oom();
+
+ if (DEBUG_LOGGING) {
+ log_debug("Looking for configuration in:");
+ log_debug(" %s", path);
+ STRV_FOREACH(t, dirs)
+ log_debug(" %s/*.conf", *t);
+ }
+
+ /* show */
+ return cat_files(path, files, CAT_FLAGS_MAIN_FILE_OPTIONAL);
+}
int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dirs);
int conf_files_insert(char ***strv, const char *root, char **dirs, const char *path);
int conf_files_insert_nulstr(char ***strv, const char *root, const char *dirs, const char *path);
+int conf_files_list_with_replacement(
+ const char *root,
+ char **config_dirs,
+ const char *replacement,
+ char ***files,
+ char **replace_file);
+int conf_files_cat(const char *root, const char *name);
#define NOTIFY_BUFFER_MAX PIPE_BUF
#if HAVE_SPLIT_USR
-# define _CONF_PATHS_SPLIT_USR(n) "/lib/" n "\0"
+# define _CONF_PATHS_SPLIT_USR_NULSTR(n) "/lib/" n "\0"
+# define _CONF_PATHS_SPLIT_USR(n) , "/lib/" n
#else
+# define _CONF_PATHS_SPLIT_USR_NULSTR(n)
# define _CONF_PATHS_SPLIT_USR(n)
#endif
"/run/" n "\0" \
"/usr/local/lib/" n "\0" \
"/usr/lib/" n "\0" \
- _CONF_PATHS_SPLIT_USR(n)
+ _CONF_PATHS_SPLIT_USR_NULSTR(n)
+
+#define CONF_PATHS_STRV(n) \
+ STRV_MAKE( \
+ "/etc/" n, \
+ "/run/" n, \
+ "/usr/local/lib/" n, \
+ "/usr/lib/" n \
+ _CONF_PATHS_SPLIT_USR(n))
#define LONG_LINE_MAX (1U*1024U*1024U)
char **strv_env_set(char **x, const char *p) {
- char **k, **r;
+ char **k;
+ _cleanup_strv_free_ char **r = NULL;
char* m[2] = { (char*) p, NULL };
/* Overrides the env var setting of p, returns a new copy */
k = r;
if (env_append(r, &k, x) < 0)
- goto fail;
+ return NULL;
if (env_append(r, &k, m) < 0)
- goto fail;
+ return NULL;
*k = NULL;
- return r;
-
-fail:
- strv_free(r);
- return NULL;
+ return TAKE_PTR(r);
}
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {
return buffer;
}
-bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
+int ether_addr_compare(const void *a, const void *b) {
assert(a);
assert(b);
- return a->ether_addr_octet[0] == b->ether_addr_octet[0] &&
- a->ether_addr_octet[1] == b->ether_addr_octet[1] &&
- a->ether_addr_octet[2] == b->ether_addr_octet[2] &&
- a->ether_addr_octet[3] == b->ether_addr_octet[3] &&
- a->ether_addr_octet[4] == b->ether_addr_octet[4] &&
- a->ether_addr_octet[5] == b->ether_addr_octet[5];
+ return memcmp(a, b, ETH_ALEN);
}
-int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset) {
+static void ether_addr_hash_func(const void *p, struct siphash *state) {
+ siphash24_compress(p, sizeof(struct ether_addr), state);
+}
+
+const struct hash_ops ether_addr_hash_ops = {
+ .hash = ether_addr_hash_func,
+ .compare = ether_addr_compare
+};
+
+int ether_addr_from_string(const char *s, struct ether_addr *ret) {
size_t pos = 0, n, field;
char sep = '\0';
const char *hex = HEXDIGITS, *hexoff;
assert(s);
assert(ret);
+ s += strspn(s, WHITESPACE);
sep = s[strspn(s, hex)];
- if (sep == '\n')
- return -EINVAL;
- if (!strchr(":.-", sep))
- return -EINVAL;
if (sep == '.') {
uint16_t shorts[3] = { 0 };
parse_fields(shorts);
+ if (s[pos] != '\0')
+ return -EINVAL;
+
for (n = 0; n < ELEMENTSOF(shorts); n++) {
ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8);
ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff);
}
- } else {
- struct ether_addr out = { .ether_addr_octet = { 0 } };
+
+ } else if (IN_SET(sep, ':', '-')) {
+ struct ether_addr out = ETHER_ADDR_NULL;
parse_fields(out.ether_addr_octet);
+ if (s[pos] != '\0')
+ return -EINVAL;
+
for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++)
ret->ether_addr_octet[n] = out.ether_addr_octet[n];
- }
- if (offset)
- *offset = pos;
+ } else
+ return -EINVAL;
+
return 0;
}
#include <net/ethernet.h>
#include <stdbool.h>
+#include "hash-funcs.h"
+
#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]
#define ETHER_ADDR_TO_STRING_MAX (3*6)
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]);
-bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b);
+int ether_addr_compare(const void *a, const void *b);
+static inline bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) {
+ return ether_addr_compare(a, b) == 0;
+}
#define ETHER_ADDR_NULL ((const struct ether_addr){})
return ether_addr_equal(addr, ÐER_ADDR_NULL);
}
-int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset);
+int ether_addr_from_string(const char *s, struct ether_addr *ret);
+
+extern const struct hash_ops ether_addr_hash_ops;
d = opendir("/proc/self/fd");
if (!d) {
- int fd;
struct rlimit rl;
+ int fd, max_fd;
- /* When /proc isn't available (for example in chroots)
- * the fallback is brute forcing through the fd
+ /* When /proc isn't available (for example in chroots) the fallback is brute forcing through the fd
* table */
assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
- for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
+
+ if (rl.rlim_max == 0)
+ return -EINVAL;
+
+ /* Let's take special care if the resource limit is set to unlimited, or actually larger than the range
+ * of 'int'. Let's avoid implicit overflows. */
+ max_fd = (rl.rlim_max == RLIM_INFINITY || rl.rlim_max > INT_MAX) ? INT_MAX : (int) (rl.rlim_max - 1);
+
+ for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
int q;
if (fd_in_set(fd, except, n_except))
break;
}
+ va_end(ap);
return 0;
}
if (column == (size_t) -1)
break;
}
+ va_end(ap);
return 0;
}
}
int fchmod_opath(int fd, mode_t m) {
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
/* This function operates also on fd that might have been opened with
* O_PATH. Indeed fchmodat() doesn't have the AT_EMPTY_PATH flag like
return exists;
chased_one:
-
if (ret) {
char *c;
- if (done) {
- if (todo) {
- c = strjoin(done, todo);
- if (!c)
- return -ENOMEM;
- } else
- c = TAKE_PTR(done);
- } else {
- if (todo)
- c = strdup(todo);
- else
- c = strdup("/");
- if (!c)
- return -ENOMEM;
- }
+ c = strjoin(strempty(done), todo);
+ if (!c)
+ return -ENOMEM;
*ret = c;
}
return r;
}
+void unlink_tempfilep(char (*p)[]) {
+ /* If the file is created with mkstemp(), it will (almost always)
+ * change the suffix. Treat this as a sign that the file was
+ * successfully created. We ignore both the rare case where the
+ * original suffix is used and unlink failures. */
+ if (!endswith(*p, ".XXXXXX"))
+ (void) unlink_noerrno(*p);
+}
+
int unlinkat_deallocate(int fd, const char *name, int flags) {
_cleanup_close_ int truncate_fd = -1;
struct stat st;
int access_fd(int fd, int mode);
+void unlink_tempfilep(char (*p)[]);
int unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd);
},
};
-#ifdef VALGRIND
+#if VALGRIND
__attribute__((destructor)) static void cleanup_pools(void) {
_cleanup_free_ char *t = NULL;
int r;
return r;
}
-int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
- _cleanup_free_ uint8_t *r = NULL;
- uint8_t *z;
+static int unhex_next(const char **p, size_t *l) {
+ int r;
+
+ assert(p);
+ assert(l);
+
+ /* Find the next non-whitespace character, and decode it. We
+ * greedily skip all preceeding and all following whitespace. */
+
+ for (;;) {
+ if (*l == 0)
+ return -EPIPE;
+
+ if (!strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip leading whitespace */
+ (*p)++, (*l)--;
+ }
+
+ r = unhexchar(**p);
+ if (r < 0)
+ return r;
+
+ for (;;) {
+ (*p)++, (*l)--;
+
+ if (*l == 0 || !strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip following whitespace */
+ }
+
+ return r;
+}
+
+int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
+ _cleanup_free_ uint8_t *buf = NULL;
const char *x;
+ uint8_t *z;
- assert(mem);
- assert(len);
+ assert(ret);
+ assert(ret_len);
assert(p || l == 0);
if (l == (size_t) -1)
l = strlen(p);
- if (l % 2 != 0)
- return -EINVAL;
-
- z = r = malloc((l + 1) / 2 + 1);
- if (!r)
+ /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
+ buf = malloc((l + 1) / 2 + 1);
+ if (!buf)
return -ENOMEM;
- for (x = p; x < p + l; x += 2) {
+ for (x = p, z = buf;;) {
int a, b;
- a = unhexchar(x[0]);
+ a = unhex_next(&x, &l);
+ if (a == -EPIPE) /* End of string */
+ break;
if (a < 0)
return a;
- b = unhexchar(x[1]);
+ b = unhex_next(&x, &l);
if (b < 0)
return b;
*z = 0;
- *mem = TAKE_PTR(r);
- *len = (l + 1) / 2;
+ *ret_len = (size_t) (z - buf);
+ *ret = TAKE_PTR(buf);
return 0;
}
for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) {
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ
- x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
+ * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */
*(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */
*(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */
*(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */
}
/* a group of eight input bytes needs five output bytes, in case of
- padding we need to add some extra bytes */
+ * padding we need to add some extra bytes */
len = (l / 8) * 5;
switch (l % 8) {
for (x = p; x < p + (l / 8) * 8; x += 8) {
/* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW
- e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
+ * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */
a = unbase32hexchar(x[0]);
if (a < 0)
return -EINVAL;
l = strlen(p);
/* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
- bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
+ * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0);
buf = malloc(len + 1);
*z = 0;
- if (ret_size)
- *ret_size = (size_t) (z - buf);
-
+ *ret_size = (size_t) (z - buf);
*ret = TAKE_PTR(buf);
return 0;
return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;
}
+
+int log_dup_console(void) {
+ int copy;
+
+ /* Duplicate the fd we use for fd logging if it's < 3 and use the copy from now on. This call is useful
+ * whenever we want to continue logging through the original fd, but want to rearrange stderr. */
+
+ if (console_fd >= 3)
+ return 0;
+
+ copy = fcntl(console_fd, F_DUPFD_CLOEXEC, 3);
+ if (copy < 0)
+ return -errno;
+
+ console_fd = copy;
+ return 0;
+}
* stderr, the console or kmsg */
void log_set_prohibit_ipc(bool b);
+int log_dup_console(void);
+
int log_syntax_internal(
const char *unit,
int level,
mp->freelist = p;
}
-#ifdef VALGRIND
+#if VALGRIND
void mempool_drop(struct mempool *mp) {
struct pool *p = mp->first_pool;
.at_least = alloc_at_least, \
}
-
-#ifdef VALGRIND
+#if VALGRIND
void mempool_drop(struct mempool *mp);
#endif
endforeach
basic_sources += [missing_h] + generated_gperf_headers
+basic_gcrypt_sources = files(
+ 'gcrypt-util.c',
+ 'gcrypt-util.h')
libbasic = static_library(
'basic',
# unnecessary linking to libgcrypt.
libbasic_gcrypt = static_library(
'basic-gcrypt',
- 'gcrypt-util.c',
- 'gcrypt-util.h',
+ basic_gcrypt_sources,
include_directories : includes,
dependencies : [libgcrypt],
c_args : ['-fvisibility=default'])
__u32 len;
};
-
struct btrfs_ioctl_search_args {
struct btrfs_ioctl_search_key key;
char buf[BTRFS_SEARCH_ARGS_BUFSIZE];
# define kcmp missing_kcmp
#endif
-
/* ======================================================================= */
#if !HAVE_KEYCTL
*ret = d;
return 0;
}
+
+int parse_oom_score_adjust(const char *s, int *ret) {
+ int r, v;
+
+ assert(s);
+ assert(ret);
+
+ r = safe_atoi(s, &v);
+ if (r < 0)
+ return r;
+
+ if (v < OOM_SCORE_ADJ_MIN || v > OOM_SCORE_ADJ_MAX)
+ return -ERANGE;
+
+ *ret = v;
+ return 0;
+}
int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret);
+
+int parse_oom_score_adjust(const char *s, int *ret);
return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path);
path_kill_slashes(p);
- if (suppress_root && path_equal(p, "/"))
+ if (suppress_root && empty_or_root(p))
p = mfree(p);
free(*arg);
*arg = p;
+
return 0;
}
if (r < 0)
return r;
- assert_se((c = endswith(path, "*.so")));
+ assert_se(c = endswith(path, "*.so"));
*c = '\0'; /* truncate the glob part */
STRV_FOREACH(name, names) {
}
bool empty_or_root(const char *root);
+static inline const char *empty_to_root(const char *path) {
+ return isempty(path) ? "/" : path;
+}
_exit(EXIT_FAILURE);
}
+int set_oom_score_adjust(int value) {
+ char t[DECIMAL_STR_MAX(int)];
+
+ sprintf(t, "%i", value);
+
+ return write_string_file("/proc/self/oom_score_adj", t,
+ WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
+}
+
static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime",
int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...);
+int set_oom_score_adjust(int value);
+
#if SIZEOF_PID_T == 4
/* The highest possibly (theoretic) pid_t value on this architecture. */
#define PID_T_MAX ((pid_t) INT32_MAX)
/* Modelled after Linux' lib/ratelimit.c by Dave Young
* <hidave.darkstar@gmail.com>, which is licensed GPLv2. */
-bool ratelimit_test(RateLimit *r) {
+bool ratelimit_below(RateLimit *r) {
usec_t ts;
assert(r);
_r->begin = 0; \
} while (false)
-bool ratelimit_test(RateLimit *r);
+bool ratelimit_below(RateLimit *r);
if (getrlimit(resource, &highest) < 0)
return -errno;
+ /* If the hard limit is unbounded anyway, then the EPERM had other reasons, let's propagate the original EPERM
+ * then */
+ if (highest.rlim_max == RLIM_INFINITY)
+ return -EPERM;
+
fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
return 0;
}
+int setrlimit_closest_all(const struct rlimit *const *rlim, int *which_failed) {
+ int i, r;
+
+ assert(rlim);
+
+ /* On failure returns the limit's index that failed in *which_failed, but only if non-NULL */
+
+ for (i = 0; i < _RLIMIT_MAX; i++) {
+ if (!rlim[i])
+ continue;
+
+ r = setrlimit_closest(i, rlim[i]);
+ if (r < 0) {
+ if (which_failed)
+ *which_failed = i;
+
+ return r;
+ }
+ }
+
+ if (which_failed)
+ *which_failed = -1;
+
+ return 0;
+}
+
static int rlimit_parse_u64(const char *val, rlim_t *ret) {
uint64_t u;
int r;
}
static const char* const rlimit_table[_RLIMIT_MAX] = {
- [RLIMIT_CPU] = "LimitCPU",
- [RLIMIT_FSIZE] = "LimitFSIZE",
- [RLIMIT_DATA] = "LimitDATA",
- [RLIMIT_STACK] = "LimitSTACK",
- [RLIMIT_CORE] = "LimitCORE",
- [RLIMIT_RSS] = "LimitRSS",
- [RLIMIT_NOFILE] = "LimitNOFILE",
- [RLIMIT_AS] = "LimitAS",
- [RLIMIT_NPROC] = "LimitNPROC",
- [RLIMIT_MEMLOCK] = "LimitMEMLOCK",
- [RLIMIT_LOCKS] = "LimitLOCKS",
- [RLIMIT_SIGPENDING] = "LimitSIGPENDING",
- [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE",
- [RLIMIT_NICE] = "LimitNICE",
- [RLIMIT_RTPRIO] = "LimitRTPRIO",
- [RLIMIT_RTTIME] = "LimitRTTIME"
+ [RLIMIT_AS] = "AS",
+ [RLIMIT_CORE] = "CORE",
+ [RLIMIT_CPU] = "CPU",
+ [RLIMIT_DATA] = "DATA",
+ [RLIMIT_FSIZE] = "FSIZE",
+ [RLIMIT_LOCKS] = "LOCKS",
+ [RLIMIT_MEMLOCK] = "MEMLOCK",
+ [RLIMIT_MSGQUEUE] = "MSGQUEUE",
+ [RLIMIT_NICE] = "NICE",
+ [RLIMIT_NOFILE] = "NOFILE",
+ [RLIMIT_NPROC] = "NPROC",
+ [RLIMIT_RSS] = "RSS",
+ [RLIMIT_RTPRIO] = "RTPRIO",
+ [RLIMIT_RTTIME] = "RTTIME",
+ [RLIMIT_SIGPENDING] = "SIGPENDING",
+ [RLIMIT_STACK] = "STACK",
};
DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
+
+int rlimit_from_string_harder(const char *s) {
+ const char *suffix;
+
+ /* The official prefix */
+ suffix = startswith(s, "RLIMIT_");
+ if (suffix)
+ return rlimit_from_string(suffix);
+
+ /* Our own unit file setting prefix */
+ suffix = startswith(s, "Limit");
+ if (suffix)
+ return rlimit_from_string(suffix);
+
+ return rlimit_from_string(s);
+}
+
+void rlimit_free_all(struct rlimit **rl) {
+ int i;
+
+ if (!rl)
+ return;
+
+ for (i = 0; i < _RLIMIT_MAX; i++)
+ rl[i] = mfree(rl[i]);
+}
const char *rlimit_to_string(int i) _const_;
int rlimit_from_string(const char *s) _pure_;
+int rlimit_from_string_harder(const char *s) _pure_;
int setrlimit_closest(int resource, const struct rlimit *rlim);
+int setrlimit_closest_all(const struct rlimit * const *rlim, int *which_failed);
int rlimit_parse_one(int resource, const char *val, rlim_t *ret);
int rlimit_parse(int resource, const char *val, struct rlimit *ret);
int rlimit_format(const struct rlimit *rl, char **ret);
+void rlimit_free_all(struct rlimit **rl);
+
#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
#include <sys/statfs.h>
#include <unistd.h>
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "cgroup-util.h"
#include "dirent-util.h"
}
if (is_physical_fs(&sfs)) {
- /* We refuse to clean physical file systems
- * with this call, unless explicitly
- * requested. This is extra paranoia just to
- * be sure we never ever remove non-state
- * data */
+ /* We refuse to clean physical file systems with this call,
+ * unless explicitly requested. This is extra paranoia just
+ * to be sure we never ever remove non-state data. */
+ _cleanup_free_ char *path = NULL;
+
+ (void) fd_get_path(fd, &path);
+ log_error("Attempted to remove disk file system under \"%s\", and we can't allow that.",
+ strna(path));
- log_error("Attempted to remove disk file system, and we can't allow that.");
safe_close(fd);
return -EPERM;
}
* call. This is extra paranoia to never cause a really
* seriously broken system. */
if (path_equal_or_files_same(path, "/", AT_SYMLINK_NOFOLLOW)) {
- log_error("Attempted to remove entire root file system, and we can't allow that.");
+ log_error("Attempted to remove entire root file system (\"%s\"), and we can't allow that.", path);
return -EPERM;
}
fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
if (fd < 0) {
-
if (!IN_SET(errno, ENOTDIR, ELOOP))
return -errno;
return -errno;
if (is_physical_fs(&s)) {
- log_error("Attempted to remove disk file system, and we can't allow that.");
+ log_error("Attempted to remove files from a disk file system under \"%s\", refusing.", path);
return -EPERM;
}
}
#include <stdint.h>
#include <sys/types.h>
+#include "macro.h"
+
struct strbuf {
char *buf;
size_t len;
ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len);
void strbuf_complete(struct strbuf *str);
void strbuf_cleanup(struct strbuf *str);
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_cleanup);
return (type) -1; \
} \
-
#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope)
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static)
+
+#define DUMP_STRING_TABLE(name,type,max) \
+ do { \
+ type _k; \
+ flockfile(stdout); \
+ for (_k = 0; _k < (max); _k++) { \
+ const char *_t; \
+ _t = name##_to_string(_k); \
+ if (!_t) \
+ continue; \
+ fputs_unlocked(_t, stdout); \
+ fputc_unlocked('\n', stdout); \
+ } \
+ funlockfile(stdout); \
+ } while(false)
return isempty(p) ? NULL : p;
}
-static inline const char *strdash_if_empty(const char *str) {
+static inline const char *empty_to_dash(const char *str) {
return isempty(str) ? "-" : str;
}
char **strv_new_ap(const char *x, va_list ap) {
const char *s;
- char **a;
+ _cleanup_strv_free_ char **a = NULL;
size_t n = 0, i = 0;
va_list aq;
if (x != STRV_IGNORE) {
a[i] = strdup(x);
if (!a[i])
- goto fail;
+ return NULL;
i++;
}
a[i] = strdup(s);
if (!a[i])
- goto fail;
+ return NULL;
i++;
}
a[i] = NULL;
- return a;
-
-fail:
- strv_free(a);
- return NULL;
+ return TAKE_PTR(a);
}
char **strv_new(const char *x, ...) {
Copyright 2013 Kay Sievers
***/
-
#include <stddef.h>
#include "macro.h"
#include <unistd.h>
#include "alloc-util.h"
+#include "copy.h"
+#include "def.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
return terminal_urlify(url, text, ret);
}
+
+static int cat_file(const char *filename, bool newline) {
+ _cleanup_fclose_ FILE *f = NULL;
+ int r;
+
+ f = fopen(filename, "re");
+ if (!f)
+ return -errno;
+
+ printf("%s%s# %s%s\n",
+ newline ? "\n" : "",
+ ansi_highlight_blue(),
+ filename,
+ ansi_normal());
+ fflush(stdout);
+
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read \"%s\": %m", filename);
+ if (r == 0)
+ break;
+
+ puts(line);
+ }
+
+ return 0;
+}
+
+int cat_files(const char *file, char **dropins, CatFlags flags) {
+ char **path;
+ int r;
+
+ if (file) {
+ r = cat_file(file, false);
+ if (r == -ENOENT && (flags & CAT_FLAGS_MAIN_FILE_OPTIONAL))
+ printf("%s# config file %s not found%s\n",
+ ansi_highlight_magenta(),
+ file,
+ ansi_normal());
+ else if (r < 0)
+ return log_warning_errno(r, "Failed to cat %s: %m", file);
+ }
+
+ STRV_FOREACH(path, dropins) {
+ r = cat_file(*path, file || path != dropins);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to cat %s: %m", *path);
+ }
+
+ return 0;
+}
+
+void print_separator(void) {
+
+ /* Outputs a separator line that resolves to whitespace when copied from the terminal. We do that by outputting
+ * one line filled with spaces with ANSI underline set, followed by a second (empty) line. */
+
+ if (underline_enabled()) {
+ size_t i, c;
+
+ c = columns();
+
+ flockfile(stdout);
+ fputs_unlocked(ANSI_UNDERLINE, stdout);
+
+ for (i = 0; i < c; i++)
+ fputc_unlocked(' ', stdout);
+
+ fputs_unlocked(ANSI_NORMAL "\n\n", stdout);
+ funlockfile(stdout);
+ } else
+ fputs("\n\n", stdout);
+}
DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN);
DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW);
DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE);
+DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA);
DEFINE_ANSI_FUNC(normal, NORMAL);
DEFINE_ANSI_FUNC_UNDERLINE(underline, UNDERLINE, NORMAL);
int terminal_urlify(const char *url, const char *text, char **ret);
int terminal_urlify_path(const char *path, const char *text, char **ret);
+
+typedef enum CatFlags {
+ CAT_FLAGS_MAIN_FILE_OPTIONAL = 1 << 1,
+} CatFlags;
+
+int cat_files(const char *file, char **dropins, CatFlags flags);
+
+void print_separator(void);
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "io-util.h"
#include "log.h"
#include "macro.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
+#include "stat-util.h"
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
int r, weekday = -1, dst = -1;
size_t i;
- /*
- * Allowed syntaxes:
+ /* Allowed syntaxes:
*
* 2012-09-22 16:34:22
* 2012-09-22 16:34 (seconds will be set to 0)
* +5min
* -5days
* @2147483647 (seconds since epoch)
- *
*/
assert(t);
tzset();
/* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only
- * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
- * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
- * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
- * support arbitrary timezone specifications. */
+ * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because
+ * there are no nice APIs available to cover this. By accepting the local time zone strings, we make
+ * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't
+ * support arbitrary timezone specifications. */
for (j = 0; j <= 1; j++) {
int r;
last_space = strrchr(t, ' ');
- if (last_space != NULL && timezone_is_valid(last_space + 1))
+ if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG))
tz = last_space + 1;
if (!tz || endswith_no_case(t, " UTC"))
tzset();
/* If there is a timezone that matches the tzname fields, leave the parsing to the implementation.
- * Otherwise just cut it off */
+ * Otherwise just cut it off. */
with_tz = !STR_IN_SET(tz, tzname[0], tzname[1]);
- /*cut off the timezone if we dont need it*/
+ /* Cut off the timezone if we dont need it. */
if (with_tz)
t = strndupa(t, last_space - t);
return 0;
}
-bool timezone_is_valid(const char *name) {
+bool timezone_is_valid(const char *name, int log_level) {
bool slash = false;
const char *p, *t;
- struct stat st;
+ _cleanup_close_ int fd = -1;
+ char buf[4];
+ int r;
if (isempty(name))
return false;
return false;
t = strjoina("/usr/share/zoneinfo/", name);
- if (stat(t, &st) < 0)
+
+ fd = open(t, O_RDONLY|O_CLOEXEC);
+ if (fd < 0) {
+ log_full_errno(log_level, errno, "Failed to open timezone file '%s': %m", t);
return false;
+ }
- if (!S_ISREG(st.st_mode))
+ r = fd_verify_regular(fd);
+ if (r < 0) {
+ log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t);
return false;
+ }
+
+ r = loop_read_exact(fd, buf, 4, false);
+ if (r < 0) {
+ log_full_errno(log_level, r, "Failed to read from timezone file '%s': %m", t);
+ return false;
+ }
+
+ /* Magic from tzfile(5) */
+ if (memcmp(buf, "TZif", 4) != 0) {
+ log_full(log_level, "Timezone file '%s' has wrong magic bytes", t);
+ return false;
+ }
return true;
}
if (!e)
return -EINVAL;
- if (!timezone_is_valid(e))
+ if (!timezone_is_valid(e, LOG_DEBUG))
return -EINVAL;
z = strdup(e);
bool ntp_synced(void);
int get_timezones(char ***l);
-bool timezone_is_valid(const char *name);
+bool timezone_is_valid(const char *name, int log_level);
bool clock_boottime_supported(void);
bool clock_supported(clockid_t clock);
uint64_t mem, lim;
size_t ps;
long sc;
+ int r;
/* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
* memory.
ps = page_size();
mem = (uint64_t) sc * (uint64_t) ps;
- if (cg_get_root_path(&root) < 0)
+ r = cg_get_root_path(&root);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m");
return mem;
+ }
- if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
+ r = cg_all_unified();
+ if (r < 0) {
+ log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m");
return mem;
+ }
+ if (r > 0) {
+ r = cg_get_attribute("memory", root, "memory.max", &value);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
+ return mem;
+ }
+
+ if (streq(value, "max"))
+ return mem;
+ } else {
+ r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m");
+ return mem;
+ }
+ }
- if (safe_atou64(value, &lim) < 0)
+ r = safe_atou64(value, &lim);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value);
+ return mem;
+ }
+ if (lim == UINT64_MAX)
return mem;
/* Make sure the limit is a multiple of our own page size */
uint64_t a = TASKS_MAX, b = TASKS_MAX;
_cleanup_free_ char *root = NULL;
+ int r;
/* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
* limit:
*
* And then pick the smallest of the three */
- (void) procfs_tasks_get_limit(&a);
+ r = procfs_tasks_get_limit(&a);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m");
- if (cg_get_root_path(&root) >= 0) {
+ r = cg_get_root_path(&root);
+ if (r < 0)
+ log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m");
+ else {
_cleanup_free_ char *value = NULL;
- if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
- (void) safe_atou64(value, &b);
+ r = cg_get_attribute("pids", root, "pids.max", &value);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m");
+ else if (!streq(value, "max")) {
+ r = safe_atou64(value, &b);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m");
+ }
}
return MIN3(TASKS_MAX,
#include "log.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
#include "util.h"
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("binfmt.d");
+static bool arg_cat_config = false;
static int delete_rule(const char *rule) {
_cleanup_free_ char *x = NULL, *fn = NULL;
assert(path);
- r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
+ r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f);
if (r < 0) {
if (ignore_enoent && r == -ENOENT)
return 0;
"Registers binary formats.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --cat-config Show configuration files\n"
, program_invocation_short_name);
}
enum {
ARG_VERSION = 0x100,
+ ARG_CAT_CONFIG,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
{}
};
case ARG_VERSION:
return version();
+ case ARG_CAT_CONFIG:
+ arg_cat_config = true;
+ break;
+
case '?':
return -EINVAL;
assert_not_reached("Unhandled option");
}
+ if (arg_cat_config && argc > optind) {
+ log_error("Positional arguments are not allowed with --cat-config");
+ return -EINVAL;
+ }
+
return 1;
}
_cleanup_strv_free_ char **files = NULL;
char **f;
- r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
+ r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("binfmt.d"));
if (r < 0) {
log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
goto finish;
}
+ if (arg_cat_config) {
+ r = cat_files(NULL, files, 0);
+ goto finish;
+ }
+
/* Flush out all rules */
write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
return 0;
}
-static const char *strdash(const char *x) {
- return isempty(x) ? "-" : x;
-}
-
static int introspect(int argc, char **argv, void *userdata) {
static const struct hash_ops member_hash_ops = {
.hash = member_hash_func,
rv = ellipsized;
} else
- rv = strdash(m->result);
+ rv = empty_to_dash(m->result);
printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n",
is_interface ? ansi_highlight() : "",
is_interface ? "" : ".",
- - !is_interface + (int) name_width, strdash(streq_ptr(m->type, "interface") ? m->interface : m->name),
+ - !is_interface + (int) name_width, empty_to_dash(streq_ptr(m->type, "interface") ? m->interface : m->name),
is_interface ? ansi_normal() : "",
- (int) type_width, strdash(m->type),
- (int) signature_width, strdash(m->signature),
+ (int) type_width, empty_to_dash(m->type),
+ (int) signature_width, empty_to_dash(m->signature),
(int) result_width, rv,
(m->flags & SD_BUS_VTABLE_DEPRECATED) ? " deprecated" : (m->flags || m->writable ? "" : " -"),
(m->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ? " no-reply" : "",
if (cg_all_unified() == 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER))
printf("Controller %s; ", controller);
- printf("Control group %s:\n", isempty(path) ? "/" : path);
+ printf("Control group %s:\n", empty_to_root(path));
fflush(stdout);
}
return 0;
}
-static const char *empty_to_slash(const char *p) {
- return isempty(p) ? "/" : p;
-}
-
static int group_compare(const void*a, const void *b) {
const Group *x = *(Group**)a, *y = *(Group**)b;
* recursive summing is off, since that is actually
* not accumulative for all children. */
- if (path_startswith(empty_to_slash(y->path), empty_to_slash(x->path)))
+ if (path_startswith(empty_to_root(y->path), empty_to_root(x->path)))
return -1;
- if (path_startswith(empty_to_slash(x->path), empty_to_slash(y->path)))
+ if (path_startswith(empty_to_root(x->path), empty_to_root(y->path)))
return 1;
}
g = array[j];
- path = empty_to_slash(g->path);
+ path = empty_to_root(g->path);
ellipsized = ellipsize(path, path_columns, 33);
printf("%-*s", path_columns, ellipsized ?: path);
--- /dev/null
+#pragma once
+
+#include "unit.h"
+
+#include "automount.h"
+#include "device.h"
+#include "path.h"
+#include "scope.h"
+#include "service.h"
+#include "slice.h"
+#include "socket.h"
+#include "swap.h"
+#include "target.h"
+#include "timer.h"
const char* automount_result_to_string(AutomountResult i) _const_;
AutomountResult automount_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(AUTOMOUNT, Automount);
_CGROUP_IP_ACCOUNTING_METRIC_INVALID = -1,
} CGroupIPAccountingMetric;
-#include "unit.h"
+typedef struct Unit Unit;
+typedef struct Manager Manager;
void cgroup_context_init(CGroupContext *c);
void cgroup_context_done(CGroupContext *c);
Copyright 2010 Lennart Poettering
***/
-
extern const sd_bus_vtable bus_automount_vtable[];
int bus_automount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
#include "sd-bus.h"
+#include "unit.h"
#include "cgroup.h"
extern const sd_bus_vtable bus_cgroup_vtable[];
BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
-
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode);
-
-static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
-static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_home, protect_home, ProtectHome);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system, protect_system, ProtectSystem);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality, personality, unsigned long);
+static BUS_DEFINE_PROPERTY_GET(property_get_ioprio, "i", ExecContext, exec_context_get_effective_ioprio);
+static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_class, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_CLASS);
+static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_DATA);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL);
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI);
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC);
static int property_get_environment_files(
sd_bus *bus,
return sd_bus_message_append(reply, "i", n);
}
-static int property_get_ioprio(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", exec_context_get_effective_ioprio(c));
-}
-
-static int property_get_ioprio_class(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", IOPRIO_PRIO_CLASS(exec_context_get_effective_ioprio(c)));
-}
-
-static int property_get_ioprio_priority(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", IOPRIO_PRIO_DATA(exec_context_get_effective_ioprio(c)));
-}
-
static int property_get_cpu_sched_policy(
sd_bus *bus,
const char *path,
assert(reply);
assert(c);
- if (c->cpuset)
- return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
- else
- return sd_bus_message_append_array(reply, 'y', NULL, 0);
+ return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
}
static int property_get_timer_slack_nsec(
return sd_bus_message_append(reply, "t", u);
}
-static int property_get_capability_bounding_set(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "t", c->capability_bounding_set);
-}
-
-static int property_get_ambient_capabilities(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "t", c->capability_ambient_set);
-}
-
-static int property_get_empty_string(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", "");
-}
-
static int property_get_syscall_filter(
sd_bus *bus,
const char *path,
return 0;
}
-static int property_get_syscall_errno(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
-}
-
static int property_get_selinux_context(
sd_bus *bus,
const char *path,
return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
}
-static int property_get_personality(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
-}
-
static int property_get_address_families(
sd_bus *bus,
const char *path,
return sd_bus_message_append(reply, "s", wd);
}
-static int property_get_syslog_level(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
-}
-
-static int property_get_syslog_facility(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- ExecContext *c = userdata;
-
- assert(bus);
- assert(reply);
- assert(c);
-
- return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
-}
-
static int property_get_stdio_fdname(
sd_bus *bus,
const char *path,
SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int, offsetof(ExecContext, log_level_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("CapabilityBoundingSet", "t", NULL, offsetof(ExecContext, capability_bounding_set), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("AmbientCapabilities", "t", NULL, offsetof(ExecContext, capability_ambient_set), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ProtectHome", "s", property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ProtectSystem", "s", property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
UnitWriteFlags flags,
sd_bus_error *error) {
- const char *soft = NULL;
- int r, ri;
+ const char *suffix;
+ int r;
assert(u);
assert(c);
if (!e)
return -ENOMEM;
- strv_free(c->environment);
- c->environment = e;
-
+ strv_free_and_replace(c->environment, e);
unit_write_settingf(u, flags, name, "Environment=%s", joined);
}
}
if (!e)
return -ENOMEM;
- strv_free(c->unset_environment);
- c->unset_environment = e;
-
+ strv_free_and_replace(c->unset_environment, e);
unit_write_settingf(u, flags, name, "UnsetEnvironment=%s", joined);
}
}
return r;
STRV_FOREACH(p, l) {
- if (!path_is_normalized(*p) || path_is_absolute(*p))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not valid: %s", name, *p);
+ if (!path_is_normalized(*p))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not normalized: %s", name, *p);
+
+ if (path_is_absolute(*p))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is absolute: %s", name, *p);
+
+ if (path_startswith(*p, "private"))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path can't be 'private': %s", name, *p);
}
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
}
return 1;
- }
- ri = rlimit_from_string(name);
- if (ri < 0) {
- soft = endswith(name, "Soft");
- if (soft) {
- const char *n;
+ } else if ((suffix = startswith(name, "Limit"))) {
+ const char *soft = NULL;
+ int ri;
- n = strndupa(name, soft - name);
- ri = rlimit_from_string(n);
- if (ri >= 0)
- name = n;
+ ri = rlimit_from_string(suffix);
+ if (ri < 0) {
+ soft = endswith(suffix, "Soft");
+ if (soft) {
+ const char *n;
+ n = strndupa(suffix, soft - suffix);
+ ri = rlimit_from_string(n);
+ if (ri >= 0)
+ name = strjoina("Limit", n);
+ }
}
- }
- if (ri >= 0) {
- uint64_t rl;
- rlim_t x;
+ if (ri >= 0) {
+ uint64_t rl;
+ rlim_t x;
- r = sd_bus_message_read(message, "t", &rl);
- if (r < 0)
- return r;
-
- if (rl == (uint64_t) -1)
- x = RLIM_INFINITY;
- else {
- x = (rlim_t) rl;
-
- if ((uint64_t) x != rl)
- return -ERANGE;
- }
-
- if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
- _cleanup_free_ char *f = NULL;
- struct rlimit nl;
-
- if (c->rlimit[ri]) {
- nl = *c->rlimit[ri];
-
- if (soft)
- nl.rlim_cur = x;
- else
- nl.rlim_max = x;
- } else
- /* When the resource limit is not initialized yet, then assign the value to both fields */
- nl = (struct rlimit) {
- .rlim_cur = x,
- .rlim_max = x,
- };
-
- r = rlimit_format(&nl, &f);
+ r = sd_bus_message_read(message, "t", &rl);
if (r < 0)
return r;
- if (c->rlimit[ri])
- *c->rlimit[ri] = nl;
+ if (rl == (uint64_t) -1)
+ x = RLIM_INFINITY;
else {
- c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
- if (!c->rlimit[ri])
- return -ENOMEM;
+ x = (rlim_t) rl;
+
+ if ((uint64_t) x != rl)
+ return -ERANGE;
}
- unit_write_settingf(u, flags, name, "%s=%s", name, f);
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ _cleanup_free_ char *f = NULL;
+ struct rlimit nl;
+
+ if (c->rlimit[ri]) {
+ nl = *c->rlimit[ri];
+
+ if (soft)
+ nl.rlim_cur = x;
+ else
+ nl.rlim_max = x;
+ } else
+ /* When the resource limit is not initialized yet, then assign the value to both fields */
+ nl = (struct rlimit) {
+ .rlim_cur = x,
+ .rlim_max = x,
+ };
+
+ r = rlimit_format(&nl, &f);
+ if (r < 0)
+ return r;
+
+ if (c->rlimit[ri])
+ *c->rlimit[ri] = nl;
+ else {
+ c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
+ if (!c->rlimit[ri])
+ return -ENOMEM;
+ }
+
+ unit_write_settingf(u, flags, name, "%s=%s", name, f);
+ }
+
+ return 1;
}
- return 1;
}
return 0;
(force ? UNIT_FILE_FORCE : 0);
}
-static int property_get_version(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
-}
-
-static int property_get_features(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
-}
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", PACKAGE_VERSION);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_features, "s", SYSTEMD_FEATURES);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_architecture, "s", architecture_to_string(uname_architecture()));
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_log_target, "s", log_target_to_string(log_get_target()));
+static BUS_DEFINE_PROPERTY_GET2(property_get_system_state, "s", Manager, manager_state, manager_state_to_string);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_timer_slack_nsec, "t", (uint64_t) prctl(PR_GET_TIMERSLACK));
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "u", Hashmap *, hashmap_size);
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_set_size, "u", Set *, set_size);
static int property_get_virtualization(
sd_bus *bus,
return sd_bus_message_append(
reply, "s",
- v == VIRTUALIZATION_NONE ? "" : virtualization_to_string(v));
-}
-
-static int property_get_architecture(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", architecture_to_string(uname_architecture()));
+ v == VIRTUALIZATION_NONE ? NULL : virtualization_to_string(v));
}
static int property_get_tainted(
return sd_bus_message_append(reply, "s", s);
}
-static int property_get_log_target(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
-}
-
static int property_set_log_target(
sd_bus *bus,
const char *path,
return r;
}
-static int property_get_n_names(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
-}
-
-static int property_get_n_failed_units(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "u", (uint32_t) set_size(m->failed_units));
-}
-
-static int property_get_n_jobs(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
-}
-
static int property_get_progress(
sd_bus *bus,
const char *path,
return sd_bus_message_append(reply, "d", d);
}
-static int property_get_system_state(
+static int property_get_show_status(
sd_bus *bus,
const char *path,
const char *interface,
sd_bus_error *error) {
Manager *m = userdata;
+ int b;
assert(bus);
assert(reply);
assert(m);
- return sd_bus_message_append(reply, "s", manager_state_to_string(manager_state(m)));
+ b = m->show_status > 0;
+ return sd_bus_message_append_basic(reply, 'b', &b);
}
static int property_set_runtime_watchdog(
return watchdog_set_timeout(t);
}
-static int property_get_timer_slack_nsec(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "t", (uint64_t) prctl(PR_GET_TIMERSLACK));
-}
-
static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) {
Unit *u;
int r;
return sd_bus_reply_method_return(message, NULL);
}
-static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int dump_impl(sd_bus_message *message, void *userdata, sd_bus_error *error, int (*reply)(sd_bus_message *, char *)) {
_cleanup_free_ char *dump = NULL;
Manager *m = userdata;
int r;
if (r < 0)
return r;
+ return reply(message, dump);
+}
+
+static int reply_dump(sd_bus_message *message, char *dump) {
return sd_bus_reply_method_return(message, "s", dump);
}
+static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return dump_impl(message, userdata, error, reply_dump);
+}
+
+static int reply_dump_by_fd(sd_bus_message *message, char *dump) {
+ _cleanup_close_ int fd = -1;
+
+ fd = acquire_data_fd(dump, strlen(dump), 0);
+ if (fd < 0)
+ return fd;
+
+ return sd_bus_reply_method_return(message, "h", fd);
+}
+
+static int method_dump_by_fd(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return dump_impl(message, userdata, error, reply_dump_by_fd);
+}
+
static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed.");
}
BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
- SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
- SD_BUS_PROPERTY("NFailedUnits", "u", property_get_n_failed_units, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
+ SD_BUS_PROPERTY("NNames", "u", property_get_hashmap_size, offsetof(Manager, units), 0),
+ SD_BUS_PROPERTY("NFailedUnits", "u", property_get_set_size, offsetof(Manager, failed_units), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("NJobs", "u", property_get_hashmap_size, offsetof(Manager, jobs), 0),
SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ShowStatus", "b", property_get_show_status, 0, 0),
SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.search_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("DumpByFileDescriptor", NULL, "h", method_dump_by_fd, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN),
SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN),
SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
#include "string-util.h"
#include "unit.h"
-static int property_get_what(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Mount *m = userdata;
- const char *d = NULL;
-
- assert(bus);
- assert(reply);
- assert(m);
-
+static const char *mount_get_what(const Mount *m) {
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what)
- d = m->parameters_proc_self_mountinfo.what;
- else if (m->from_fragment && m->parameters_fragment.what)
- d = m->parameters_fragment.what;
-
- return sd_bus_message_append(reply, "s", d);
+ return m->parameters_proc_self_mountinfo.what;
+ if (m->from_fragment && m->parameters_fragment.what)
+ return m->parameters_fragment.what;
+ return NULL;
}
-static int property_get_options(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Mount *m = userdata;
- const char *d = NULL;
-
- assert(bus);
- assert(reply);
- assert(m);
-
+static const char *mount_get_options(const Mount *m) {
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.options)
- d = m->parameters_proc_self_mountinfo.options;
- else if (m->from_fragment && m->parameters_fragment.options)
- d = m->parameters_fragment.options;
-
- return sd_bus_message_append(reply, "s", d);
+ return m->parameters_proc_self_mountinfo.options;
+ if (m->from_fragment && m->parameters_fragment.options)
+ return m->parameters_fragment.options;
+ return NULL;
}
-static int property_get_type(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- const char *fstype = NULL;
- Mount *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
+static const char *mount_get_fstype(const Mount *m) {
if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype)
- fstype = m->parameters_proc_self_mountinfo.fstype;
+ return m->parameters_proc_self_mountinfo.fstype;
else if (m->from_fragment && m->parameters_fragment.fstype)
- fstype = m->parameters_fragment.fstype;
-
- return sd_bus_message_append(reply, "s", fstype);
+ return m->parameters_fragment.fstype;
+ return NULL;
}
+static BUS_DEFINE_PROPERTY_GET(property_get_what, "s", Mount, mount_get_what);
+static BUS_DEFINE_PROPERTY_GET(property_get_options, "s", Mount, mount_get_options);
+static BUS_DEFINE_PROPERTY_GET(property_get_type, "s", Mount, mount_get_fstype);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResult);
const sd_bus_vtable bus_mount_vtable[] = {
SD_BUS_PROPERTY("LazyUnmount", "b", bus_property_get_bool, offsetof(Mount, lazy_unmount), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ForceUnmount", "b", bus_property_get_bool, offsetof(Mount, force_unmount), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_VTABLE("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
return sd_bus_message_close_container(reply);
}
-static int property_get_unit(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *p = userdata, *trigger;
-
- assert(bus);
- assert(reply);
- assert(p);
-
- trigger = UNIT_TRIGGER(p);
-
- return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
-}
-
const sd_bus_vtable bus_path_vtable[] = {
SD_BUS_VTABLE_START(0),
- SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Unit", "s", bus_property_get_triggered_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Paths", "a(ss)", property_get_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MakeDirectory", "b", bus_property_get_bool, offsetof(Path, make_directory), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Path, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
#include "sd-bus.h"
-#include "unit.h"
+#include "scope.h"
extern const sd_bus_vtable bus_scope_vtable[];
SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store), 0),
SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("StatusErrno", "i", NULL, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("StatusErrno", "i", bus_property_get_int, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL, offsetof(Service, usb_function_descriptors), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL, offsetof(Service, usb_function_strings), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned, offsetof(Service, n_restarts), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
+static BUS_DEFINE_PROPERTY_GET(property_get_fdname, "s", Socket, socket_fdname);
static int property_get_listen(
sd_bus *bus,
return sd_bus_message_close_container(reply);
}
-static int property_get_fdname(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Socket *s = SOCKET(userdata);
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "s", socket_fdname(s));
-}
-
const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("BindIPv6Only", "s", property_get_bind_ipv6_only, offsetof(Socket, bind_ipv6_only), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SocketProtocol", "i", bus_property_get_int, offsetof(Socket, socket_protocol), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TriggerLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Socket, trigger_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TriggerLimitBurst", "u", bus_property_get_unsigned, offsetof(Socket, trigger_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
#include "swap.h"
#include "unit.h"
-static int property_get_priority(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Swap *s = SWAP(userdata);
- int p;
-
- assert(bus);
- assert(reply);
- assert(s);
-
+static int swap_get_priority(Swap *s) {
if (s->from_proc_swaps)
- p = s->parameters_proc_swaps.priority;
- else if (s->from_fragment)
- p = s->parameters_fragment.priority;
- else
- p = -1;
-
- return sd_bus_message_append(reply, "i", p);
+ return s->parameters_proc_swaps.priority;
+ if (s->from_fragment)
+ return s->parameters_fragment.priority;
+ return -1;
}
-static int property_get_options(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Swap *s = SWAP(userdata);
- const char *options = NULL;
-
- assert(bus);
- assert(reply);
- assert(s);
-
+static const char *swap_get_options(Swap *s) {
if (s->from_fragment)
- options = s->parameters_fragment.options;
-
- return sd_bus_message_append(reply, "s", options);
+ return s->parameters_fragment.options;
+ return NULL;
}
+static BUS_DEFINE_PROPERTY_GET(property_get_priority, "i", Swap, swap_get_priority);
+static BUS_DEFINE_PROPERTY_GET(property_get_options, "s", Swap, swap_get_options);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, swap_result, SwapResult);
const sd_bus_vtable bus_swap_vtable[] = {
SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Swap, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Swap, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
- SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
BUS_EXEC_COMMAND_VTABLE("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
BUS_EXEC_COMMAND_VTABLE("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_VTABLE_END
return sd_bus_message_close_container(reply);
}
-static int property_get_unit(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata, *trigger;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- trigger = UNIT_TRIGGER(u);
-
- return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
-}
-
static int property_get_next_elapse_monotonic(
sd_bus *bus,
const char *path,
const sd_bus_vtable bus_timer_vtable[] = {
SD_BUS_VTABLE_START(0),
- SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Unit", "s", bus_property_get_triggered_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
#include "user-util.h"
#include "web-util.h"
+static bool unit_can_start_refuse_manual(Unit *u) {
+ return unit_can_start(u) && !u->refuse_manual_start;
+}
+
+static bool unit_can_stop_refuse_manual(Unit *u) {
+ return unit_can_stop(u) && !u->refuse_manual_stop;
+}
+
+static bool unit_can_isolate_refuse_manual(Unit *u) {
+ return unit_can_isolate(u) && !u->refuse_manual_start;
+}
+
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
+static BUS_DEFINE_PROPERTY_GET(property_get_description, "s", Unit, unit_description);
+static BUS_DEFINE_PROPERTY_GET2(property_get_active_state, "s", Unit, unit_active_state, unit_active_state_to_string);
+static BUS_DEFINE_PROPERTY_GET(property_get_sub_state, "s", Unit, unit_sub_state_to_string);
+static BUS_DEFINE_PROPERTY_GET2(property_get_unit_file_state, "s", Unit, unit_get_unit_file_state, unit_file_state_to_string);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_reload, "b", Unit, unit_can_reload);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_start, "b", Unit, unit_can_start_refuse_manual);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_stop, "b", Unit, unit_can_stop_refuse_manual);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_isolate, "b", Unit, unit_can_isolate_refuse_manual);
+static BUS_DEFINE_PROPERTY_GET(property_get_need_daemon_reload, "b", Unit, unit_need_daemon_reload);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_strv, "as", 0);
static int property_get_names(
sd_bus *bus,
void *userdata,
sd_bus_error *error) {
- Unit *u = userdata;
+ Set **s = userdata;
Iterator i;
const char *t;
int r;
assert(bus);
assert(reply);
- assert(u);
+ assert(s);
r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0)
return r;
- SET_FOREACH(t, u->names, i) {
+ SET_FOREACH(t, *s, i) {
r = sd_bus_message_append(reply, "s", t);
if (r < 0)
return r;
assert(u);
f = unit_following(u);
- return sd_bus_message_append(reply, "s", f ? f->id : "");
+ return sd_bus_message_append(reply, "s", f ? f->id : NULL);
}
static int property_get_dependencies(
void *userdata,
sd_bus_error *error) {
- Hashmap *h = *(Hashmap**) userdata;
+ Hashmap **h = userdata;
Iterator j;
Unit *u;
void *v;
assert(bus);
assert(reply);
+ assert(h);
r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0)
return r;
- HASHMAP_FOREACH_KEY(v, u, h, j) {
+ HASHMAP_FOREACH_KEY(v, u, *h, j) {
r = sd_bus_message_append(reply, "s", u->id);
if (r < 0)
return r;
return sd_bus_message_close_container(reply);
}
-static int property_get_obsolete_dependencies(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- /* For dependency types we don't support anymore always return an empty array */
- return sd_bus_message_append(reply, "as", 0);
-}
-
static int property_get_requires_mounts_for(
sd_bus *bus,
const char *path,
void *userdata,
sd_bus_error *error) {
- Hashmap *h = *(Hashmap**) userdata;
+ Hashmap **h = userdata;
const char *p;
Iterator j;
void *v;
assert(bus);
assert(reply);
+ assert(h);
r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0)
return r;
- HASHMAP_FOREACH_KEY(v, p, h, j) {
+ HASHMAP_FOREACH_KEY(v, p, *h, j) {
r = sd_bus_message_append(reply, "s", p);
if (r < 0)
return r;
return sd_bus_message_close_container(reply);
}
-static int property_get_description(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", unit_description(u));
-}
-
-static int property_get_active_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
-}
-
-static int property_get_sub_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
-}
-
static int property_get_unit_file_preset(
sd_bus *bus,
const char *path,
r = unit_get_unit_file_preset(u);
return sd_bus_message_append(reply, "s",
- r < 0 ? "":
+ r < 0 ? NULL:
r > 0 ? "enabled" : "disabled");
}
-static int property_get_unit_file_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
-}
-
-static int property_get_can_start(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
-}
-
-static int property_get_can_stop(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_can_stop(u) && !u->refuse_manual_stop);
-}
-
-static int property_get_can_reload(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_can_reload(u));
-}
-
-static int property_get_can_isolate(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
-}
-
static int property_get_job(
sd_bus *bus,
const char *path,
sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
- Unit *u = userdata;
+ Job **j = userdata;
assert(bus);
assert(reply);
- assert(u);
+ assert(j);
- if (!u->job)
+ if (!*j)
return sd_bus_message_append(reply, "(uo)", 0, "/");
- p = job_dbus_path(u->job);
+ p = job_dbus_path(*j);
if (!p)
return -ENOMEM;
- return sd_bus_message_append(reply, "(uo)", u->job->id, p);
-}
-
-static int property_get_need_daemon_reload(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Unit *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
+ return sd_bus_message_append(reply, "(uo)", (*j)->id, p);
}
static int property_get_conditions(
sd_bus_error *error) {
_cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
- Unit *u = userdata;
+ int *n = userdata;
assert(bus);
assert(reply);
- assert(u);
+ assert(n);
- if (u->load_error != 0)
- sd_bus_error_set_errno(&e, u->load_error);
+ if (*n != 0)
+ sd_bus_error_set_errno(&e, *n);
return sd_bus_message_append(reply, "(ss)", e.name, e.message);
}
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("Names", "as", property_get_names, offsetof(Unit, names), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("Job", "(uo)", property_get_job, offsetof(Unit, job), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0),
SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
- SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, offsetof(Unit, load_error), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED),
- /* Obsolete properties or obsolete alias names */
- SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
- SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
- SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
- SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
+ /* For dependency types we don't support anymore always return an empty array */
+ SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
+ SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN),
+ /* Obsolete alias names */
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_VTABLE_END
sd_bus_error *error) {
Unit *u = userdata;
- const char *t;
+ const char *t = NULL;
assert(bus);
assert(reply);
* other cases we report as-is. */
if (u->cgroup_path)
- t = isempty(u->cgroup_path) ? "/" : u->cgroup_path;
- else
- t = "";
+ t = empty_to_root(u->cgroup_path);
return sd_bus_message_append(reply, "s", t);
}
int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- _cleanup_(set_freep) Set *pids = NULL;
+ _cleanup_set_free_ Set *pids = NULL;
Unit *u = userdata;
pid_t pid;
int r;
int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- _cleanup_(set_freep) Set *pids = NULL;
+ _cleanup_set_free_ Set *pids = NULL;
Unit *u = userdata;
const char *path;
int r;
#include "user-util.h"
#include "unit.h"
+int bus_property_get_triggered_unit(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ Unit *u = userdata, *trigger;
+
+ assert(bus);
+ assert(reply);
+ assert(u);
+
+ trigger = UNIT_TRIGGER(u);
+
+ return sd_bus_message_append(reply, "s", trigger ? trigger->id : NULL);
+}
+
BUS_DEFINE_SET_TRANSIENT(mode_t, "u", uint32_t, mode_t, "%040o");
BUS_DEFINE_SET_TRANSIENT(unsigned, "u", uint32_t, unsigned, "%" PRIu32);
BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user, valid_user_group_name_or_id);
#include "sd-bus.h"
#include "unit.h"
+int bus_property_get_triggered_unit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
+
#define BUS_DEFINE_SET_TRANSIENT(function, bus_type, type, cast_type, fmt) \
int bus_set_transient_##function( \
Unit *u, \
#include "mkdir.h"
#include "process-util.h"
#include "selinux-access.h"
+#include "service.h"
#include "special.h"
#include "string-util.h"
#include "strv.h"
path = sd_bus_message_get_path(message);
if (object_path_startswith("/org/freedesktop/systemd1", path)) {
-
r = mac_selinux_access_check(message, verb, error);
if (r < 0)
return r;
else
manager_load_unit_from_dbus_path(m, path, NULL, &u);
}
-
if (!u)
return 0;
static int device_following_set(Unit *u, Set **_set) {
Device *d = DEVICE(u), *other;
- Set *set;
+ _cleanup_set_free_ Set *set = NULL;
int r;
assert(d);
LIST_FOREACH_AFTER(same_sysfs, other, d) {
r = set_put(set, other);
if (r < 0)
- goto fail;
+ return r;
}
LIST_FOREACH_BEFORE(same_sysfs, other, d) {
r = set_put(set, other);
if (r < 0)
- goto fail;
+ return r;
}
- *_set = set;
+ *_set = TAKE_PTR(set);
return 1;
-
-fail:
- set_free(set);
- return r;
}
static void device_shutdown(Manager *m) {
if (revents != EPOLLIN) {
static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
- if (ratelimit_test(&limit))
+ if (ratelimit_below(&limit))
log_warning("Failed to get udev event");
if (!(revents & EPOLLIN))
return 0;
Copyright 2010 Lennart Poettering
***/
+#include "unit.h"
+
typedef struct Device Device;
typedef enum DeviceFound {
int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now);
bool device_shall_be_bound_by(Unit *device, Unit *u);
+
+DEFINE_CAST(DEVICE, Device);
#include "io-util.h"
#include "parse-util.h"
#include "random-util.h"
+#include "socket-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "user-util.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "smack-util.h"
+#include "socket-util.h"
#include "special.h"
#include "stat-util.h"
#include "string-table.h"
if (!barrier_place_and_sync(&barrier))
log_error("PAM initialization failed");
- strv_free(*env);
- *env = e;
-
- return 0;
+ return strv_free_and_replace(*env, e);
fail:
if (pam_code != PAM_SUCCESS) {
}
} else {
r = mkdir_label(p, context->directories[type].mode);
- if (r == -EEXIST)
- continue;
- if (r < 0)
+ if (r < 0 && r != -EEXIST)
goto fail;
+ if (r == -EEXIST && !context->dynamic_user)
+ continue;
}
/* Don't change the owner of the configuration directory, as in the common case it is not written to by
#endif
uid_t uid = UID_INVALID;
gid_t gid = GID_INVALID;
- int i, r, ngids = 0;
+ int r, ngids = 0;
size_t n_fds;
ExecDirectoryType dt;
int secure_bits;
}
if (context->oom_score_adjust_set) {
- char t[DECIMAL_STR_MAX(context->oom_score_adjust)];
-
- /* When we can't make this change due to EPERM, then
- * let's silently skip over it. User namespaces
- * prohibit write access to this file, and we
- * shouldn't trip up over that. */
-
- sprintf(t, "%i", context->oom_score_adjust);
- r = write_string_file("/proc/self/oom_score_adj", t, 0);
+ /* When we can't make this change due to EPERM, then let's silently skip over it. User namespaces
+ * prohibit write access to this file, and we shouldn't trip up over that. */
+ r = set_oom_score_adjust(context->oom_score_adjust);
if (IN_SET(r, -EPERM, -EACCES))
log_unit_debug_errno(unit, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
else if (r < 0) {
if (needs_sandboxing) {
uint64_t bset;
+ int which_failed;
- for (i = 0; i < _RLIMIT_MAX; i++) {
-
- if (!context->rlimit[i])
- continue;
-
- r = setrlimit_closest(i, context->rlimit[i]);
- if (r < 0) {
- *exit_status = EXIT_LIMITS;
- return log_unit_error_errno(unit, r, "Failed to adjust resource limit %s: %m", rlimit_to_string(i));
- }
+ r = setrlimit_closest_all((const struct rlimit* const *) context->rlimit, &which_failed);
+ if (r < 0) {
+ *exit_status = EXIT_LIMITS;
+ return log_unit_error_errno(unit, r, "Failed to adjust resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed));
}
/* Set the RTPRIO resource limit to 0, but only if nothing else was explicitly requested. */
return log_oom();
}
- strv_free(accum_env);
- accum_env = ee;
+ strv_free_and_replace(accum_env, ee);
}
final_argv = replace_env_argv(argv, accum_env);
c->pass_environment = strv_free(c->pass_environment);
c->unset_environment = strv_free(c->unset_environment);
- for (l = 0; l < ELEMENTSOF(c->rlimit); l++)
- c->rlimit[l] = mfree(c->rlimit[l]);
+ rlimit_free_all(c->rlimit);
for (l = 0; l < 3; l++) {
c->stdio_fdname[l] = mfree(c->stdio_fdname[l]);
for (i = 0; i < RLIM_NLIMITS; i++)
if (c->rlimit[i]) {
- fprintf(f, "%s%s: " RLIM_FMT "\n",
+ fprintf(f, "Limit%s%s: " RLIM_FMT "\n",
prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
- fprintf(f, "%s%sSoft: " RLIM_FMT "\n",
+ fprintf(f, "Limit%s%sSoft: " RLIM_FMT "\n",
prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur);
}
free(c->path);
c->path = p;
- strv_free(c->argv);
- c->argv = l;
-
- return 0;
+ return strv_free_and_replace(c->argv, l);
}
int exec_command_append(ExecCommand *c, const char *path, ...) {
Copyright 2016 Daniel Mack
***/
+#include "conf-parser.h"
#include "in-addr-util.h"
#include "list.h"
LIST_FIELDS(IPAddressAccessItem, items);
};
-int config_parse_ip_address_access(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_ip_address_access);
IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first);
j->manager = unit->manager;
j->unit = unit;
j->type = _JOB_TYPE_INVALID;
+ j->reloaded = false;
return j;
}
return j;
}
-void job_free(Job *j) {
+void job_unlink(Job *j) {
assert(j);
assert(!j->installed);
assert(!j->transaction_prev);
assert(!j->subject_list);
assert(!j->object_list);
- if (j->in_run_queue)
+ if (j->in_run_queue) {
LIST_REMOVE(run_queue, j->manager->run_queue, j);
+ j->in_run_queue = false;
+ }
- if (j->in_dbus_queue)
+ if (j->in_dbus_queue) {
LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
+ j->in_dbus_queue = false;
+ }
- if (j->in_gc_queue)
+ if (j->in_gc_queue) {
LIST_REMOVE(gc_queue, j->manager->gc_job_queue, j);
+ j->in_gc_queue = false;
+ }
- sd_event_source_unref(j->timer_event_source);
+ j->timer_event_source = sd_event_source_unref(j->timer_event_source);
+}
+
+void job_free(Job *j) {
+ assert(j);
+ assert(!j->installed);
+ assert(!j->transaction_prev);
+ assert(!j->transaction_next);
+ assert(!j->subject_list);
+ assert(!j->object_list);
+
+ job_unlink(j);
sd_bus_track_unref(j->bus_track);
strv_free(j->deserialized_clients);
*pj = j;
j->installed = true;
+ j->reloaded = true;
if (j->state == JOB_RUNNING)
j->unit->manager->n_running_jobs++;
}
}
+static int job_save_pending_finished_job(Job *j) {
+ int r;
+
+ assert(j);
+
+ r = set_ensure_allocated(&j->manager->pending_finished_jobs, NULL);
+ if (r < 0)
+ return r;
+
+ job_unlink(j);
+ return set_put(j->manager->pending_finished_jobs, j);
+}
+
int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already) {
Unit *u;
Unit *other;
j->manager->n_failed_jobs++;
job_uninstall(j);
- job_free(j);
+ /* Keep jobs started before the reload to send singal later, free all others */
+ if (!MANAGER_IS_RELOADING(j->manager) ||
+ !j->reloaded ||
+ job_save_pending_finished_job(j) < 0)
+ job_free(j);
/* Fail depending jobs on failure */
if (result != JOB_DONE && recursive) {
bool irreversible:1;
bool in_gc_queue:1;
bool ref_by_private_bus:1;
+ bool reloaded:1;
};
Job* job_new(Unit *unit, JobType type);
Job* job_new_raw(Unit *unit);
+void job_unlink(Job *job);
void job_free(Job *job);
Job* job_install(Job *j);
int job_install_deserialized(Job *j);
#include "conf-parser.h"
#include "load-fragment.h"
#include "missing.h"
+
+#include "all-units.h"
%}
struct ConfigPerfItem;
%null_strings
$1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
-$1.LimitCPU, config_parse_limit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
-$1.LimitFSIZE, config_parse_limit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
-$1.LimitDATA, config_parse_limit, RLIMIT_DATA, offsetof($1, exec_context.rlimit)
-$1.LimitSTACK, config_parse_limit, RLIMIT_STACK, offsetof($1, exec_context.rlimit)
-$1.LimitCORE, config_parse_limit, RLIMIT_CORE, offsetof($1, exec_context.rlimit)
-$1.LimitRSS, config_parse_limit, RLIMIT_RSS, offsetof($1, exec_context.rlimit)
-$1.LimitNOFILE, config_parse_limit, RLIMIT_NOFILE, offsetof($1, exec_context.rlimit)
-$1.LimitAS, config_parse_limit, RLIMIT_AS, offsetof($1, exec_context.rlimit)
-$1.LimitNPROC, config_parse_limit, RLIMIT_NPROC, offsetof($1, exec_context.rlimit)
-$1.LimitMEMLOCK, config_parse_limit, RLIMIT_MEMLOCK, offsetof($1, exec_context.rlimit)
-$1.LimitLOCKS, config_parse_limit, RLIMIT_LOCKS, offsetof($1, exec_context.rlimit)
-$1.LimitSIGPENDING, config_parse_limit, RLIMIT_SIGPENDING, offsetof($1, exec_context.rlimit)
-$1.LimitMSGQUEUE, config_parse_limit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit)
-$1.LimitNICE, config_parse_limit, RLIMIT_NICE, offsetof($1, exec_context.rlimit)
-$1.LimitRTPRIO, config_parse_limit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit)
-$1.LimitRTTIME, config_parse_limit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
+$1.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
+$1.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit)
+$1.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof($1, exec_context.rlimit)
+$1.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof($1, exec_context.rlimit)
+$1.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof($1, exec_context.rlimit)
+$1.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof($1, exec_context.rlimit)
+$1.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof($1, exec_context.rlimit)
+$1.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof($1, exec_context.rlimit)
+$1.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof($1, exec_context.rlimit)
+$1.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof($1, exec_context.rlimit)
+$1.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof($1, exec_context.rlimit)
+$1.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof($1, exec_context.rlimit)
+$1.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit)
+$1.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof($1, exec_context.rlimit)
+$1.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit)
+$1.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit)
$1.ReadWriteDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_paths)
$1.ReadOnlyDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_paths)
$1.InaccessibleDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_paths)
#include "af-list.h"
#include "alloc-util.h"
+#include "all-units.h"
#include "bus-error.h"
#include "bus-internal.h"
#include "bus-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
-#include "rlimit-util.h"
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
#include "strv.h"
#include "unit-name.h"
#include "unit-printf.h"
-#include "unit.h"
#include "user-util.h"
#include "utf8.h"
#include "web-util.h"
r = unit_name_printf(u, word, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
continue;
}
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve unit specifiers in \"%s\"%s: %m",
+ "Failed to resolve unit specifiers in '%s'%s: %m",
rvalue, fatal ? "" : ", ignoring");
return fatal ? -ENOEXEC : 0;
}
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve unit specifiers on \"%s\", ignoring: %m", word);
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
return 0;
}
p->type = ltype;
r = unit_full_printf(UNIT(s), rvalue, &p->path);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
p->type = SOCKET_SOCKET;
r = unit_full_printf(UNIT(s), rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
r = socket_address_parse_netlink(&p->address, k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k);
return 0;
}
p->type = SOCKET_SOCKET;
r = unit_full_printf(UNIT(s), rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,"Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
r = socket_address_parse_and_warn(&p->address, k);
if (r < 0) {
if (r != -EAFNOSUPPORT)
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k);
return 0;
}
r = socket_protocol_from_name(rvalue);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid socket protocol, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid socket protocol '%s', ignoring: %m", rvalue);
return 0;
} else if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Socket protocol not supported, ignoring: %s", rvalue);
if (r == -ERANGE)
log_syntax(unit, LOG_ERR, filename, line, r, "Nice priority out of range, ignoring: %s", rvalue);
else
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority, ignoring: %s", rvalue);
-
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority '%s', ignoring: %m", rvalue);
return 0;
}
return 0;
}
-int config_parse_exec_oom_score_adjust(const char* unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_exec_oom_score_adjust(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
ExecContext *c = data;
int oa, r;
assert(rvalue);
assert(data);
- r = safe_atoi(rvalue, &oa);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
+ if (isempty(rvalue)) {
+ c->oom_score_adjust_set = false;
return 0;
}
- if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "OOM score adjust value out of range, ignoring: %s", rvalue);
+ r = parse_oom_score_adjust(rvalue, &oa);
+ if (r < 0) {
+ if (r == -ERANGE)
+ log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue);
+ else
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value '%s', ignoring: %m", rvalue);
return 0;
}
r = unit_full_printf(u, f, &path);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve unit specifiers on %s%s: %m",
+ "Failed to resolve unit specifiers in '%s'%s: %m",
f, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
if (isempty(path)) {
/* First word is either "-" or "@" with no command. */
log_syntax(unit, LOG_ERR, filename, line, 0,
- "Empty path in command line%s: \"%s\"",
+ "Empty path in command line%s: '%s'",
ignore ? ", ignoring" : "", rvalue);
return ignore ? 0 : -ENOEXEC;
}
r = unit_full_printf(u, word, &resolved);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve unit specifiers on %s%s: %m",
+ "Failed to resolve unit specifiers in %s%s: %m",
word, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
void *userdata) {
Socket *s = data;
- char *n;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- if (rvalue[0] && !streq(rvalue, "*")) {
- if (!ifname_valid(rvalue)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is invalid, ignoring: %s", rvalue);
- return 0;
- }
+ if (isempty(rvalue) || streq(rvalue, "*")) {
+ s->bind_to_device = mfree(s->bind_to_device);
+ return 0;
+ }
- n = strdup(rvalue);
- if (!n)
- return log_oom();
- } else
- n = NULL;
+ if (!ifname_valid(rvalue)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid interface name, ignoring: %s", rvalue);
+ return 0;
+ }
- free(s->bind_to_device);
- s->bind_to_device = n;
+ free_and_strdup(&s->bind_to_device, rvalue);
return 0;
}
r = unit_full_printf(u, n, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s: %m", n);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n);
if (isempty(resolved))
resolved = mfree(resolved);
r = unit_full_printf(u, n, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s: %m", n);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n);
if (!path_is_absolute(resolved)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "file: requires an absolute path name: %s", resolved);
r = cunescape(rvalue, 0, &unescaped);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode C escaped text: %s", rvalue);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode C escaped text '%s': %m", rvalue);
r = unit_full_printf(u, unescaped, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers: %s", unescaped);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", unescaped);
sz = strlen(resolved);
if (c->stdin_data_size + sz + 1 < c->stdin_data_size || /* check for overflow */
if (n) {
r = unit_full_printf(u, n, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s: %m", n);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n);
if (isempty(resolved))
resolved = mfree(resolved);
r = unit_full_printf(u, n, &resolved);
if (r < 0)
- return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s: %m", n);
+ return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n);
if (!path_is_absolute(resolved)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "file: requires an absolute path name: %s", resolved);
r = safe_atoi(rvalue, &i);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU scheduling priority, ignoring: %s", rvalue);
return 0;
}
}
r = secure_bits_from_string(rvalue);
- if (r == -ENOMEM)
- return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
- "Invalid syntax, ignoring: %s", rvalue);
+ "Failed to parse secure bits, ignoring: %s", rvalue);
return 0;
}
/* else "AmbientCapabilities" initialized to all bits off */
r = capability_set_from_string(rvalue, &sum);
- if (r == -ENOMEM)
- return log_oom();
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse word: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= specifier '%s', ignoring: %m", lvalue, rvalue);
return 0;
}
return 0;
}
-int config_parse_limit(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- struct rlimit **rl = data, d = {};
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = rlimit_parse(ltype, rvalue, &d);
- if (r == -EILSEQ) {
- log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue);
- return 0;
- }
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
-
- if (rl[ltype])
- *rl[ltype] = d;
- else {
- rl[ltype] = newdup(struct rlimit, &d, 1);
- if (!rl[ltype])
- return log_oom();
- }
-
- return 0;
-}
-
#if HAVE_SYSV_COMPAT
int config_parse_sysv_priority(const char *unit,
const char *filename,
assert(data);
r = safe_atoi(rvalue, &i);
- if (r < 0 || i < 0) {
+ if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse SysV start priority, ignoring: %s", rvalue);
return 0;
}
+ if (i < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid SysV start priority, ignoring: %s", rvalue);
+ return 0;
+ }
*priority = (int) i;
return 0;
r = mount_propagation_flags_from_string(rvalue, &c->mount_flags);
if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse mount flag %s, ignoring: %m", rvalue);
return 0;
}
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers%s: %m",
- ignore ? ", ignoring" : "");
+ "Failed to resolve unit specifiers in '%s'%s: %m",
+ rvalue, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
- free(c->selinux_context);
- c->selinux_context = k;
+ free_and_replace(c->selinux_context, k);
c->selinux_context_ignore = ignore;
return 0;
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers%s: %m",
- ignore ? ", ignoring" : "");
+ "Failed to resolve unit specifiers in '%s'%s: %m",
+ rvalue, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
- free(c->apparmor_profile);
- c->apparmor_profile = k;
+ free_and_replace(c->apparmor_profile, k);
c->apparmor_profile_ignore = ignore;
return 0;
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers%s: %m",
- ignore ? ", ignoring" : "");
+ "Failed to resolve unit specifiers in '%s'%s: %m",
+ rvalue, ignore ? ", ignoring" : "");
return ignore ? 0 : -ENOEXEC;
}
- free(c->smack_process_label);
- c->smack_process_label = k;
+ free_and_replace(c->smack_process_label, k);
c->smack_process_label_ignore = ignore;
return 0;
usec_t usec = 0;
TimerValue *v;
TimerBase b;
- CalendarSpec *c = NULL;
+ _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
Unit *u = userdata;
_cleanup_free_ char *k = NULL;
int r;
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse calendar specification, ignoring: %s", k);
return 0;
}
- } else {
+ } else
if (parse_sec(k, &usec) < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", k);
return 0;
}
- }
v = new0(TimerValue, 1);
- if (!v) {
- calendar_spec_free(c);
+ if (!v)
return log_oom();
- }
v->base = b;
v->value = usec;
- v->calendar_spec = c;
+ v->calendar_spec = TAKE_PTR(c);
LIST_PREPEND(value, t->values, v);
r = unit_name_printf(u, rvalue, &p);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
r = unit_full_printf(UNIT(p), rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
+ path_kill_slashes(k);
+
if (!path_is_absolute(k)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Path is not absolute, ignoring: %s", k);
return 0;
return log_oom();
s->unit = UNIT(p);
- s->path = path_kill_slashes(k);
- k = NULL;
+ s->path = TAKE_PTR(k);
s->type = b;
s->inotify_fd = -1;
r = unit_name_printf(UNIT(s), rvalue, &p);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
return -ENOEXEC;
}
r = unit_full_printf(UNIT(s), rvalue, &p);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
r = unit_name_printf(UNIT(s), word, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
continue;
}
r = unit_full_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
if (!service_name_is_valid(k)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name %s, ignoring.", k);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name, ignoring: %s", k);
return 0;
}
void *data,
void *userdata) {
- char **user = data, *n;
+ _cleanup_free_ char *k = NULL;
+ char **user = data;
Unit *u = userdata;
int r;
assert(rvalue);
assert(u);
- if (isempty(rvalue))
- n = NULL;
- else {
- _cleanup_free_ char *k = NULL;
-
- r = unit_full_printf(u, rvalue, &k);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
- return -ENOEXEC;
- }
-
- if (!valid_user_group_name_or_id(k)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
- return -ENOEXEC;
- }
+ if (isempty(rvalue)) {
+ *user = mfree(*user);
+ return 0;
+ }
- n = TAKE_PTR(k);
+ r = unit_full_printf(u, rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
+ return -ENOEXEC;
}
- free(*user);
- *user = n;
+ if (!valid_user_group_name_or_id(k)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
+ return -ENOEXEC;
+ }
- return 0;
+ return free_and_replace(*user, k);
}
int config_parse_user_group_strv(
char ***users = data;
Unit *u = userdata;
- const char *p;
+ const char *p = rvalue;
int r;
assert(filename);
return 0;
}
- p = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
r = unit_full_printf(u, rvalue, &n);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers, ignoring: %s", word);
+ "Failed to resolve unit specifiers in %s, ignoring: %m", word);
continue;
}
} else
void *data,
void *userdata) {
- const char *whole_rvalue = rvalue;
_cleanup_strv_free_ char **n = NULL;
size_t nlen = 0, nbufsize = 0;
char*** passenv = data;
+ const char *p = rvalue;
Unit *u = userdata;
int r;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
- r = extract_first_word(&rvalue, &word, NULL, EXTRACT_QUOTES);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Trailing garbage in %s, ignoring: %s", lvalue, whole_rvalue);
+ "Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
break;
}
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers, ignoring: %s", word);
+ "Failed to resolve specifiers in %s, ignoring: %m", word);
continue;
}
} else
void *userdata) {
_cleanup_strv_free_ char **n = NULL;
- const char *whole_rvalue = rvalue;
size_t nlen = 0, nbufsize = 0;
char*** unsetenv = data;
+ const char *p = rvalue;
Unit *u = userdata;
int r;
for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
- r = extract_first_word(&rvalue, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_QUOTES);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_QUOTES);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Trailing garbage in %s, ignoring: %s", lvalue, whole_rvalue);
+ "Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
break;
}
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers, ignoring: %s", word);
+ "Failed to resolve unit specifiers in %s, ignoring: %m", word);
continue;
}
} else
ExecContext *c = data;
Unit *u = userdata;
- const char *p;
+ const char *p = rvalue;
int r;
assert(filename);
return 0;
}
- for (p = rvalue;; ) {
+ for (;;) {
_cleanup_free_ char *word = NULL, *k = NULL;
struct iovec *t;
const char *eq;
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_QUOTES);
if (r == 0)
- break;
+ return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
r = unit_full_printf(u, word, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring field: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word);
continue;
}
eq = strchr(k, '=');
if (!eq) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Log field lacks '=' character, ignoring field: %s", k);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Log field lacks '=' character, ignoring: %s", k);
continue;
}
if (!journal_field_valid(k, eq-k, false)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Log field name is invalid, ignoring field: %s", k);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Log field name is invalid, ignoring: %s", k);
continue;
}
k = NULL;
}
-
- return 0;
}
int config_parse_ip_tos(const char *unit,
r = unit_full_printf(u, rvalue, &p);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
r = unit_full_printf(u, rvalue, &s);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0;
}
void *data,
void *userdata) {
+ const char *p = rvalue;
Unit *u = userdata;
- const char *p;
int r;
assert(filename);
assert(rvalue);
assert(data);
- for (p = rvalue;; ) {
+ for (;;) {
_cleanup_free_ char *word = NULL, *resolved = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
r = unit_full_printf(u, word, &resolved);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit name \"%s\", ignoring: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
continue;
}
r = unit_require_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount \"%s\", ignoring: %m", resolved);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount '%s', ignoring: %m", resolved);
continue;
}
}
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
- break;
+ return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
- break;
+ return 0;
}
r = parse_syscall_and_errno(word, &name, &num);
if (r < 0)
return r;
}
-
- return 0;
}
int config_parse_syscall_archs(
void *data,
void *userdata) {
+ const char *p = rvalue;
Set **archs = data;
- const char *p;
int r;
if (isempty(rvalue)) {
if (r < 0)
return log_oom();
- for (p = rvalue;;) {
+ for (;;) {
_cleanup_free_ char *word = NULL;
uint32_t a;
}
af = af_from_name(word);
- if (af <= 0) {
+ if (af <= 0) {
log_syntax(unit, LOG_ERR, filename, line, 0,
- "Failed to parse address family \"%s\", ignoring: %m", word);
+ "Failed to parse address family, ignoring: %s", word);
continue;
}
void *data,
void *userdata) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *k = NULL;
Unit *u = userdata, *slice = NULL;
int r;
r = unit_name_printf(u, rvalue, &k);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0;
}
- r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
+ r = manager_load_unit(u->manager, k, NULL, &error, &slice);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load slice unit %s. Ignoring.", k);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load slice unit %s, ignoring: %s", k, bus_error_message(&error, r));
return 0;
}
r = unit_set_slice(u, slice);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to assign slice %s to unit %s. Ignoring.", slice->id, u->id);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to assign slice %s to unit %s, ignoring: %m", slice->id, u->id);
return 0;
}
r = cg_weight_parse(rvalue, weight);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "CPU weight '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU weight '%s', ignoring: %m", rvalue);
return 0;
}
r = cg_cpu_shares_parse(rvalue, shares);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "CPU shares '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU shares '%s', ignoring: %m", rvalue);
return 0;
}
r = parse_percent_unbounded(rvalue);
if (r <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "CPU quota '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU quota '%s', ignoring.", rvalue);
return 0;
}
if (r < 0) {
r = parse_size(rvalue, 1024, &bytes);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Memory limit '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid memory limit '%s', ignoring: %m", rvalue);
return 0;
}
} else
if (bytes >= UINT64_MAX ||
(bytes <= 0 && !streq(lvalue, "MemorySwapMax"))) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue);
return 0;
}
}
if (r < 0) {
r = safe_atou64(rvalue, &v);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Maximum tasks value '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid maximum tasks value '%s', ignoring: %m", rvalue);
return 0;
}
} else
v = system_tasks_max_scale(r, 100U);
if (v <= 0 || v >= UINT64_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue);
return 0;
}
cc = cgroup_controller_from_string(word);
if (cc < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Invalid controller name '%s', ignoring", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid controller name '%s', ignoring", word);
continue;
}
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL, *t = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupContext *c = data;
CGroupDeviceAllow *a;
- const char *m = NULL;
- size_t n;
+ const char *p = rvalue;
int r;
if (isempty(rvalue)) {
return 0;
}
- r = unit_full_printf(userdata, rvalue, &t);
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to resolve specifiers in %s, ignoring: %m",
- rvalue);
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device path and rights from '%s', ignoring.", rvalue);
return 0;
}
- n = strcspn(t, WHITESPACE);
-
- path = strndup(t, n);
- if (!path)
- return log_oom();
-
- if (!is_deviceallow_pattern(path) &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
return 0;
}
- m = t + n + strspn(t + n, WHITESPACE);
- if (isempty(m))
- m = "rwm";
+ if (!is_deviceallow_pattern(resolved) &&
+ !path_startswith(resolved, "/run/systemd/inaccessible/")) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s', ignoring.", resolved);
+ return 0;
+ }
- if (!in_charset(m, "rwm")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device rights '%s'. Ignoring.", m);
+ if (!isempty(p) && !in_charset(p, "rwm")) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device rights '%s', ignoring.", p);
return 0;
}
if (!a)
return log_oom();
- a->path = TAKE_PTR(path);
- a->r = !!strchr(m, 'r');
- a->w = !!strchr(m, 'w');
- a->m = !!strchr(m, 'm');
+ a->path = TAKE_PTR(resolved);
+ a->r = isempty(p) || !!strchr(p, 'r');
+ a->w = isempty(p) || !!strchr(p, 'w');
+ a->m = isempty(p) || !!strchr(p, 'm');
LIST_PREPEND(device_allow, c->device_allow, a);
return 0;
r = cg_weight_parse(rvalue, weight);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid IO weight '%s', ignoring.", rvalue);
return 0;
}
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupIODeviceWeight *w;
CGroupContext *c = data;
- const char *weight;
+ const char *p = rvalue;
uint64_t u;
- size_t n;
int r;
assert(filename);
return 0;
}
- n = strcspn(rvalue, WHITESPACE);
- weight = rvalue + n;
- weight += strspn(weight, WHITESPACE);
-
- if (isempty(weight)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Expected block device and device weight. Ignoring.");
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0 || isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device path and weight from '%s', ignoring.", rvalue);
return 0;
}
- path = strndup(rvalue, n);
- if (!path)
- return log_oom();
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
+ return 0;
+ }
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ if (!path_startswith(resolved, "/dev") &&
+ !path_startswith(resolved, "/run/systemd/inaccessible/")) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s', ignoring.", resolved);
return 0;
}
- r = cg_weight_parse(weight, &u);
+ r = cg_weight_parse(p, &u);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid. Ignoring.", weight);
+ log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid, ignoring: %m", p);
return 0;
}
if (!w)
return log_oom();
- w->path = TAKE_PTR(path);
-
+ w->path = TAKE_PTR(resolved);
w->weight = u;
LIST_PREPEND(device_weights, c->io_device_weights, w);
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupIODeviceLimit *l = NULL, *t;
CGroupContext *c = data;
CGroupIOLimitType type;
- const char *limit;
+ const char *p = rvalue;
uint64_t num;
- size_t n;
int r;
assert(filename);
return 0;
}
- n = strcspn(rvalue, WHITESPACE);
- limit = rvalue + n;
- limit += strspn(limit, WHITESPACE);
-
- if (!*limit) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Expected space separated pair of device node and bandwidth. Ignoring.");
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0 || isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device node and bandwidth from '%s', ignoring.", rvalue);
return 0;
}
- path = strndup(rvalue, n);
- if (!path)
- return log_oom();
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
+ return 0;
+ }
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ if (!path_startswith(resolved, "/dev") &&
+ !path_startswith(resolved, "/run/systemd/inaccessible/")) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s', ignoring.", resolved);
return 0;
}
- if (streq("infinity", limit)) {
+ if (streq("infinity", p)) {
num = CGROUP_LIMIT_MAX;
} else {
- r = parse_size(limit, 1000, &num);
+ r = parse_size(p, 1000, &num);
if (r < 0 || num <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "IO Limit '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid IO limit '%s', ignoring.", p);
return 0;
}
}
LIST_FOREACH(device_limits, t, c->io_device_limits) {
- if (path_equal(path, t->path)) {
+ if (path_equal(resolved, t->path)) {
l = t;
break;
}
if (!l)
return log_oom();
- l->path = TAKE_PTR(path);
+ l->path = TAKE_PTR(resolved);
for (ttype = 0; ttype < _CGROUP_IO_LIMIT_TYPE_MAX; ttype++)
l->limits[ttype] = cgroup_io_limit_defaults[ttype];
r = cg_blkio_weight_parse(rvalue, weight);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid block IO weight '%s', ignoring: %m", rvalue);
return 0;
}
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupBlockIODeviceWeight *w;
CGroupContext *c = data;
- const char *weight;
+ const char *p = rvalue;
uint64_t u;
- size_t n;
int r;
assert(filename);
return 0;
}
- n = strcspn(rvalue, WHITESPACE);
- weight = rvalue + n;
- weight += strspn(weight, WHITESPACE);
-
- if (isempty(weight)) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Expected block device and device weight. Ignoring.");
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0 || isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device node and weight from '%s', ignoring.", rvalue);
return 0;
}
- path = strndup(rvalue, n);
- if (!path)
- return log_oom();
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
+ return 0;
+ }
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ if (!path_startswith(resolved, "/dev") &&
+ !path_startswith(resolved, "/run/systemd/inaccessible/")) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", resolved);
return 0;
}
- r = cg_blkio_weight_parse(weight, &u);
+ r = cg_blkio_weight_parse(p, &u);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Block IO weight '%s' invalid. Ignoring.", weight);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid block IO weight '%s', ignoring: %m", p);
return 0;
}
if (!w)
return log_oom();
- w->path = TAKE_PTR(path);
-
+ w->path = TAKE_PTR(resolved);
w->weight = u;
LIST_PREPEND(device_weights, c->blockio_device_weights, w);
void *data,
void *userdata) {
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path = NULL, *resolved = NULL;
CGroupBlockIODeviceBandwidth *b = NULL, *t;
CGroupContext *c = data;
- const char *bandwidth;
+ const char *p = rvalue;
uint64_t bytes;
bool read;
- size_t n;
int r;
assert(filename);
return 0;
}
- n = strcspn(rvalue, WHITESPACE);
- bandwidth = rvalue + n;
- bandwidth += strspn(bandwidth, WHITESPACE);
-
- if (!*bandwidth) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Expected space separated pair of device node and bandwidth. Ignoring.");
+ r = extract_first_word(&p, &path, NULL, EXTRACT_QUOTES);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r == 0 || isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to extract device node and bandwidth from '%s', ignoring.", rvalue);
return 0;
}
- path = strndup(rvalue, n);
- if (!path)
- return log_oom();
+ r = unit_full_printf(userdata, path, &resolved);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
+ return 0;
+ }
- if (!path_startswith(path, "/dev") &&
- !path_startswith(path, "/run/systemd/inaccessible/")) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
+ if (!path_startswith(resolved, "/dev") &&
+ !path_startswith(resolved, "/run/systemd/inaccessible/")) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s', ignoring.", resolved);
return 0;
}
- r = parse_size(bandwidth, 1000, &bytes);
+ r = parse_size(p, 1000, &bytes);
if (r < 0 || bytes <= 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid Block IO Bandwidth '%s', ignoring.", p);
return 0;
}
LIST_FOREACH(device_bandwidths, t, c->blockio_device_bandwidths) {
- if (path_equal(path, t->path)) {
+ if (path_equal(resolved, t->path)) {
b = t;
break;
}
if (!b)
return log_oom();
- b->path = TAKE_PTR(path);
+ b->path = TAKE_PTR(resolved);
b->rbps = CGROUP_LIMIT_MAX;
b->wbps = CGROUP_LIMIT_MAX;
r = unit_full_printf(u, word, &k);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolve specifiers in \"%s\", ignoring: %m", word);
+ "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word);
+ continue;
+ }
+
+ if (!path_is_normalized(k)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is not normalized, ignoring assignment: %s", lvalue, rvalue);
+ continue;
+ }
+
+ if (path_is_absolute(k)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "%s= path is absolute, ignoring assignment: %s", lvalue, rvalue);
continue;
}
- if (!path_is_normalized(k) || path_is_absolute(k)) {
+ if (path_startswith(k, "private")) {
log_syntax(unit, LOG_ERR, filename, line, 0,
- "%s= path is not valid, ignoring assignment: %s", lvalue, rvalue);
+ "%s= path can't be 'private', ingoring assignment: %s", lvalue, rvalue);
continue;
}
return log_oom();
r = set_put(*set, INT_TO_PTR(val));
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Unable to store: %s", word);
- return r;
- }
+ if (r < 0)
+ return log_oom();
}
if (!isempty(state))
log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
Unit *u = userdata;
char*** sv = data;
- const char *cur;
+ const char *p = rvalue;
int r;
assert(filename);
return 0;
}
- cur = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL, *resolved = NULL, *joined = NULL;
const char *w;
bool ignore_enoent = false, shall_prefix = false;
- r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
break;
if (r == -ENOMEM)
r = unit_full_printf(u, w, &resolved);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers in %s: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", w);
continue;
}
Unit *u = userdata;
ExecContext *c = data;
- const char *cur;
+ const char *p = rvalue;
int r;
assert(filename);
return 0;
}
- cur = rvalue;
for (;;) {
_cleanup_free_ char *word = NULL, *path = NULL, *resolved = NULL;
const char *w;
- r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r == 0)
- break;
+ return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
w = word;
r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", word);
+ continue;
+ }
+ if (r == 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring: %s", word);
+ continue;
+ }
r = unit_full_printf(u, path, &resolved);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers in %s, ignoring: %m", word);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", path);
continue;
}
continue;
}
}
-
- return 0;
}
int config_parse_bind_paths(
r = unit_full_printf(u, source, &sresolved);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to resolved specifiers in \"%s\", ignoring: %m", source);
+ "Failed to resolved unit specifiers in \"%s\", ignoring: %m", source);
return 0;
}
void *userdata) {
ExecContext *c = data;
- int k;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- k = parse_boolean(rvalue);
- if (k < 0) {
- log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
+ r = parse_boolean(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse boolean value, ignoring: %s", rvalue);
return 0;
}
- c->no_new_privileges = k;
+ c->no_new_privileges = r;
return 0;
}
assert(rvalue);
assert(data);
- /* Our enum shall be a superset of booleans, hence first try
- * to parse as boolean, and then as enum */
-
s = parse_protect_system_or_bool(rvalue);
if (s < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue);
{ config_parse_log_level, "LEVEL" },
{ config_parse_exec_secure_bits, "SECUREBITS" },
{ config_parse_capability_set, "BOUNDINGSET" },
- { config_parse_limit, "LIMIT" },
+ { config_parse_rlimit, "LIMIT" },
{ config_parse_unit_deps, "UNIT [...]" },
{ config_parse_exec, "PATH [ARGUMENT [...]]" },
{ config_parse_service_type, "SERVICETYPE" },
Copyright 2010 Lennart Poettering
***/
+#include "conf-parser.h"
#include "unit.h"
/* Read service data from .desktop file style configuration fragments */
void unit_dump_config_items(FILE *f);
-int config_parse_unit_deps(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_obsolete_unit_deps(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_string_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_strv_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_path_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_path_strv_printf(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_documentation(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_listen(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_protocol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_bind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_nice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_oom_score_adjust(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_timeout(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_restart(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_bindtodevice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_output(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_input(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_input_text(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_input_data(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_io_class(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_io_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_sched_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_sched_prio(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_cpu_affinity(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_secure_bits(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_capability_set(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_sysv_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_kill_signal(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_mount_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_timer(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_trigger_unit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_path_spec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_socket_service(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_service_sockets(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_env_file(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ip_tos(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_path(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_string(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_condition_null(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_kill_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_notify_access(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_emergency_action(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_requires_mounts_for(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_filter(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_archs(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_errno(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_pass_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unset_environ(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_unit_slice(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_cpu_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_cpu_shares(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_memory_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_delegate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_io_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_io_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_io_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_blockio_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_blockio_bandwidth(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_netclass(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_job_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_job_mode_isolate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_selinux_context(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_apparmor_profile(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_smack_process_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_families(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_runtime_preserve_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_directories(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_set_status(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_namespace_path_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_temporary_filesystems(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_no_new_privileges(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_cpu_quota(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_protect_home(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_protect_system(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bus_name(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_utmp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_working_directory(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_fdname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_sec_fix_0(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_user_group(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_user_group_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_restrict_namespaces(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bind_paths(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_exec_keyring_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_job_timeout_sec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_job_running_timeout_sec(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_log_extra_fields(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_collect_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_deps);
+CONFIG_PARSER_PROTOTYPE(config_parse_obsolete_unit_deps);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_string_printf);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_strv_printf);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_printf);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_strv_printf);
+CONFIG_PARSER_PROTOTYPE(config_parse_documentation);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_listen);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_protocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_bind);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_nice);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_oom_score_adjust);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec);
+CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout);
+CONFIG_PARSER_PROTOTYPE(config_parse_service_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_service_restart);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_bindtodevice);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_output);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_input);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_input_text);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_input_data);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_io_class);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_io_priority);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_policy);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
+CONFIG_PARSER_PROTOTYPE(config_parse_capability_set);
+CONFIG_PARSER_PROTOTYPE(config_parse_sysv_priority);
+CONFIG_PARSER_PROTOTYPE(config_parse_kill_signal);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_flags);
+CONFIG_PARSER_PROTOTYPE(config_parse_timer);
+CONFIG_PARSER_PROTOTYPE(config_parse_trigger_unit);
+CONFIG_PARSER_PROTOTYPE(config_parse_path_spec);
+CONFIG_PARSER_PROTOTYPE(config_parse_socket_service);
+CONFIG_PARSER_PROTOTYPE(config_parse_service_sockets);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_env_file);
+CONFIG_PARSER_PROTOTYPE(config_parse_ip_tos);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_path);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_string);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_null);
+CONFIG_PARSER_PROTOTYPE(config_parse_kill_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_notify_access);
+CONFIG_PARSER_PROTOTYPE(config_parse_emergency_action);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_requires_mounts_for);
+CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter);
+CONFIG_PARSER_PROTOTYPE(config_parse_syscall_archs);
+CONFIG_PARSER_PROTOTYPE(config_parse_syscall_errno);
+CONFIG_PARSER_PROTOTYPE(config_parse_environ);
+CONFIG_PARSER_PROTOTYPE(config_parse_pass_environ);
+CONFIG_PARSER_PROTOTYPE(config_parse_unset_environ);
+CONFIG_PARSER_PROTOTYPE(config_parse_unit_slice);
+CONFIG_PARSER_PROTOTYPE(config_parse_cpu_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_cpu_shares);
+CONFIG_PARSER_PROTOTYPE(config_parse_memory_limit);
+CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max);
+CONFIG_PARSER_PROTOTYPE(config_parse_delegate);
+CONFIG_PARSER_PROTOTYPE(config_parse_device_policy);
+CONFIG_PARSER_PROTOTYPE(config_parse_device_allow);
+CONFIG_PARSER_PROTOTYPE(config_parse_io_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_io_device_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_io_limit);
+CONFIG_PARSER_PROTOTYPE(config_parse_blockio_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_blockio_device_weight);
+CONFIG_PARSER_PROTOTYPE(config_parse_blockio_bandwidth);
+CONFIG_PARSER_PROTOTYPE(config_parse_netclass);
+CONFIG_PARSER_PROTOTYPE(config_parse_job_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_job_mode_isolate);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_selinux_context);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_apparmor_profile);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_smack_process_label);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_families);
+CONFIG_PARSER_PROTOTYPE(config_parse_runtime_preserve_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_directories);
+CONFIG_PARSER_PROTOTYPE(config_parse_set_status);
+CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems);
+CONFIG_PARSER_PROTOTYPE(config_parse_no_new_privileges);
+CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota);
+CONFIG_PARSER_PROTOTYPE(config_parse_protect_home);
+CONFIG_PARSER_PROTOTYPE(config_parse_protect_system);
+CONFIG_PARSER_PROTOTYPE(config_parse_bus_name);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_utmp_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_working_directory);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdname);
+CONFIG_PARSER_PROTOTYPE(config_parse_sec_fix_0);
+CONFIG_PARSER_PROTOTYPE(config_parse_user_group);
+CONFIG_PARSER_PROTOTYPE(config_parse_user_group_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_restrict_namespaces);
+CONFIG_PARSER_PROTOTYPE(config_parse_bind_paths);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_keyring_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_job_timeout_sec);
+CONFIG_PARSER_PROTOTYPE(config_parse_job_running_timeout_sec);
+CONFIG_PARSER_PROTOTYPE(config_parse_log_extra_fields);
+CONFIG_PARSER_PROTOTYPE(config_parse_collect_mode);
/* gperf prototypes */
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
goto finish;
}
- strv_free(*environment);
- *environment = e;
+ strv_free_and_replace(*environment, e);
}
r = 0;
%_udevhwdbdir @udevhwdbdir@
%_udevrulesdir @udevrulesdir@
%_journalcatalogdir @catalogdir@
-%_tmpfilesdir @tmpfilesdir@
-%_sysusersdir @sysusersdir@
-%_sysctldir @sysctldir@
%_binfmtdir @binfmtdir@
+%_sysctldir @sysctldir@
+%_sysusersdir @sysusersdir@
+%_tmpfilesdir @tmpfilesdir@
+%_environmnentdir @environmentdir@
+%_modulesloaddir @modulesloaddir@
+%_modprobedir @modprobedir@
%_systemdgeneratordir @systemgeneratordir@
%_systemdusergeneratordir @usergeneratordir@
%_systemd_system_env_generator_dir @systemenvgeneratordir@
%systemd_post() \
if [ $1 -eq 1 ] ; then \
# Initial installation \
- systemctl --no-reload preset %{?*} >/dev/null 2>&1 || : \
+ systemctl --no-reload preset %{?*} &>/dev/null || : \
fi \
%{nil}
-%systemd_user_post() %{expand:%systemd_post \\--user \\--global %%{?*}}
+%systemd_user_post() %{expand:%systemd_post \\--global %%{?*}}
%systemd_preun() \
if [ $1 -eq 0 ] ; then \
# Package removal, not upgrade \
- systemctl --no-reload disable --now %{?*} > /dev/null 2>&1 || : \
+ systemctl --no-reload disable --now %{?*} &>/dev/null || : \
fi \
%{nil}
%systemd_user_preun() \
if [ $1 -eq 0 ] ; then \
# Package removal, not upgrade \
- systemctl --no-reload --user --global disable %{?*} > /dev/null 2>&1 || : \
+ systemctl --global disable %{?*} &>/dev/null || : \
fi \
%{nil}
%systemd_postun_with_restart() \
if [ $1 -ge 1 ] ; then \
# Package upgrade, not uninstall \
- systemctl try-restart %{?*} >/dev/null 2>&1 || : \
+ systemctl try-restart %{?*} &>/dev/null || : \
fi \
%{nil}
# Deprecated. Use %tmpfiles_create_package instead
%tmpfiles_create() \
-systemd-tmpfiles --create %{?*} >/dev/null 2>&1 || : \
+systemd-tmpfiles --create %{?*} &>/dev/null || : \
%{nil}
# Deprecated. Use %sysusers_create_package instead
%sysusers_create() \
-systemd-sysusers %{?*} >/dev/null 2>&1 || : \
+systemd-sysusers %{?*} &>/dev/null || : \
%{nil}
%sysusers_create_inline() \
-systemd-sysusers - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || : \
+systemd-sysusers - <<SYSTEMD_INLINE_EOF &>/dev/null || : \
%{?*} \
SYSTEMD_INLINE_EOF \
%{nil}
# %files
# %{_sysusersdir}/%{name}.conf
%sysusers_create_package() \
-systemd-sysusers --replace=%_sysusersdir/%1.conf - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || : \
+systemd-sysusers --replace=%_sysusersdir/%1.conf - <<SYSTEMD_INLINE_EOF &>/dev/null || : \
%(cat %2) \
SYSTEMD_INLINE_EOF \
%{nil}
# %files
# %{_tmpfilesdir}/%{name}.conf
%tmpfiles_create_package() \
-systemd-tmpfiles --replace=%_tmpfilesdir/%1.conf --create - <<SYSTEMD_INLINE_EOF >/dev/null 2>&1 || : \
+systemd-tmpfiles --replace=%_tmpfilesdir/%1.conf --create - <<SYSTEMD_INLINE_EOF &>/dev/null || : \
%(cat %2) \
SYSTEMD_INLINE_EOF \
%{nil}
%sysctl_apply() \
-@rootlibexecdir@/systemd-sysctl %{?*} >/dev/null 2>&1 || : \
+@rootlibexecdir@/systemd-sysctl %{?*} &>/dev/null || : \
%{nil}
%binfmt_apply() \
-@rootlibexecdir@/systemd-binfmt %{?*} >/dev/null 2>&1 || : \
+@rootlibexecdir@/systemd-binfmt %{?*} &>/dev/null || : \
%{nil}
#include "def.h"
#include "emergency-action.h"
#include "env-util.h"
+#include "exit-status.h"
#include "fd-util.h"
#include "fdset.h"
#include "fileio.h"
{ "Manager", "DefaultStartLimitIntervalSec",config_parse_sec, 0, &arg_default_start_limit_interval },
{ "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst },
{ "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment },
- { "Manager", "DefaultLimitCPU", config_parse_limit, RLIMIT_CPU, arg_default_rlimit },
- { "Manager", "DefaultLimitFSIZE", config_parse_limit, RLIMIT_FSIZE, arg_default_rlimit },
- { "Manager", "DefaultLimitDATA", config_parse_limit, RLIMIT_DATA, arg_default_rlimit },
- { "Manager", "DefaultLimitSTACK", config_parse_limit, RLIMIT_STACK, arg_default_rlimit },
- { "Manager", "DefaultLimitCORE", config_parse_limit, RLIMIT_CORE, arg_default_rlimit },
- { "Manager", "DefaultLimitRSS", config_parse_limit, RLIMIT_RSS, arg_default_rlimit },
- { "Manager", "DefaultLimitNOFILE", config_parse_limit, RLIMIT_NOFILE, arg_default_rlimit },
- { "Manager", "DefaultLimitAS", config_parse_limit, RLIMIT_AS, arg_default_rlimit },
- { "Manager", "DefaultLimitNPROC", config_parse_limit, RLIMIT_NPROC, arg_default_rlimit },
- { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, RLIMIT_MEMLOCK, arg_default_rlimit },
- { "Manager", "DefaultLimitLOCKS", config_parse_limit, RLIMIT_LOCKS, arg_default_rlimit },
- { "Manager", "DefaultLimitSIGPENDING", config_parse_limit, RLIMIT_SIGPENDING, arg_default_rlimit },
- { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, RLIMIT_MSGQUEUE, arg_default_rlimit },
- { "Manager", "DefaultLimitNICE", config_parse_limit, RLIMIT_NICE, arg_default_rlimit },
- { "Manager", "DefaultLimitRTPRIO", config_parse_limit, RLIMIT_RTPRIO, arg_default_rlimit },
- { "Manager", "DefaultLimitRTTIME", config_parse_limit, RLIMIT_RTTIME, arg_default_rlimit },
+ { "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit },
+ { "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit },
+ { "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit },
+ { "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_default_rlimit },
+ { "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_default_rlimit },
+ { "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_default_rlimit },
+ { "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_default_rlimit },
+ { "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_default_rlimit },
+ { "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_default_rlimit },
+ { "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_default_rlimit },
+ { "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_default_rlimit },
+ { "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_default_rlimit },
+ { "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_default_rlimit },
+ { "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_default_rlimit },
+ { "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_default_rlimit },
+ { "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_default_rlimit },
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
{ "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_default_io_accounting },
{ "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_default_ip_accounting },
}
static void initialize_coredump(bool skip_setup) {
-
+#if ENABLE_COREDUMP
if (getpid_cached() != 1)
return;
* until the systemd-coredump tool is enabled via sysctl. */
if (!skip_setup)
disable_coredumps();
+#endif
}
static void do_reexecute(
#include "sd-path.h"
#include "alloc-util.h"
+#include "all-units.h"
#include "audit-fd.h"
#include "boot-timestamps.h"
#include "bus-common-errors.h"
#include "path-util.h"
#include "process-util.h"
#include "ratelimit.h"
+#include "rlimit-util.h"
#include "rm-rf.h"
#include "signal-util.h"
+#include "socket-util.h"
#include "special.h"
#include "stat-util.h"
#include "string-table.h"
Manager* manager_free(Manager *m) {
UnitType c;
- int i;
ExecDirectoryType dt;
if (!m)
free(m->switch_root);
free(m->switch_root_init);
- for (i = 0; i < _RLIMIT_MAX; i++)
- m->rlimit[i] = mfree(m->rlimit[i]);
+ rlimit_free_all(m->rlimit);
assert(hashmap_isempty(m->units_requiring_mounts_for));
hashmap_free(m->units_requiring_mounts_for);
* 7 times within 2s, we reboot/shutdown immediately,
* unless it was disabled in system.conf */
- if (ratelimit_test(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE)
+ if (ratelimit_below(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE)
manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
else
emergency_action(m, m->cad_burst_action, NULL,
if (m->runtime_watchdog > 0 && m->runtime_watchdog != USEC_INFINITY && MANAGER_IS_SYSTEM(m))
watchdog_ping();
- if (!ratelimit_test(&rl)) {
+ if (!ratelimit_below(&rl)) {
/* Yay, something is going seriously wrong, pause a little */
log_warning("Looping too fast. Throttling execution a little.");
sleep(1);
return 0;
}
- return sd_bus_error_setf(e, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", SD_ID128_FORMAT_VAL(invocation_id));
+ return sd_bus_error_setf(e, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID,
+ "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.",
+ SD_ID128_FORMAT_VAL(invocation_id));
}
/* If this didn't work, we check if this is a unit name */
- if (!unit_name_is_valid(n, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
- return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is neither a valid invocation ID nor unit name.", n);
+ if (!unit_name_is_valid(n, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
+ _cleanup_free_ char *nn = NULL;
+
+ nn = cescape(n);
+ return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS,
+ "Unit name %s is neither a valid invocation ID nor unit name.", strnull(nn));
+ }
r = manager_load_unit(m, n, NULL, e, &u);
if (r < 0)
return r;
}
+static void manager_flush_finished_jobs(Manager *m) {
+ Job *j;
+
+ while ((j = set_steal_first(m->pending_finished_jobs))) {
+ bus_job_send_removed_signal(j);
+ job_free(j);
+ }
+
+ m->pending_finished_jobs = set_free(m->pending_finished_jobs);
+}
+
int manager_reload(Manager *m) {
int r, q;
_cleanup_fclose_ FILE *f = NULL;
if (q < 0 && r >= 0)
r = q;
+ if (!MANAGER_IS_RELOADING(m))
+ manager_flush_finished_jobs(m);
+
m->send_reloading_done = true;
return r;
#include "ratelimit.h"
struct libmnt_monitor;
+typedef struct Unit Unit;
/* Enforce upper limit how many names we allow */
#define MANAGER_MAX_NAMES 131072 /* 128K */
/* non-zero if we are reloading or reexecuting, */
int n_reloading;
+ /* A set which contains all jobs that started before reload and finished
+ * during it */
+ Set *pending_finished_jobs;
unsigned n_installed_jobs;
unsigned n_failed_jobs;
'load-fragment-gperf.gperf',
input : 'load-fragment-gperf.gperf.m4',
output: 'load-fragment-gperf.gperf',
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true)
load_fragment_gperf_c = custom_target(
if (strv_find(*k, controller))
break;
- if (k && *k) {
+ if (*k) {
char **i, **j;
for (i = *k, j = *k; *i; i++) {
if (r < 0)
return r;
- if (r > 0 && k && *k) {
+ if (r > 0 && *k) {
char **i;
for (i = *k; *i; i++) {
#include "alloc-util.h"
#include "dbus-mount.h"
+#include "device.h"
#include "escape.h"
#include "exit-status.h"
#include "format-util.h"
#include "kill.h"
#include "dynamic-user.h"
+#include "unit.h"
typedef enum MountExecCommand {
MOUNT_EXEC_MOUNT,
const char* mount_result_to_string(MountResult i) _const_;
MountResult mount_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(MOUNT, Mount);
/* ProtectKernelTunables= option and the related filesystem APIs */
static const MountEntry protect_kernel_tunables_table[] = {
- { "/proc/sys", READONLY, false },
- { "/proc/sysrq-trigger", READONLY, true },
- { "/proc/latency_stats", READONLY, true },
- { "/proc/mtrr", READONLY, true },
- { "/proc/apm", READONLY, true }, /* Obsolete API, there's no point in permitting access to this, ever */
{ "/proc/acpi", READONLY, true },
- { "/proc/timer_stats", READONLY, true },
+ { "/proc/apm", READONLY, true }, /* Obsolete API, there's no point in permitting access to this, ever */
{ "/proc/asound", READONLY, true },
{ "/proc/bus", READONLY, true },
{ "/proc/fs", READONLY, true },
{ "/proc/irq", READONLY, true },
+ { "/proc/kallsyms", INACCESSIBLE, true },
+ { "/proc/kcore", INACCESSIBLE, true },
+ { "/proc/latency_stats", READONLY, true },
+ { "/proc/mtrr", READONLY, true },
+ { "/proc/scsi", READONLY, true },
+ { "/proc/sys", READONLY, false },
+ { "/proc/sysrq-trigger", READONLY, true },
+ { "/proc/timer_stats", READONLY, true },
{ "/sys", READONLY, false },
- { "/sys/kernel/debug", READONLY, true },
- { "/sys/kernel/tracing", READONLY, true },
{ "/sys/fs/bpf", READONLY, true },
{ "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */
{ "/sys/fs/selinux", READWRITE, true },
+ { "/sys/kernel/debug", READONLY, true },
+ { "/sys/kernel/tracing", READONLY, true },
};
/* ProtectKernelModules= option */
send_interface="org.freedesktop.systemd1.Manager"
send_member="Dump"/>
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Manager"
+ send_member="DumpByFileDescriptor"/>
+
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="ListUnitFiles"/>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.systemd1.reload-daemon org.freedesktop.systemd1.manage-units</annotate>
</action>
<action id="org.freedesktop.systemd1.set-environment">
const char* path_result_to_string(PathResult i) _const_;
PathResult path_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(PATH, Path);
const char* scope_result_to_string(ScopeResult i) _const_;
ScopeResult scope_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(SCOPE, Scope);
if (r < 0)
return r;
- if (s->type == SERVICE_NOTIFY && s->notify_access == NOTIFY_NONE)
- s->notify_access = NOTIFY_MAIN;
-
- if (s->watchdog_usec > 0 && s->notify_access == NOTIFY_NONE)
+ /* If the service needs the notify socket, let's enable it automatically. */
+ if (s->notify_access == NOTIFY_NONE &&
+ (s->type == SERVICE_NOTIFY || s->watchdog_usec > 0 || s->n_fd_store_max > 0))
s->notify_access = NOTIFY_MAIN;
r = service_add_default_dependencies(s);
#include "kill.h"
#include "path.h"
#include "ratelimit.h"
+#include "socket.h"
+#include "unit.h"
typedef enum ServiceRestart {
SERVICE_RESTART_NO,
const char* service_result_to_string(ServiceResult i) _const_;
ServiceResult service_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(SERVICE, Service);
Copyright 2013 Lennart Poettering
***/
+#include "unit.h"
+
typedef struct Slice Slice;
struct Slice {
};
extern const UnitVTable slice_vtable;
+
+DEFINE_CAST(SLICE, Slice);
return;
}
- if (!ratelimit_test(&s->trigger_limit)) {
+ if (!ratelimit_below(&s->trigger_limit)) {
safe_close(cfd);
log_unit_warning(UNIT(s), "Trigger limit hit, refusing further activation.");
socket_enter_stop_pre(s, SOCKET_FAILURE_TRIGGER_LIMIT_HIT);
#include "mount.h"
#include "service.h"
#include "socket-util.h"
+#include "unit.h"
typedef enum SocketExecCommand {
SOCKET_EXEC_START_PRE,
const char* socket_port_type_to_string(SocketPort *p) _pure_;
SocketType socket_port_type_from_string(const char *p) _pure_;
+
+DEFINE_CAST(SOCKET, Socket);
#include "alloc-util.h"
#include "dbus-swap.h"
+#include "device.h"
#include "escape.h"
#include "exit-status.h"
#include "fd-util.h"
static int swap_following_set(Unit *u, Set **_set) {
Swap *s = SWAP(u), *other;
- Set *set;
+ _cleanup_set_free_ Set *set = NULL;
int r;
assert(s);
LIST_FOREACH_OTHERS(same_devnode, other, s) {
r = set_put(set, other);
if (r < 0)
- goto fail;
+ return r;
}
- *_set = set;
+ *_set = TAKE_PTR(set);
return 1;
-
-fail:
- set_free(set);
- return r;
}
static void swap_shutdown(Manager *m) {
***/
#include "libudev.h"
+#include "unit.h"
typedef struct Swap Swap;
const char* swap_result_to_string(SwapResult i) _const_;
SwapResult swap_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(SWAP, Swap);
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
+#include "unit.h"
+
/***
This file is part of systemd.
};
extern const UnitVTable target_vtable;
+
+DEFINE_CAST(TARGET, Target);
typedef struct Timer Timer;
#include "calendarspec.h"
+#include "unit.h"
typedef enum TimerBase {
TIMER_ACTIVE,
const char* timer_result_to_string(TimerResult i) _const_;
TimerResult timer_result_from_string(const char *s) _pure_;
+
+DEFINE_CAST(TIMER, Timer);
#include "sd-messages.h"
#include "alloc-util.h"
+#include "all-units.h"
#include "bus-common-errors.h"
#include "bus-util.h"
#include "cgroup-util.h"
int unit_start_limit_test(Unit *u) {
assert(u);
- if (ratelimit_test(&u->start_limit)) {
+ if (ratelimit_below(&u->start_limit)) {
u->start_limit_hit = false;
return 0;
}
/* If stopping a unit fails continuously we might enter a stop
* loop here, hence stop acting on the service being
* unnecessary after a while. */
- if (!ratelimit_test(&u->auto_stop_ratelimit)) {
+ if (!ratelimit_below(&u->auto_stop_ratelimit)) {
log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently.");
return;
}
/* If stopping a unit fails continuously we might enter a stop
* loop here, hence stop acting on the service being
* unnecessary after a while. */
- if (!ratelimit_test(&u->auto_stop_ratelimit)) {
+ if (!ratelimit_below(&u->auto_stop_ratelimit)) {
log_unit_warning(u, "Unit is bound to inactive unit %s, but not stopping since we tried this too often recently.", other->id);
return;
}
}
static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) {
- Set *pid_set;
+ _cleanup_set_free_ Set *pid_set = NULL;
int r;
pid_set = set_new(NULL);
if (main_pid > 0) {
r = set_put(pid_set, PID_TO_PTR(main_pid));
if (r < 0)
- goto fail;
+ return NULL;
}
if (control_pid > 0) {
r = set_put(pid_set, PID_TO_PTR(control_pid));
if (r < 0)
- goto fail;
+ return NULL;
}
- return pid_set;
-
-fail:
- set_free(pid_set);
- return NULL;
+ return TAKE_PTR(pid_set);
}
int unit_kill_common(
#include <stdlib.h>
#include <unistd.h>
-typedef struct Unit Unit;
-typedef struct UnitVTable UnitVTable;
-typedef struct UnitRef UnitRef;
-typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
-
#include "bpf-program.h"
#include "condition.h"
#include "emergency-action.h"
#include "unit-name.h"
#include "cgroup.h"
+typedef struct UnitRef UnitRef;
+
typedef enum KillOperation {
KILL_TERMINATE,
KILL_TERMINATE_AND_LOG,
UNIT_CGROUP_BPF_INVALIDATED = -1,
} UnitCGroupBPFState;
-struct Unit {
+typedef struct Unit {
Manager *manager;
UnitType type;
/* When writing transient unit files, stores which section we stored last. If < 0, we didn't write any yet. If
* == 0 we are in the [Unit] section, if > 0 we are in the unit type-specific section. */
int last_section_private:2;
-};
+} Unit;
-struct UnitStatusMessageFormats {
+typedef struct UnitStatusMessageFormats {
const char *starting_stopping[2];
const char *finished_start_job[_JOB_RESULT_MAX];
const char *finished_stop_job[_JOB_RESULT_MAX];
-};
+} UnitStatusMessageFormats;
/* Flags used when writing drop-in files or transient unit files */
typedef enum UnitWriteFlags {
/* Returns true if neither persistent, nor runtime storage is requested, i.e. this is a check invocation only */
#define UNIT_WRITE_FLAGS_NOOP(flags) (((flags) & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0)
-#include "automount.h"
-#include "device.h"
-#include "path.h"
-#include "scope.h"
-#include "slice.h"
-#include "socket.h"
-#include "swap.h"
-#include "target.h"
-#include "timer.h"
-
-struct UnitVTable {
+#include "kill.h"
+
+typedef struct UnitVTable {
/* How much memory does an object of this unit type need */
size_t object_size;
/* True if queued jobs of this type should be GC'ed if no other job needs them anymore */
bool gc_jobs:1;
-};
+} UnitVTable;
extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
#define UNIT_TRIGGER(u) ((Unit*) hashmap_first_key((u)->dependencies[UNIT_TRIGGERS]))
-DEFINE_CAST(SERVICE, Service);
-DEFINE_CAST(SOCKET, Socket);
-DEFINE_CAST(TARGET, Target);
-DEFINE_CAST(DEVICE, Device);
-DEFINE_CAST(MOUNT, Mount);
-DEFINE_CAST(AUTOMOUNT, Automount);
-DEFINE_CAST(SWAP, Swap);
-DEFINE_CAST(TIMER, Timer);
-DEFINE_CAST(PATH, Path);
-DEFINE_CAST(SLICE, Slice);
-DEFINE_CAST(SCOPE, Scope);
-
Unit *unit_new(Manager *m, size_t size);
void unit_free(Unit *u);
DEFINE_TRIVIAL_CLEANUP_FUNC(Unit *, unit_free);
}
static inline uint64_t storage_size_max(void) {
- return arg_storage == COREDUMP_STORAGE_EXTERNAL ? arg_external_size_max : arg_journal_size_max;
+ if (arg_storage == COREDUMP_STORAGE_EXTERNAL)
+ return arg_external_size_max;
+ if (arg_storage == COREDUMP_STORAGE_JOURNAL)
+ return arg_journal_size_max;
+ assert(arg_storage == COREDUMP_STORAGE_NONE);
+ return 0;
}
static int fix_acl(int fd, uid_t uid) {
_cleanup_free_ char *fn = NULL, *tmp = NULL;
_cleanup_close_ int fd = -1;
- uint64_t rlimit, max_size;
+ uint64_t rlimit, process_limit, max_size;
struct stat st;
uid_t uid;
int r;
return -EBADSLT;
}
+ process_limit = MAX(arg_process_size_max, storage_size_max());
+ if (process_limit == 0) {
+ log_debug("Limits for coredump processing and storage are both 0, not dumping core.");
+ return -EBADSLT;
+ }
+
/* Never store more than the process configured, or than we actually shall keep or process */
- max_size = MIN(rlimit, MAX(arg_process_size_max, storage_size_max()));
+ max_size = MIN(rlimit, process_limit);
r = make_filename(context, &fn);
if (r < 0)
case 'o':
if (arg_output) {
- log_error("cannot set output more than once");
+ log_error("Cannot set output more than once.");
return -EINVAL;
}
case 'F':
if (arg_field) {
- log_error("cannot use --field/-F more than once");
+ log_error("Cannot use --field/-F more than once.");
return -EINVAL;
}
arg_field = optarg;
#include <stdbool.h>
#include <stdlib.h>
+#include "string-table.h"
#include "util.h"
#include "virt.h"
" -r --chroot Detect whether we are run in a chroot() environment\n"
" --private-users Only detect whether we are running in a user namespace\n"
" -q --quiet Don't output anything, just set return value\n"
+ " --list List all known and detectable types of virtualization\n"
, program_invocation_short_name);
}
enum {
ARG_VERSION = 0x100,
ARG_PRIVATE_USERS,
+ ARG_LIST,
};
static const struct option options[] = {
{ "chroot", no_argument, NULL, 'r' },
{ "private-users", no_argument, NULL, ARG_PRIVATE_USERS },
{ "quiet", no_argument, NULL, 'q' },
+ { "list", no_argument, NULL, ARG_LIST },
{}
};
arg_mode = ONLY_CHROOT;
break;
+ case ARG_LIST:
+ DUMP_STRING_TABLE(virtualization, int, _VIRTUALIZATION_MAX);
+ return 0;
+
case '?':
return -EINVAL;
return 0;
}
+static bool timezone_is_valid_log_error(const char *name) {
+ return timezone_is_valid(name, LOG_ERR);
+}
+
static int prompt_timezone(void) {
_cleanup_strv_free_ char **zones = NULL;
int r;
putchar('\n');
- r = prompt_loop("Please enter timezone name or number", zones, timezone_is_valid, &arg_timezone);
+ r = prompt_loop("Please enter timezone name or number", zones, timezone_is_valid_log_error, &arg_timezone);
if (r < 0)
return r;
break;
case ARG_TIMEZONE:
- if (!timezone_is_valid(optarg)) {
+ if (!timezone_is_valid(optarg, LOG_ERR)) {
log_error("Timezone %s is not valid.", optarg);
return -EINVAL;
}
if (!u)
return -ENOMEM;
- strv_free(l);
- l = u;
+ strv_free_and_replace(l, u);
}
if (strv_isempty(l)) {
Context *c = userdata;
const char *name;
int interactive;
- char *h;
int r;
assert(m);
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- h = strdup(name);
- if (!h)
- return -ENOMEM;
-
- free(c->data[PROP_HOSTNAME]);
- c->data[PROP_HOSTNAME] = h;
+ r = free_and_strdup(&c->data[PROP_HOSTNAME], name);
+ if (r < 0)
+ return r;
r = context_update_kernel_hostname(c);
if (r < 0) {
if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
return sd_bus_reply_method_return(m, NULL);
+ if (!isempty(name) && !hostname_is_valid(name, false))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
+
r = bus_verify_polkit_async(
m,
CAP_SYS_ADMIN,
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- if (isempty(name))
- c->data[PROP_STATIC_HOSTNAME] = mfree(c->data[PROP_STATIC_HOSTNAME]);
- else {
- char *h;
-
- if (!hostname_is_valid(name, false))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
-
- h = strdup(name);
- if (!h)
- return -ENOMEM;
-
- free(c->data[PROP_STATIC_HOSTNAME]);
- c->data[PROP_STATIC_HOSTNAME] = h;
- }
+ r = free_and_strdup(&c->data[PROP_STATIC_HOSTNAME], name);
+ if (r < 0)
+ return r;
r = context_update_kernel_hostname(c);
if (r < 0) {
if (streq_ptr(name, c->data[prop]))
return sd_bus_reply_method_return(m, NULL);
+ if (!isempty(name)) {
+ /* The icon name might ultimately be used as file
+ * name, so better be safe than sorry */
+
+ if (prop == PROP_ICON_NAME && !filename_is_valid(name))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name);
+ if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name);
+ if (prop == PROP_CHASSIS && !valid_chassis(name))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name);
+ if (prop == PROP_DEPLOYMENT && !valid_deployment(name))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name);
+ if (prop == PROP_LOCATION && string_has_cc(name, NULL))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name);
+ }
+
/* Since the pretty hostname should always be changed at the
* same time as the static one, use the same policy action for
* both... */
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- if (isempty(name))
- c->data[prop] = mfree(c->data[prop]);
- else {
- char *h;
-
- /* The icon name might ultimately be used as file
- * name, so better be safe than sorry */
-
- if (prop == PROP_ICON_NAME && !filename_is_valid(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name);
- if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name);
- if (prop == PROP_CHASSIS && !valid_chassis(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name);
- if (prop == PROP_DEPLOYMENT && !valid_deployment(name))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name);
- if (prop == PROP_LOCATION && string_has_cc(name, NULL))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name);
-
- h = strdup(name);
- if (!h)
- return -ENOMEM;
-
- free(c->data[prop]);
- c->data[prop] = h;
- }
+ r = free_and_strdup(&c->data[prop], name);
+ if (r < 0)
+ return r;
r = context_write_data_machine_info(c);
if (r < 0) {
if (percent == e->last_percent)
return;
- if (!ratelimit_test(&e->progress_rate_limit))
+ if (!ratelimit_below(&e->progress_rate_limit))
return;
sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
if (percent == e->last_percent)
return;
- if (!ratelimit_test(&e->progress_rate_limit))
+ if (!ratelimit_below(&e->progress_rate_limit))
return;
sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
if (percent == i->last_percent)
return;
- if (!ratelimit_test(&i->progress_rate_limit))
+ if (!ratelimit_below(&i->progress_rate_limit))
return;
sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
if (percent == i->last_percent)
return;
- if (!ratelimit_test(&i->progress_rate_limit))
+ if (!ratelimit_below(&i->progress_rate_limit))
return;
sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
int catalog_update(const char* database, const char* root, const char* const* dirs) {
_cleanup_strv_free_ char **files = NULL;
char **f;
- struct strbuf *sb = NULL;
+ _cleanup_(strbuf_cleanupp) struct strbuf *sb = NULL;
_cleanup_hashmap_free_free_free_ Hashmap *h = NULL;
_cleanup_free_ CatalogItem *items = NULL;
ssize_t offset;
h = hashmap_new(&catalog_hash_ops);
sb = strbuf_new();
-
- if (!h || !sb) {
- r = log_oom();
- goto finish;
- }
+ if (!h || !sb)
+ return log_oom();
r = conf_files_list_strv(&files, ".catalog", root, 0, dirs);
- if (r < 0) {
- log_error_errno(r, "Failed to get catalog files: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to get catalog files: %m");
STRV_FOREACH(f, files) {
log_debug("Reading file '%s'", *f);
r = catalog_import_file(h, *f);
- if (r < 0) {
- log_error_errno(r, "Failed to import file '%s': %m", *f);
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to import file '%s': %m", *f);
}
if (hashmap_size(h) <= 0) {
log_info("No items in catalog.");
- goto finish;
+ return 0;
} else
log_debug("Found %u items in catalog.", hashmap_size(h));
items = new(CatalogItem, hashmap_size(h));
- if (!items) {
- r = log_oom();
- goto finish;
- }
+ if (!items)
+ return log_oom();
n = 0;
HASHMAP_FOREACH_KEY(payload, i, h, j) {
isempty(i->language) ? "C" : i->language);
offset = strbuf_add_string(sb, payload, strlen(payload));
- if (offset < 0) {
- r = log_oom();
- goto finish;
- }
+ if (offset < 0)
+ return log_oom();
+
i->offset = htole64((uint64_t) offset);
items[n++] = *i;
}
sz = write_catalog(database, sb, items, n);
if (sz < 0)
- r = log_error_errno(sz, "Failed to write %s: %m", database);
- else {
- r = 0;
- log_debug("%s: wrote %u items, with %zu bytes of strings, %"PRIi64" total size.",
- database, n, sb->len, sz);
- }
-
-finish:
- strbuf_cleanup(sb);
+ return log_error_errno(sz, "Failed to write %s: %m", database);
- return r;
+ log_debug("%s: wrote %u items, with %zu bytes of strings, %"PRIi64" total size.",
+ database, n, sb->len, sz);
+ return 0;
}
static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p) {
#include "rlimit-util.h"
#include "set.h"
#include "sigbus.h"
+#include "string-table.h"
#include "strv.h"
#include "syslog-util.h"
#include "terminal-util.h"
-#include "udev.h"
#include "udev-util.h"
+#include "udev.h"
#include "unit-name.h"
#include "user-util.h"
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output format '%s'.", optarg);
typedef struct Server Server;
+#include "conf-parser.h"
#include "hashmap.h"
#include "journal-file.h"
#include "journald-context.h"
/* gperf lookup function */
const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-int config_parse_storage(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_line_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_compress(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_storage);
+CONFIG_PARSER_PROTOTYPE(config_parse_line_max);
+CONFIG_PARSER_PROTOTYPE(config_parse_compress);
const char *storage_to_string(Storage s) _const_;
Storage storage_from_string(const char *s) _pure_;
-int config_parse_split_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_split_mode);
const char *split_mode_to_string(SplitMode s) _const_;
SplitMode split_mode_from_string(const char *s) _pure_;
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
+ * does it on word boundaries, so is OK with this. But valgrind will
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
+#if !VALGRIND && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
+ * does it on word boundaries, so is OK with this. But valgrind will
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
+#if !VALGRIND && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
* then shifts out the part it's not allowed to read. Because the
* string is aligned, the illegal read is in the same word as the
* rest of the string. Every machine with memory protection I've seen
- * does it on word boundaries, so is OK with this. But VALGRIND will
+ * does it on word boundaries, so is OK with this. But valgrind will
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
+#if !VALGRIND && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
}
static sd_journal *journal_new(int flags, const char *path) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
j = new0(sd_journal, 1);
if (!j)
t = strdup(path);
if (!t)
- goto fail;
+ return NULL;
if (flags & SD_JOURNAL_OS_ROOT)
j->prefix = t;
j->files = ordered_hashmap_new(&path_hash_ops);
if (!j->files)
- goto fail;
+ return NULL;
j->files_cache = ordered_hashmap_iterated_cache_new(j->files);
j->directories_by_path = hashmap_new(&path_hash_ops);
j->mmap = mmap_cache_new();
if (!j->files_cache || !j->directories_by_path || !j->mmap)
- goto fail;
-
- return j;
+ return NULL;
-fail:
- sd_journal_close(j);
- return NULL;
+ return TAKE_PTR(j);
}
#define OPEN_ALLOWED_FLAGS \
SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)
_public_ int sd_journal_open(sd_journal **ret, int flags) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
int r;
assert_return(ret, -EINVAL);
r = add_search_paths(j);
if (r < 0)
- goto fail;
+ return r;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
-
- return r;
}
#define OPEN_CONTAINER_ALLOWED_FLAGS \
_public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
_cleanup_free_ char *root = NULL, *class = NULL;
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
char *p;
int r;
r = add_search_paths(j);
if (r < 0)
- goto fail;
+ return r;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
- return r;
}
#define OPEN_DIRECTORY_ALLOWED_FLAGS \
SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
int r;
assert_return(ret, -EINVAL);
else
r = add_root_directory(j, path, false);
if (r < 0)
- goto fail;
+ return r;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
- return r;
}
_public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
const char **path;
int r;
STRV_FOREACH(path, paths) {
r = add_any_file(j, -1, *path);
if (r < 0)
- goto fail;
+ return r;
}
j->no_new_files = true;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
- return r;
}
#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \
SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
struct stat st;
int r;
else
r = add_root_directory(j, NULL, false);
if (r < 0)
- goto fail;
+ return r;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
-
-fail:
- sd_journal_close(j);
- return r;
}
_public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) {
Iterator iterator;
JournalFile *f;
- sd_journal *j;
+ _cleanup_(sd_journal_closep) sd_journal *j = NULL;
unsigned i;
int r;
j->no_new_files = true;
j->no_inotify = true;
- *ret = j;
+ *ret = TAKE_PTR(j);
return 0;
fail:
ORDERED_HASHMAP_FOREACH(f, j->files, iterator)
f->close_fd = false;
- sd_journal_close(j);
return r;
}
#include "alloc-util.h"
#include "catalog.h"
#include "fd-util.h"
+#include "fs-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
NULL
};
-static Hashmap * test_import(const char* contents, ssize_t size, int code) {
- int r;
- char name[] = "/tmp/test-catalog.XXXXXX";
+static Hashmap* test_import(const char* contents, ssize_t size, int code) {
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-catalog.XXXXXX";
_cleanup_close_ int fd;
Hashmap *h;
assert_se(fd >= 0);
assert_se(write(fd, contents, size) == size);
- r = catalog_import_file(h, name);
- assert_se(r == code);
-
- unlink(name);
+ assert_se(catalog_import_file(h, name) == code);
return h;
}
}
}
-static const char* database = NULL;
-
-static void test_catalog_update(void) {
- static char name[] = "/tmp/test-catalog.XXXXXX";
+static void test_catalog_update(const char *database) {
int r;
- r = mkostemp_safe(name);
- assert_se(r >= 0);
-
- database = name;
-
/* Test what happens if there are no files. */
r = catalog_update(database, NULL, NULL);
- assert_se(r >= 0);
+ assert_se(r == 0);
/* Test what happens if there are no files in the directory. */
r = catalog_update(database, NULL, no_catalog_dirs);
- assert_se(r >= 0);
+ assert_se(r == 0);
/* Make sure that we at least have some files loaded or the
catalog_list below will fail. */
r = catalog_update(database, NULL, catalog_dirs);
- assert_se(r >= 0);
+ assert_se(r == 0);
}
static void test_catalog_file_lang(void) {
}
int main(int argc, char *argv[]) {
+ _cleanup_(unlink_tempfilep) char database[] = "/tmp/test-catalog.XXXXXX";
_cleanup_free_ char *text = NULL;
int r;
test_catalog_import_merge();
test_catalog_import_merge_no_body();
- test_catalog_update();
+ assert_se(mkostemp_safe(database) >= 0);
+
+ test_catalog_update(database);
r = catalog_list(stdout, database, true);
assert_se(r >= 0);
assert_se(catalog_get(database, SD_MESSAGE_COREDUMP, &text) >= 0);
printf(">>>%s<<<\n", text);
- if (database)
- unlink(database);
-
return 0;
}
#include "compress.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "macro.h"
#include "path-util.h"
#include "random-util.h"
const char *srcfile) {
_cleanup_close_ int src = -1, dst = -1, dst2 = -1;
- char pattern[] = "/tmp/systemd-test.compressed.XXXXXX",
- pattern2[] = "/tmp/systemd-test.compressed.XXXXXX";
+ _cleanup_(unlink_tempfilep) char
+ pattern[] = "/tmp/systemd-test.compressed.XXXXXX",
+ pattern2[] = "/tmp/systemd-test.compressed.XXXXXX";
int r;
_cleanup_free_ char *cmd = NULL, *cmd2 = NULL;
struct stat st = {};
assert_se(lseek(dst2, 0, SEEK_SET) == 0);
r = decompress(dst, dst2, st.st_size - 1);
assert_se(r == -EFBIG);
-
- assert_se(unlink(pattern) == 0);
- assert_se(unlink(pattern2) == 0);
}
#endif
#include "alloc-util.h"
#include "utf8.h"
+#include "strv.h"
#include "dhcp-internal.h"
*offset += 1;
break;
+ case SD_DHCP_OPTION_USER_CLASS: {
+ size_t len = 0;
+ char **s;
+
+ STRV_FOREACH(s, (char **) optval)
+ len += strlen(*s) + 1;
+
+ if (size < *offset + len + 2)
+ return -ENOBUFS;
+
+ options[*offset] = code;
+ options[*offset + 1] = len;
+ *offset += 2;
+
+ STRV_FOREACH(s, (char **) optval) {
+ len = strlen(*s);
+
+ if (len > 255)
+ return -ENAMETOOLONG;
+
+ options[*offset] = len;
+
+ memcpy_safe(&options[*offset + 1], *s, len);
+ *offset += len + 1;
+ }
+
+ break;
+ }
default:
if (size < *offset + optlen + 2)
return -ENOBUFS;
return string && strv_fnmatch(raw_patterns, string, 0);
}
-bool net_match_config(const struct ether_addr *match_mac,
+bool net_match_config(Set *match_mac,
char * const *match_paths,
char * const *match_drivers,
char * const *match_types,
if (match_arch && condition_test(match_arch) <= 0)
return false;
- if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
+ if (match_mac && dev_mac && !set_contains(match_mac, dev_mac))
return false;
if (!net_condition_test_strv(match_paths, dev_path))
const char *rvalue,
void *data,
void *userdata) {
+
+ _cleanup_free_ struct ether_addr *n = NULL;
struct ether_addr **hwaddr = data;
- struct ether_addr *n;
- const char *start;
- size_t offset;
int r;
assert(filename);
if (!n)
return log_oom();
- start = rvalue + strspn(rvalue, WHITESPACE);
- r = ether_addr_from_string(start, n, &offset);
+ r = ether_addr_from_string(rvalue, n);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ *hwaddr = TAKE_PTR(n);
+
+ return 0;
+}
+
+int config_parse_hwaddrs(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_set_free_free_ Set *s = NULL;
+ const char *p = rvalue;
+ Set **hwaddrs = data;
+ int r;
- if (r || (start[offset + strspn(start + offset, WHITESPACE)] != '\0')) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
- free(n);
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ /* Empty assignment resets the list */
+ *hwaddrs = set_free_free(*hwaddrs);
return 0;
}
- free(*hwaddr);
- *hwaddr = n;
+ s = set_new(ðer_addr_hash_ops);
+ if (!s)
+ return log_oom();
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+ _cleanup_free_ struct ether_addr *n = NULL;
+
+ r = extract_first_word(&p, &word, NULL, 0);
+ if (r == 0)
+ break;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ n = new(struct ether_addr, 1);
+ if (!n)
+ return log_oom();
+
+ r = ether_addr_from_string(word, n);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring: %s", word);
+ continue;
+ }
+
+ r = set_put(s, n);
+ if (r < 0)
+ return log_oom();
+ if (r > 0)
+ n = NULL; /* avoid cleanup */
+ }
+
+ r = set_ensure_allocated(hwaddrs, ðer_addr_hash_ops);
+ if (r < 0)
+ return log_oom();
+
+ r = set_move(*hwaddrs, s);
+ if (r < 0)
+ return log_oom();
return 0;
}
return 0;
}
-
-int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {
- assert(data);
- assert(data_len);
- assert(string);
-
- if (strlen(string) % 2)
- return -EINVAL;
-
- return unhexmem(string, strlen(string), (void **)data, data_len);
-}
#include "sd-dhcp-lease.h"
#include "condition.h"
+#include "conf-parser.h"
+#include "set.h"
#include "udev.h"
#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
-bool net_match_config(const struct ether_addr *match_mac,
+bool net_match_config(Set *match_mac,
char * const *match_path,
char * const *match_driver,
char * const *match_type,
const char *dev_type,
const char *dev_name);
-int config_parse_net_condition(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_hwaddr(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_ifnames(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_ifalias(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_iaid(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_bridge_port_priority(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_net_condition);
+CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
+CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
+CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
+CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
const char *net_get_name(struct udev_device *device);
void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size);
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
+/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
-int deserialize_dhcp_option(void **data, size_t *data_len, const char *string);
#include "random-util.h"
#include "string-util.h"
#include "util.h"
+#include "strv.h"
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
size_t client_id_len;
char *hostname;
char *vendor_class_identifier;
+ char **user_class;
uint32_t mtu;
uint32_t xid;
usec_t start_time;
return free_and_strdup(&client->vendor_class_identifier, vci);
}
+int sd_dhcp_client_set_user_class(
+ sd_dhcp_client *client,
+ const char* const* user_class) {
+
+ _cleanup_strv_free_ char **s = NULL;
+ char **p;
+
+ STRV_FOREACH(p, (char **) user_class)
+ if (strlen(*p) > 255)
+ return -ENAMETOOLONG;
+
+ s = strv_copy((char **) user_class);
+ if (!s)
+ return -ENOMEM;
+
+ client->user_class = TAKE_PTR(s);
+
+ return 0;
+}
+
int sd_dhcp_client_set_client_port(
sd_dhcp_client *client,
uint16_t port) {
return r;
}
+ if (client->user_class) {
+ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+ SD_DHCP_OPTION_USER_CLASS,
+ strv_length(client->user_class),
+ client->user_class);
+ if (r < 0)
+ return r;
+ }
+
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
free(client->req_opts);
free(client->hostname);
free(client->vendor_class_identifier);
+ client->user_class = strv_free(client->user_class);
return mfree(client);
}
return 0;
}
- if (!timezone_is_valid(tz)) {
+ if (!timezone_is_valid(tz, LOG_DEBUG)) {
log_debug_errno(r, "Timezone is not valid, ignoring: %m");
return 0;
}
}
if (client_id_hex) {
- r = deserialize_dhcp_option(&lease->client_id, &lease->client_id_len, client_id_hex);
+ r = unhexmem(client_id_hex, (size_t) -1, &lease->client_id, &lease->client_id_len);
if (r < 0)
log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex);
}
if (vendor_specific_hex) {
- r = deserialize_dhcp_option(&lease->vendor_specific, &lease->vendor_specific_len, vendor_specific_hex);
+ r = unhexmem(vendor_specific_hex, (size_t) -1, &lease->vendor_specific, &lease->vendor_specific_len);
if (r < 0)
log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
}
if (!options[i])
continue;
- r = deserialize_dhcp_option(&data, &len, options[i]);
+ r = unhexmem(options[i], (size_t) -1, &data, &len);
if (r < 0) {
log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]);
continue;
int r;
assert_return(server, -EINVAL);
- assert_return(timezone_is_valid(tz), -EINVAL);
+ assert_return(timezone_is_valid(tz, LOG_DEBUG), -EINVAL);
if (streq_ptr(tz, server->timezone))
return 0;
if (r < 0)
return 0;
- strv_free(lease->domains);
- lease->domains = domains;
+ strv_free_and_replace(lease->domains, domains);
lease->domains_count = r;
return r;
if (r < 0)
return 0;
- lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
- lease->ntp_fqdn = servers;
+ strv_free_and_replace(lease->ntp_fqdn, servers);
lease->ntp_fqdn_count = r;
break;
test_discover_message(e);
test_addr_acq(e);
-#ifdef VALGRIND
+#if VALGRIND
/* Make sure the async_close thread has finished.
* valgrind would report some of the phread_* structures
* as not cleaned up properly. */
sd-utf8/sd-utf8.c
'''.split()) + id128_sources + sd_daemon_c + sd_event_c + sd_login_c
+libsystemd_c_args = ['-fvisibility=default']
+
libsystemd_static = static_library(
- 'systemd',
+ 'systemd_static',
libsystemd_sources,
install : false,
include_directories : includes,
link_with : libbasic,
dependencies : [threads,
librt],
- c_args : ['-fvisibility=default'])
+ c_args : libsystemd_c_args)
libsystemd_sym = 'src/libsystemd/libsystemd.sym'
#define BUS_WQUEUE_MAX (192*1024)
#define BUS_RQUEUE_MAX (192*1024)
-#define BUS_MESSAGE_SIZE_MAX (64*1024*1024)
+#define BUS_MESSAGE_SIZE_MAX (128*1024*1024)
#define BUS_AUTH_SIZE_MAX (64*1024)
#define BUS_CONTAINER_DEPTH 128
m->root_container.index = 0;
}
-static void message_free(sd_bus_message *m) {
+static sd_bus_message* message_free(sd_bus_message *m) {
assert(m);
if (m->free_header)
free(m->root_container.peeked_signature);
bus_creds_done(&m->creds);
- free(m);
+ return mfree(m);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free);
+
static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
void *op, *np;
size_t old_size, new_size, start;
const char *label,
sd_bus_message **ret) {
- sd_bus_message *m;
+ _cleanup_(message_freep) sd_bus_message *m = NULL;
size_t sz;
int r;
r = bus_message_parse_fields(m);
if (r < 0)
- goto fail;
+ return r;
/* We take possession of the memory and fds now */
m->free_header = true;
m->free_fds = true;
- *ret = m;
+ *ret = TAKE_PTR(m);
return 0;
-
-fail:
- message_free(m);
- return r;
}
_public_ int sd_bus_message_new(
const char *interface,
const char *member) {
- sd_bus_message *t;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL;
int r;
assert_return(bus, -ENOTCONN);
r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
if (r < 0)
- goto fail;
+ return r;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
if (r < 0)
- goto fail;
+ return r;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
if (r < 0)
- goto fail;
+ return r;
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- sd_bus_message_unref(t);
- return r;
}
_public_ int sd_bus_message_new_method_call(
const char *interface,
const char *member) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
int r;
assert_return(bus, -ENOTCONN);
r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
if (r < 0)
- goto fail;
+ return r;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
if (r < 0)
- goto fail;
+ return r;
if (interface) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
if (r < 0)
- goto fail;
+ return r;
}
if (destination) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
if (r < 0)
- goto fail;
+ return r;
}
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
static int message_new_reply(
uint8_t type,
sd_bus_message **m) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
uint64_t cookie;
int r;
t->reply_cookie = cookie;
r = message_append_reply_cookie(t, t->reply_cookie);
if (r < 0)
- goto fail;
+ return r;
if (call->sender) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
if (r < 0)
- goto fail;
+ return r;
}
t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
t->enforced_reply_signature = call->enforced_reply_signature;
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
_public_ int sd_bus_message_new_method_return(
sd_bus_message **m,
const sd_bus_error *e) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
int r;
assert_return(sd_bus_error_is_set(e), -EINVAL);
r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
if (r < 0)
- goto fail;
+ return r;
if (e->message) {
r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
if (r < 0)
- goto fail;
+ return r;
}
t->error._need_free = -1;
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
_public_ int sd_bus_message_new_method_errorf(
const sd_bus_error *e,
sd_bus_message **m) {
- sd_bus_message *t;
+ _cleanup_(message_freep) sd_bus_message *t = NULL;
int r;
assert(bus);
r = message_append_reply_cookie(t, t->reply_cookie);
if (r < 0)
- goto fail;
+ return r;
if (bus && bus->unique_name) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
if (r < 0)
- goto fail;
+ return r;
}
r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
if (r < 0)
- goto fail;
+ return r;
if (e->message) {
r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message);
if (r < 0)
- goto fail;
+ return r;
}
t->error._need_free = -1;
bus_message_set_sender_driver(bus, t);
- *m = t;
+ *m = TAKE_PTR(t);
return 0;
-
-fail:
- message_free(t);
- return r;
}
_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) {
if (IN_SET(errno, ENOENT, ELOOP))
break; /* This component doesn't exist yet, or the path contains a cyclic symlink right now */
- r = log_debug_errno(errno, "Failed to add inotify watch on %s: %m", isempty(prefix) ? "/" : prefix);
+ r = log_debug_errno(errno, "Failed to add inotify watch on %s: %m", empty_to_root(prefix));
goto fail;
} else
new_watches[n++] = wd;
b->wqueue_allocated = 0;
}
-static void bus_free(sd_bus *b) {
+static sd_bus* bus_free(sd_bus *b) {
sd_bus_slot *s;
assert(b);
assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0);
- free(b);
+ return mfree(b);
}
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, bus_free);
+
_public_ int sd_bus_new(sd_bus **ret) {
- sd_bus *r;
+ _cleanup_free_ sd_bus *b = NULL;
assert_return(ret, -EINVAL);
- r = new0(sd_bus, 1);
- if (!r)
+ b = new0(sd_bus, 1);
+ if (!b)
return -ENOMEM;
- r->n_ref = REFCNT_INIT;
- r->input_fd = r->output_fd = -1;
- r->inotify_fd = -1;
- r->message_version = 1;
- r->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
- r->accept_fd = true;
- r->original_pid = getpid_cached();
- r->n_groups = (size_t) -1;
-
- assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
-
- /* We guarantee that wqueue always has space for at least one
- * entry */
- if (!GREEDY_REALLOC(r->wqueue, r->wqueue_allocated, 1)) {
- free(r);
+ b->n_ref = REFCNT_INIT;
+ b->input_fd = b->output_fd = -1;
+ b->inotify_fd = -1;
+ b->message_version = 1;
+ b->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
+ b->accept_fd = true;
+ b->original_pid = getpid_cached();
+ b->n_groups = (size_t) -1;
+
+ assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0);
+
+ /* We guarantee that wqueue always has space for at least one entry */
+ if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1))
return -ENOMEM;
- }
- *ret = r;
+ *ret = TAKE_PTR(b);
return 0;
}
_public_ int sd_bus_set_address(sd_bus *bus, const char *address) {
- char *a;
-
assert_return(bus, -EINVAL);
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(bus->state == BUS_UNSET, -EPERM);
assert_return(address, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- a = strdup(address);
- if (!a)
- return -ENOMEM;
-
- free_and_replace(bus->address, a);
-
- return 0;
+ return free_and_strdup(&bus->address, address);
}
_public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
}
_public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
- char *p, **a;
+ _cleanup_strv_free_ char **a = NULL;
+ int r;
assert_return(bus, -EINVAL);
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!strv_isempty(argv), -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
- p = strdup(path);
- if (!p)
- return -ENOMEM;
-
a = strv_copy(argv);
- if (!a) {
- free(p);
+ if (!a)
return -ENOMEM;
- }
-
- free_and_replace(bus->exec_path, p);
- strv_free(bus->exec_argv);
- bus->exec_argv = a;
+ r = free_and_strdup(&bus->exec_path, path);
+ if (r < 0)
+ return r;
- return 0;
+ return strv_free_and_replace(bus->exec_argv, a);
}
_public_ int sd_bus_set_bus_client(sd_bus *bus, int b) {
static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
const char *s;
- char *t;
sd_bus *bus;
int r;
if (!service_name_is_valid(s) || s[0] != ':')
return -EBADMSG;
- t = strdup(s);
- if (!t)
- return -ENOMEM;
-
- free_and_replace(bus->unique_name, t);
+ r = free_and_strdup(&bus->unique_name, s);
+ if (r < 0)
+ return r;
if (bus->state == BUS_HELLO) {
bus_set_state(bus, BUS_RUNNING);
_public_ int sd_bus_open_with_description(sd_bus **ret, const char *description) {
const char *e;
- sd_bus *b;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(ret, -EINVAL);
r = sd_bus_set_address(b, e);
if (r < 0)
- goto fail;
+ return r;
b->bus_client = true;
r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = b;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(b);
- return r;
}
_public_ int sd_bus_open(sd_bus **ret) {
}
_public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *description) {
- sd_bus *b;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(ret, -EINVAL);
if (description) {
r = sd_bus_set_description(b, description);
if (r < 0)
- goto fail;
+ return r;
}
r = bus_set_address_system(b);
if (r < 0)
- goto fail;
+ return r;
b->bus_client = true;
b->is_system = true;
r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = b;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(b);
- return r;
}
_public_ int sd_bus_open_system(sd_bus **ret) {
}
_public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *description) {
- sd_bus *b;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(ret, -EINVAL);
if (description) {
r = sd_bus_set_description(b, description);
if (r < 0)
- goto fail;
+ return r;
}
r = bus_set_address_user(b);
if (r < 0)
- goto fail;
+ return r;
b->bus_client = true;
b->is_user = true;
r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = b;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(b);
- return r;
}
_public_ int sd_bus_open_user(sd_bus **ret) {
/* Let's make sure this is not a port of some kind,
* and is a valid machine name. */
- if (!in_charset(m, "0123456789") && machine_name_is_valid(m)) {
+ if (!in_charset(m, DIGITS) && machine_name_is_valid(m)) {
char *t;
/* Cut out the host part */
if (!a)
return -ENOMEM;
- free_and_replace(b->address, a);
-
- return 0;
- }
+ return free_and_replace(b->address, a);
+}
_public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
- sd_bus *bus;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(host, -EINVAL);
assert_return(ret, -EINVAL);
- r = sd_bus_new(&bus);
+ r = sd_bus_new(&b);
if (r < 0)
return r;
- r = bus_set_address_system_remote(bus, host);
+ r = bus_set_address_system_remote(b, host);
if (r < 0)
- goto fail;
+ return r;
- bus->bus_client = true;
- bus->trusted = false;
- bus->is_system = true;
- bus->is_local = false;
+ b->bus_client = true;
+ b->trusted = false;
+ b->is_system = true;
+ b->is_local = false;
- r = sd_bus_start(bus);
+ r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = bus;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(bus);
- return r;
}
int bus_set_address_system_machine(sd_bus *b, const char *machine) {
if (!a)
return -ENOMEM;
- free_and_replace(b->address, a);
-
- return 0;
+ return free_and_replace(b->address, a);
}
_public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) {
- sd_bus *bus;
+ _cleanup_(bus_freep) sd_bus *b = NULL;
int r;
assert_return(machine, -EINVAL);
assert_return(ret, -EINVAL);
assert_return(machine_name_is_valid(machine), -EINVAL);
- r = sd_bus_new(&bus);
+ r = sd_bus_new(&b);
if (r < 0)
return r;
- r = bus_set_address_system_machine(bus, machine);
+ r = bus_set_address_system_machine(b, machine);
if (r < 0)
- goto fail;
+ return r;
- bus->bus_client = true;
- bus->trusted = false;
- bus->is_system = true;
- bus->is_local = false;
+ b->bus_client = true;
+ b->trusted = false;
+ b->is_system = true;
+ b->is_local = false;
- r = sd_bus_start(bus);
+ r = sd_bus_start(b);
if (r < 0)
- goto fail;
+ return r;
- *ret = bus;
+ *ret = TAKE_PTR(b);
return 0;
-
-fail:
- bus_free(bus);
- return r;
}
_public_ void sd_bus_close(sd_bus *bus) {
-
if (!bus)
return;
if (bus->state == BUS_CLOSED)
}
_public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
-
if (!bus)
return NULL;
}
_public_ sd_bus *sd_bus_ref(sd_bus *bus) {
-
if (!bus)
return NULL;
if (i > 0)
return NULL;
- bus_free(bus);
- return NULL;
+ return bus_free(bus);
}
_public_ int sd_bus_is_open(sd_bus *bus) {
-
assert_return(bus, -EINVAL);
assert_return(bus = bus_resolve(bus), -ENOPKG);
assert_return(!bus_pid_changed(bus), -ECHILD);
if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
- assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
+ assert_se((sd_bus_can_send(bus, 'h') >= 1) ==
+ (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
r = sd_bus_message_new_method_return(m, &reply);
if (r < 0) {
Copyright 2008-2011 Lennart Poettering
***/
-
#include "sd-netlink.h"
#include "in-addr-util.h"
#define RESOLVE_DONT_DESTROY(resolve) \
_cleanup_(sd_resolve_unrefp) _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve)
-static int send_died(int out_fd) {
+static void query_assign_errno(sd_resolve_query *q, int ret, int error, int h_error) {
+ assert(q);
+
+ q->ret = ret;
+ q->_errno = abs(error);
+ q->_h_errno = h_error;
+}
+static int send_died(int out_fd) {
RHeader rh = {
.type = RESPONSE_DIED,
.length = sizeof(RHeader),
._h_errno = _h_errno,
};
- struct msghdr mh = {};
- struct iovec iov[2];
union {
AddrInfoSerialization ais;
uint8_t space[BUFSIZE];
} buffer;
+ struct iovec iov[2];
+ struct msghdr mh;
assert(out_fd >= 0);
iov[0] = (struct iovec) { .iov_base = &resp, .iov_len = sizeof(AddrInfoResponse) };
iov[1] = (struct iovec) { .iov_base = &buffer, .iov_len = resp.header.length - sizeof(AddrInfoResponse) };
- mh.msg_iov = iov;
- mh.msg_iovlen = ELEMENTSOF(iov);
+ mh = (struct msghdr) { .msg_iov = iov, .msg_iovlen = ELEMENTSOF(iov) };
if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
return -errno;
._h_errno = _h_errno,
};
- struct msghdr mh = {};
struct iovec iov[3];
+ struct msghdr mh;
size_t hl, sl;
assert(out_fd >= 0);
iov[1] = (struct iovec) { .iov_base = (void*) host, .iov_len = hl };
iov[2] = (struct iovec) { .iov_base = (void*) serv, .iov_len = sl };
- mh.msg_iov = iov;
- mh.msg_iovlen = ELEMENTSOF(iov);
+ mh = (struct msghdr) { .msg_iov = iov, .msg_iovlen = ELEMENTSOF(iov) };
if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0)
return -errno;
req = &packet->rheader;
- assert(length >= sizeof(RHeader));
- assert(length == req->length);
+ assert_return(length >= sizeof(RHeader), -EIO);
+ assert_return(length == req->length, -EIO);
switch (req->type) {
case REQUEST_ADDRINFO: {
const AddrInfoRequest *ai_req = &packet->addrinfo_request;
- struct addrinfo hints = {}, *result = NULL;
+ struct addrinfo hints, *result = NULL;
const char *node, *service;
int ret;
- assert(length >= sizeof(AddrInfoRequest));
- assert(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len);
+ assert_return(length >= sizeof(AddrInfoRequest), -EBADMSG);
+ assert_return(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len, -EBADMSG);
- hints.ai_flags = ai_req->ai_flags;
- hints.ai_family = ai_req->ai_family;
- hints.ai_socktype = ai_req->ai_socktype;
- hints.ai_protocol = ai_req->ai_protocol;
+ hints = (struct addrinfo) {
+ .ai_flags = ai_req->ai_flags,
+ .ai_family = ai_req->ai_family,
+ .ai_socktype = ai_req->ai_socktype,
+ .ai_protocol = ai_req->ai_protocol,
+ };
node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL;
service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL;
- ret = getaddrinfo(
- node, service,
- ai_req->hints_valid ? &hints : NULL,
- &result);
+ ret = getaddrinfo(node, service,
+ ai_req->hints_valid ? &hints : NULL,
+ &result);
/* send_addrinfo_reply() frees result */
return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
union sockaddr_union sa;
int ret;
- assert(length >= sizeof(NameInfoRequest));
- assert(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len);
- assert(sizeof(sa) >= ni_req->sockaddr_len);
+ assert_return(length >= sizeof(NameInfoRequest), -EBADMSG);
+ assert_return(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len, -EBADMSG);
+ assert_return(ni_req->sockaddr_len <= sizeof(sa), -EBADMSG);
memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len);
ret = getnameinfo(&sa.sa, ni_req->sockaddr_len,
- ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
- ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
- ni_req->flags);
+ ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
+ ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
+ ni_req->flags);
return send_nameinfo_reply(out_fd, req->id, ret,
- ret == 0 && ni_req->gethost ? hostbuf : NULL,
- ret == 0 && ni_req->getserv ? servbuf : NULL,
- errno, h_errno);
+ ret == 0 && ni_req->gethost ? hostbuf : NULL,
+ ret == 0 && ni_req->getserv ? servbuf : NULL,
+ errno, h_errno);
}
case REQUEST_TERMINATE:
} buf;
ssize_t length;
- length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof(buf), 0);
+ length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof buf, 0);
if (length < 0) {
if (errno == EINTR)
continue;
if (length == 0)
break;
- if (resolve->dead)
- break;
-
if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0)
break;
}
n = CLAMP(n, WORKERS_MIN, WORKERS_MAX);
while (resolve->n_valid_workers < n) {
-
r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
if (r > 0) {
r = -r;
}
_public_ int sd_resolve_new(sd_resolve **ret) {
- sd_resolve *resolve = NULL;
- int i, r;
+ _cleanup_(sd_resolve_unrefp) sd_resolve *resolve = NULL;
+ int i;
assert_return(ret, -EINVAL);
for (i = 0; i < _FD_MAX; i++)
resolve->fds[i] = -1;
- r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD) < 0)
+ return -errno;
- r = socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
+ if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD) < 0)
+ return -errno;
for (i = 0; i < _FD_MAX; i++)
resolve->fds[i] = fd_move_above_stdio(resolve->fds[i]);
(void) fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true);
- *ret = resolve;
+ *ret = TAKE_PTR(resolve);
return 0;
-
-fail:
- sd_resolve_unref(resolve);
- return r;
}
_public_ int sd_resolve_default(sd_resolve **ret) {
RHeader req = {
.type = REQUEST_TERMINATE,
- .length = sizeof(req)
+ .length = sizeof req,
};
/* Send one termination packet for each worker */
}
_public_ sd_resolve* sd_resolve_unref(sd_resolve *resolve) {
-
if (!resolve)
return NULL;
int r;
assert(resolve);
+ assert(packet);
resp = &packet->rheader;
- assert(resp);
- assert(length >= sizeof(RHeader));
- assert(length == resp->length);
+ assert_return(length >= sizeof(RHeader), -EIO);
+ assert_return(length == resp->length, -EIO);
if (resp->type == RESPONSE_DIED) {
resolve->dead = true;
size_t l;
struct addrinfo *prev = NULL;
- assert(length >= sizeof(AddrInfoResponse));
- assert(q->type == REQUEST_ADDRINFO);
+ assert_return(length >= sizeof(AddrInfoResponse), -EBADMSG);
+ assert_return(q->type == REQUEST_ADDRINFO, -EBADMSG);
- q->ret = ai_resp->ret;
- q->_errno = ai_resp->_errno;
- q->_h_errno = ai_resp->_h_errno;
+ query_assign_errno(q, ai_resp->ret, ai_resp->_errno, ai_resp->_h_errno);
l = length - sizeof(AddrInfoResponse);
p = (const uint8_t*) resp + sizeof(AddrInfoResponse);
r = unserialize_addrinfo(&p, &l, &ai);
if (r < 0) {
- q->ret = EAI_SYSTEM;
- q->_errno = -r;
- q->_h_errno = 0;
+ query_assign_errno(q, EAI_SYSTEM, r, 0);
freeaddrinfo(q->addrinfo);
q->addrinfo = NULL;
break;
case RESPONSE_NAMEINFO: {
const NameInfoResponse *ni_resp = &packet->nameinfo_response;
- assert(length >= sizeof(NameInfoResponse));
- assert(q->type == REQUEST_NAMEINFO);
+ assert_return(length >= sizeof(NameInfoResponse), -EBADMSG);
+ assert_return(q->type == REQUEST_NAMEINFO, -EBADMSG);
if (ni_resp->hostlen > DNS_HOSTNAME_MAX ||
ni_resp->servlen > DNS_HOSTNAME_MAX ||
- sizeof(NameInfoResponse) + ni_resp->hostlen + ni_resp->servlen > length + 2) {
- q->ret = EAI_SYSTEM;
- q->_errno = -EIO;
- q->_h_errno = 0;
-
- } else {
- q->ret = ni_resp->ret;
- q->_errno = ni_resp->_errno;
- q->_h_errno = ni_resp->_h_errno;
+ sizeof(NameInfoResponse) + ni_resp->hostlen + ni_resp->servlen > length)
+ query_assign_errno(q, EAI_SYSTEM, EIO, 0);
+ else {
+ query_assign_errno(q, ni_resp->ret, ni_resp->_errno, ni_resp->_h_errno);
if (ni_resp->hostlen > 0) {
q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse),
ni_resp->hostlen-1);
- if (!q->host) {
- q->ret = EAI_MEMORY;
- q->_errno = ENOMEM;
- q->_h_errno = 0;
- }
+ if (!q->host)
+ query_assign_errno(q, EAI_MEMORY, ENOMEM, 0);
}
if (ni_resp->servlen > 0) {
q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen,
ni_resp->servlen-1);
- if (!q->serv) {
- q->ret = EAI_MEMORY;
- q->_errno = ENOMEM;
- q->_h_errno = 0;
- }
+ if (!q->serv)
+ query_assign_errno(q, EAI_MEMORY, ENOMEM, 0);
}
}
/* We don't allow recursively invoking sd_resolve_process(). */
assert_return(!resolve->current, -EBUSY);
- l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof(buf), 0);
+ l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof buf, 0);
if (l < 0) {
if (errno == EAGAIN)
return 0;
const struct addrinfo *hints,
sd_resolve_getaddrinfo_handler_t callback, void *userdata) {
- AddrInfoRequest req = {};
- struct msghdr mh = {};
+ _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL;
+ AddrInfoRequest req;
struct iovec iov[3];
- sd_resolve_query *q;
+ struct msghdr mh = {};
int r;
+ size_t node_len, service_len;
assert_return(resolve, -EINVAL);
assert_return(node || service, -EINVAL);
q->getaddrinfo_handler = callback;
q->userdata = userdata;
- req.node_len = node ? strlen(node)+1 : 0;
- req.service_len = service ? strlen(service)+1 : 0;
+ node_len = node ? strlen(node) + 1 : 0;
+ service_len = service ? strlen(service) + 1 : 0;
- req.header.id = q->id;
- req.header.type = REQUEST_ADDRINFO;
- req.header.length = sizeof(AddrInfoRequest) + req.node_len + req.service_len;
+ req = (AddrInfoRequest) {
+ .node_len = node_len,
+ .service_len = service_len,
- if (hints) {
- req.hints_valid = true;
- req.ai_flags = hints->ai_flags;
- req.ai_family = hints->ai_family;
- req.ai_socktype = hints->ai_socktype;
- req.ai_protocol = hints->ai_protocol;
- }
+ .header.id = q->id,
+ .header.type = REQUEST_ADDRINFO,
+ .header.length = sizeof(AddrInfoRequest) + node_len + service_len,
+
+ .hints_valid = hints,
+ .ai_flags = hints ? hints->ai_flags : 0,
+ .ai_family = hints ? hints->ai_family : 0,
+ .ai_socktype = hints ? hints->ai_socktype : 0,
+ .ai_protocol = hints ? hints->ai_protocol : 0,
+ };
iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(AddrInfoRequest) };
if (node)
iov[mh.msg_iovlen++] = (struct iovec) { .iov_base = (void*) service, .iov_len = req.service_len };
mh.msg_iov = iov;
- if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
- sd_resolve_query_unref(q);
+ if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0)
return -errno;
- }
resolve->n_outstanding++;
if (_q)
*_q = q;
+ TAKE_PTR(q);
return 0;
}
sd_resolve_getnameinfo_handler_t callback,
void *userdata) {
- NameInfoRequest req = {};
- struct msghdr mh = {};
+ _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL;
+ NameInfoRequest req;
struct iovec iov[2];
- sd_resolve_query *q;
+ struct msghdr mh;
int r;
assert_return(resolve, -EINVAL);
q->getnameinfo_handler = callback;
q->userdata = userdata;
- req.header.id = q->id;
- req.header.type = REQUEST_NAMEINFO;
- req.header.length = sizeof(NameInfoRequest) + salen;
+ req = (NameInfoRequest) {
+ .header.id = q->id,
+ .header.type = REQUEST_NAMEINFO,
+ .header.length = sizeof(NameInfoRequest) + salen,
- req.flags = flags;
- req.sockaddr_len = salen;
- req.gethost = !!(get & SD_RESOLVE_GET_HOST);
- req.getserv = !!(get & SD_RESOLVE_GET_SERVICE);
+ .flags = flags,
+ .sockaddr_len = salen,
+ .gethost = !!(get & SD_RESOLVE_GET_HOST),
+ .getserv = !!(get & SD_RESOLVE_GET_SERVICE),
+ };
iov[0] = (struct iovec) { .iov_base = &req, .iov_len = sizeof(NameInfoRequest) };
iov[1] = (struct iovec) { .iov_base = (void*) sa, .iov_len = salen };
- mh.msg_iov = iov;
- mh.msg_iovlen = 2;
+ mh = (struct msghdr) { .msg_iov = iov, .msg_iovlen = ELEMENTSOF(iov) };
- if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) {
- sd_resolve_query_unref(q);
+ if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0)
return -errno;
- }
-
- resolve->n_outstanding++;
if (_q)
*_q = q;
+ resolve->n_outstanding++;
+ TAKE_PTR(q);
+
return 0;
}
assert(q->getnameinfo_handler);
errno = q->_errno;
- h_errno= q->_h_errno;
+ h_errno = q->_h_errno;
return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata);
}
log_notice_errno(r, "sd_resolve_wait() timed out, but that's OK");
exit(EXIT_SUCCESS);
- break;
}
if (r < 0) {
log_error_errno(r, "sd_resolve_wait(): %m");
*/
int udev_util_encode_string(const char *str, char *str_enc, size_t len);
-
#ifdef __cplusplus
} /* extern "C" */
#endif
if (!u)
return -ENOMEM;
- strv_free(l);
- l = u;
+ strv_free_and_replace(l, u);
}
if (strv_isempty(l)) {
if (!u)
return -ENOMEM;
- strv_free(l);
- l = u;
+ strv_free_and_replace(l, u);
}
if (isempty(c->vc_keymap_toggle))
if (!u)
return -ENOMEM;
- strv_free(l);
- l = u;
+ strv_free_and_replace(l, u);
}
if (strv_isempty(l)) {
return 0;
}
-int find_legacy_keymap(Context *c, char **new_keymap) {
+int find_legacy_keymap(Context *c, char **ret) {
const char *map;
_cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *new_keymap = NULL;
unsigned n = 0;
unsigned best_matching = 0;
int r;
if (matching > best_matching) {
best_matching = matching;
- r = free_and_strdup(new_keymap, a[0]);
+ r = free_and_strdup(&new_keymap, a[0]);
if (r < 0)
return r;
}
r = find_converted_keymap(l, v, &converted);
if (r < 0)
return r;
- if (r > 0) {
- free(*new_keymap);
- *new_keymap = converted;
- }
+ if (r > 0)
+ free_and_replace(new_keymap, converted);
}
- return (bool) *new_keymap;
+ *ret = TAKE_PTR(new_keymap);
+ return (bool) *ret;
}
int find_language_fallback(const char *lang, char **language) {
static int show_status(int argc, char **argv, void *userdata) {
_cleanup_(status_info_clear) StatusInfo info = {};
static const struct bus_properties_map map[] = {
- { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
{ "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
{ "VConsoleKeymapToggle", "s", NULL, offsetof(StatusInfo, vconsole_keymap_toggle) },
{ "X11Layout", "s", NULL, offsetof(StatusInfo, x11_layout) },
#include "bus-util.h"
#include "fd-util.h"
#include "format-util.h"
+#include "pager.h"
#include "process-util.h"
#include "signal-util.h"
#include "strv.h"
static const char* arg_who = NULL;
static const char* arg_why = "Unknown reason";
static const char* arg_mode = NULL;
+static bool arg_no_pager = false;
static enum {
ACTION_INHIBIT,
unsigned n = 0;
int r;
+ (void) pager_open(arg_no_pager, false);
+
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"Execute a process while inhibiting shutdown/sleep/idle.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --no-pager Do not pipe output into a pager\n"
" --what=WHAT Operations to inhibit, colon separated list of:\n"
" shutdown, sleep, idle, handle-power-key,\n"
" handle-suspend-key, handle-hibernate-key,\n"
ARG_WHY,
ARG_MODE,
ARG_LIST,
+ ARG_NO_PAGER,
};
static const struct option options[] = {
{ "why", required_argument, NULL, ARG_WHY },
{ "mode", required_argument, NULL, ARG_MODE },
{ "list", no_argument, NULL, ARG_LIST },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
{}
};
arg_action = ACTION_LIST;
break;
+ case ARG_NO_PAGER:
+ arg_no_pager = true;
+ break;
+
case '?':
return -EINVAL;
if (arg_action == ACTION_LIST) {
r = print_inhibitors(bus, &error);
+ pager_close();
if (r < 0) {
log_error("Failed to list inhibitors: %s", bus_error_message(&error, -r));
return EXIT_FAILURE;
#include "sigbus.h"
#include "signal-util.h"
#include "spawn-polkit-agent.h"
+#include "string-table.h"
#include "strv.h"
#include "sysfs-show.h"
#include "terminal-util.h"
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
break;
case 's':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
Copyright 2012 Lennart Poettering
***/
+#include "conf-parser.h"
+
typedef enum HandleAction {
HANDLE_IGNORE,
HANDLE_POWEROFF,
HandleAction handle_action_from_string(const char *s) _pure_;
const char* manager_target_for_action(HandleAction handle);
-int config_parse_handle_action(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_handle_action);
}
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
-
-static int property_get_docked(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
-}
-
-static int property_get_current_sessions(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
-}
-
-static int property_get_current_inhibitors(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
-}
-
-static int property_get_compat_user_tasks_max(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(reply);
-
- return sd_bus_message_append(reply, "t", CGROUP_LIMIT_MAX);
-}
+static BUS_DEFINE_PROPERTY_GET(property_get_docked, "b", Manager, manager_is_docked_or_external_displays);
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_compat_user_tasks_max, "t", CGROUP_LIMIT_MAX);
+static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "t", Hashmap *, (uint64_t) hashmap_size);
static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *p = NULL;
cancelled = m->scheduled_shutdown_type != NULL;
reset_scheduled_shutdown(m);
- if (cancelled) {
+ if (cancelled && m->enable_wall_messages) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *tty = NULL;
uid_t uid = 0;
int r;
Manager *m = userdata;
char *wall_message;
- int enable_wall_messages;
+ unsigned enable_wall_messages;
assert(message);
assert(m);
SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
+ SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_hashmap_size, offsetof(Manager, inhibitors), 0),
SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
+ SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
typedef struct Inhibitor Inhibitor;
-
typedef enum InhibitWhat {
INHIBIT_SHUTDOWN = 1,
INHIBIT_SLEEP = 2,
#include "user-util.h"
#include "util.h"
+static BUS_DEFINE_PROPERTY_GET(property_get_can_multi_session, "b", Seat, seat_can_multi_session);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_tty, "b", Seat, seat_can_tty);
+static BUS_DEFINE_PROPERTY_GET(property_get_can_graphical, "b", Seat, seat_can_graphical);
+
static int property_get_active_session(
sd_bus *bus,
const char *path,
return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p);
}
-static int property_get_can_multi_session(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Seat *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", seat_can_multi_session(s));
-}
-
-static int property_get_can_tty(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Seat *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", seat_can_tty(s));
-}
-
-static int property_get_can_graphical(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Seat *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", seat_can_graphical(s));
-}
-
static int property_get_sessions(
sd_bus *bus,
const char *path,
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass);
-
-static int property_get_active(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Session *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "b", session_is_active(s));
-}
-
-static int property_get_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Session *s = userdata;
-
- assert(bus);
- assert(reply);
- assert(s);
-
- return sd_bus_message_append(reply, "s", session_state_to_string(session_get_state(s)));
-}
+static BUS_DEFINE_PROPERTY_GET(property_get_active, "b", Session, session_is_active);
+static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Session, session_get_state, session_state_to_string);
static int property_get_idle_hint(
sd_bus *bus,
#include "strv.h"
#include "user-util.h"
+static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", User, user_get_state, user_state_to_string);
+
static int property_get_display(
sd_bus *bus,
const char *path,
return sd_bus_message_append(reply, "(so)", u->display ? u->display->id : "", p);
}
-static int property_get_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- User *u = userdata;
-
- assert(bus);
- assert(reply);
- assert(u);
-
- return sd_bus_message_append(reply, "s", user_state_to_string(user_get_state(u)));
-}
-
static int property_get_sessions(
sd_bus *bus,
const char *path,
void *data,
void *userdata) {
- size_t *sz = data;
+ uint64_t *sz = data;
int r;
assert(filename);
typedef struct User User;
+#include "conf-parser.h"
#include "list.h"
#include "logind.h"
int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
-int config_parse_compat_user_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_compat_user_tasks_max);
if (!streq(parts[0], "session"))
return -EINVAL;
+
id = strdup(parts[1]);
if (!id)
return -ENOMEM;
if (!streq(parts[2], "device"))
return -EINVAL;
- r = safe_atou(parts[3], &major) ||
- safe_atou(parts[4], &minor);
+
+ r = safe_atou(parts[3], &major);
+ if (r < 0)
+ return r;
+ r = safe_atou(parts[4], &minor);
if (r < 0)
return r;
#include "sd-bus.h"
#include "sd-event.h"
+#include "conf-parser.h"
#include "hashmap.h"
#include "list.h"
#include "set.h"
usec_t holdoff_timeout_usec;
sd_event_source *lid_switch_ignore_event_source;
- size_t runtime_dir_size;
+ uint64_t runtime_dir_size;
uint64_t user_tasks_max;
uint64_t sessions_max;
uint64_t inhibitors_max;
int manager_set_lid_switch_ignore(Manager *m, usec_t until);
-int config_parse_n_autovts(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tmpfs_size(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_n_autovts);
+CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs_size);
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
'73-seat-late.rules',
input : '73-seat-late.rules.m4',
output: '73-seat-late.rules',
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : true,
install_dir : udevrulesdir)
'systemd-user',
input : 'systemd-user.m4',
output: 'systemd-user',
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : pamconfdir != 'no',
install_dir : pamconfdir)
#include "terminal-util.h"
#include "user-util.h"
-static int property_get_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Machine *m = userdata;
- const char *state;
- int r;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- state = machine_state_to_string(machine_get_state(m));
-
- r = sd_bus_message_append_basic(reply, 's', state);
- if (r < 0)
- return r;
-
- return 1;
-}
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
+static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Machine, machine_get_state, machine_state_to_string);
static int property_get_netif(
sd_bus *bus,
return sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
}
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
-
int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Machine *m = userdata;
int r;
#include "signal-util.h"
#include "spawn-polkit-agent.h"
#include "stdio-util.h"
+#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
#include "unit-name.h"
r = table_add_many(table,
TABLE_STRING, name,
TABLE_STRING, class,
- TABLE_STRING, strdash_if_empty(service),
- TABLE_STRING, strdash_if_empty(os),
- TABLE_STRING, strdash_if_empty(version_id),
- TABLE_STRING, strdash_if_empty(addresses));
+ TABLE_STRING, empty_to_dash(service),
+ TABLE_STRING, empty_to_dash(os),
+ TABLE_STRING, empty_to_dash(version_id),
+ TABLE_STRING, empty_to_dash(addresses));
if (r < 0)
return log_error_errno(r, "Failed to add table row: %m");
}
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
break;
case 's':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
break;
case ARG_VERIFY:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(import_verify, ImportVerify, _IMPORT_VERIFY_MAX);
+ return 0;
+ }
+
arg_verify = import_verify_from_string(optarg);
if (arg_verify < 0) {
log_error("Failed to parse --verify= setting: %s", optarg);
#include "unit-name.h"
#include "user-util.h"
-static int property_get_pool_path(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- assert(bus);
- assert(reply);
-
- return sd_bus_message_append(reply, "s", "/var/lib/machines");
-}
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_pool_path, "s", "/var/lib/machines");
static int property_get_pool_usage(
sd_bus *bus,
#include "missing.h"
#include "netdev/netdev.h"
-
typedef enum IPVlanMode {
NETDEV_IPVLAN_MODE_L2 = IPVLAN_MODE_L2,
NETDEV_IPVLAN_MODE_L3 = IPVLAN_MODE_L3,
#include <inttypes.h>
#include <stdbool.h>
+#include "conf-parser.h"
#include "in-addr-util.h"
typedef struct AddressLabel AddressLabel;
int address_label_configure(AddressLabel *address, Link *link, sd_netlink_message_handler_t callback, bool update);
-int config_parse_address_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_label_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_label);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix);
#include <inttypes.h>
#include <stdbool.h>
+#include "conf-parser.h"
#include "in-addr-util.h"
typedef struct Address Address;
DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free);
-int config_parse_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_broadcast(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_lifetime(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_scope(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_address);
+CONFIG_PARSER_PROTOTYPE(config_parse_broadcast);
+CONFIG_PARSER_PROTOTYPE(config_parse_label);
+CONFIG_PARSER_PROTOTYPE(config_parse_lifetime);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_flags);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_scope);
#include <stdint.h>
+#include "conf-parser.h"
+
typedef struct Link Link;
int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap);
-int config_parse_brvlan_pvid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_brvlan_vlan(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_brvlan_untagged(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_pvid);
+CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_vlan);
+CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_untagged);
Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.com>
***/
+#include "conf-parser.h"
+
typedef struct Manager Manager;
int manager_parse_config_file(Manager *m);
const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-int config_parse_duid_type(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
-int config_parse_duid_rawdata(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_duid_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_duid_rawdata);
return r;
}
+ if (link->network->dhcp_user_class) {
+ r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
+ if (r < 0)
+ return r;
+ }
+
if (link->network->dhcp_client_port) {
r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
if (r < 0)
if (r < 0)
return r;
+ route->family = AF_INET6;
+
while (n < n_prefixes) {
route_update(route, &prefix, pd_prefix_len, NULL, NULL,
0, 0, RTN_UNREACHABLE);
- r = route_configure(route, link, NULL);
+ r = route_configure(route, dhcp6_link, NULL);
if (r < 0) {
route_free(route);
return r;
Copyright (C) 2014 Intel Corporation. All rights reserved.
***/
+#include "conf-parser.h"
#include "list.h"
#include "macro.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free);
-int config_parse_fdb_hwaddr(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_fdb_vlan_id(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id);
Copyright 2017 Florian Klink <flokli@flokli.de>
***/
+#include "conf-parser.h"
#include "list.h"
#include "macro.h"
LIST_FIELDS(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses);
};
-
int ipv6_proxy_ndp_address_new_static(Network *network, IPv6ProxyNDPAddress ** ipv6_proxy_ndp_address);
void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address);
int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy_ndp_address);
DEFINE_TRIVIAL_CLEANUP_FUNC(IPv6ProxyNDPAddress*, ipv6_proxy_ndp_address_free);
-int config_parse_ipv6_proxy_ndp_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address);
if (r < 0)
return log_error_errno(r, "Failed to add network enumerator: %m");
- r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.network1", 0, NULL, NULL);
+ r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.network1", 0, NULL);
if (r < 0)
return log_error_errno(r, "Failed to request name: %m");
***/
#include "alloc-util.h"
+#include "ether-addr-util.h"
#include "networkd-manager.h"
#include "string-util.h"
#include "strv.h"
void *userdata,
sd_bus_error *error) {
- Network *n = userdata;
- const char *ether = NULL;
+ char buf[ETHER_ADDR_TO_STRING_MAX];
+ const struct ether_addr *p;
+ Iterator i;
+ Set *s;
int r;
assert(bus);
assert(reply);
- assert(n);
+ assert(userdata);
- if (n->match_mac)
- ether = ether_ntoa(n->match_mac);
+ s = *(Set **) userdata;
r = sd_bus_message_open_container(reply, 'a', "s");
if (r < 0)
return r;
- if (ether) {
- r = sd_bus_message_append(reply, "s", strempty(ether));
+ SET_FOREACH(p, s, i) {
+ r = sd_bus_message_append(reply, "s", ether_addr_to_string(p, buf));
if (r < 0)
return r;
}
SD_BUS_PROPERTY("Description", "s", NULL, offsetof(Network, description), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Network, filename), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, offsetof(Network, match_mac), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchPath", "as", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchDriver", "as", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST),
#endif
#include <stddef.h>
#include "conf-parser.h"
+#include "network-internal.h"
#include "networkd-conf.h"
#include "networkd-network.h"
-#include "network-internal.h"
#include "vlan-util.h"
%}
struct ConfigPerfItem;
%struct-type
%includes
%%
-Match.MACAddress, config_parse_hwaddr, 0, offsetof(Network, match_mac)
+Match.MACAddress, config_parse_hwaddrs, 0, offsetof(Network, match_mac)
Match.Path, config_parse_strv, 0, offsetof(Network, match_path)
Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver)
Match.Type, config_parse_strv, 0, offsetof(Network, match_type)
Route.Scope, config_parse_route_scope, 0, 0
Route.PreferredSource, config_parse_preferred_src, 0, 0
Route.Table, config_parse_route_table, 0, 0
+Route.MTUBytes, config_parse_route_mtu, AF_UNSPEC, 0
Route.GatewayOnlink, config_parse_gateway_onlink, 0, 0
Route.IPv6Preference, config_parse_ipv6_route_preference, 0, 0
Route.Protocol, config_parse_route_protocol, 0, 0
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
+DHCP.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class)
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
free(network->filename);
- free(network->match_mac);
+ set_free_free(network->match_mac);
strv_free(network->match_path);
strv_free(network->match_driver);
strv_free(network->match_type);
free(network->description);
free(network->dhcp_vendor_class_identifier);
+ strv_free(network->dhcp_user_class);
free(network->dhcp_hostname);
free(network->mac);
if (r < 0)
return r;
- if (!timezone_is_valid(tz)) {
+ if (!timezone_is_valid(tz, LOG_ERR)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Timezone is not valid, ignoring assignment: %s", rvalue);
free(tz);
return 0;
return 0;
}
+int config_parse_dhcp_user_class(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char ***l = data;
+ int r;
+
+ assert(l);
+ assert(lvalue);
+ assert(rvalue);
+
+ if (isempty(rvalue)) {
+ *l = strv_free(*l);
+ return 0;
+ }
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+
+ r = extract_first_word(&rvalue, &w, NULL, 0);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to split user classes option, ignoring: %s", rvalue);
+ break;
+ }
+ if (r == 0)
+ break;
+
+ if (strlen(w) > 255) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "%s length is not in the range 1-255, ignoring.", w);
+ continue;
+ }
+
+ r = strv_push(l, w);
+ if (r < 0)
+ return log_oom();
+
+ w = NULL;
+ }
+
+ return 0;
+}
+
int config_parse_dhcp_route_table(const char *unit,
const char *filename,
unsigned line,
#include "udev.h"
#include "condition.h"
+#include "conf-parser.h"
#include "dhcp-identifier.h"
#include "hashmap.h"
-#include "resolve-util.h"
-
-#include "networkd-address.h"
+#include "netdev/netdev.h"
#include "networkd-address-label.h"
+#include "networkd-address.h"
#include "networkd-brvlan.h"
#include "networkd-fdb.h"
-#include "networkd-lldp-tx.h"
#include "networkd-ipv6-proxy-ndp.h"
+#include "networkd-lldp-tx.h"
#include "networkd-radv.h"
#include "networkd-route.h"
#include "networkd-routing-policy-rule.h"
#include "networkd-util.h"
-#include "netdev/netdev.h"
+#include "resolve-util.h"
#define DHCP_ROUTE_METRIC 1024
#define IPV4LL_ROUTE_METRIC 2048
char *filename;
char *name;
- struct ether_addr *match_mac;
+ Set *match_mac;
char **match_path;
char **match_driver;
char **match_type;
AddressFamilyBoolean dhcp;
DHCPClientIdentifier dhcp_client_identifier;
char *dhcp_vendor_class_identifier;
+ char **dhcp_user_class;
char *dhcp_hostname;
unsigned dhcp_route_metric;
uint32_t dhcp_route_table;
bool network_has_static_ipv6_addresses(Network *network);
-int config_parse_netdev(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tunnel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_client_identifier(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ipv6token(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ipv6_privacy_extensions(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_timezone(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_server_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_radv_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_radv_search_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssec_negative_trust_anchors(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_lldp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_netdev);
+CONFIG_PARSER_PROTOTYPE(config_parse_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_tunnel);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
+CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
+CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_route_table);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
+CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
/* Legacy IPv4LL support */
-int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
Copyright 2017 Intel Corporation. All rights reserved.
***/
+#include "conf-parser.h"
#include "networkd-address.h"
#include "networkd-link.h"
int prefix_new(Prefix **ret);
void prefix_free(Prefix *prefix);
-int prefix_new_static(Network *network, const char *filename, unsigned section,
- Prefix **ret);
+int prefix_new_static(Network *network, const char *filename, unsigned section, Prefix **ret);
DEFINE_TRIVIAL_CLEANUP_FUNC(Prefix*, prefix_free);
-int config_parse_router_prefix_delegation(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_router_preference(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_prefix_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_prefix_lifetime(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation);
+CONFIG_PARSER_PROTOTYPE(config_parse_router_preference);
+CONFIG_PARSER_PROTOTYPE(config_parse_prefix);
+CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags);
+CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime);
int radv_emit_dns(Link *link);
int radv_configure(Link *link);
return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, tos, priority, table, ret);
}
-int route_add(
- Link *link,
+int route_add(Link *link,
int family,
const union in_addr_union *dst,
unsigned char dst_prefixlen,
}
void route_update(Route *route,
- const union in_addr_union *src,
- unsigned char src_prefixlen,
- const union in_addr_union *gw,
- const union in_addr_union *prefsrc,
- unsigned char scope,
- unsigned char protocol,
- unsigned char type) {
+ const union in_addr_union *src,
+ unsigned char src_prefixlen,
+ const union in_addr_union *gw,
+ const union in_addr_union *prefsrc,
+ unsigned char scope,
+ unsigned char protocol,
+ unsigned char type) {
assert(route);
- assert(src);
- assert(gw);
- assert(prefsrc);
+ assert(src || src_prefixlen == 0);
- route->src = *src;
+ route->src = src ? *src : (union in_addr_union) {};
route->src_prefixlen = src_prefixlen;
- route->gw = *gw;
- route->prefsrc = *prefsrc;
+ route->gw = gw ? *gw : (union in_addr_union) {};
+ route->prefsrc = prefsrc ? *prefsrc : (union in_addr_union) {};
route->scope = scope;
route->protocol = protocol;
route->type = type;
}
int route_remove(Route *route, Link *link,
- sd_netlink_message_handler_t callback) {
+ sd_netlink_message_handler_t callback) {
+
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
return 0;
}
-int config_parse_gateway(const char *unit,
+int config_parse_gateway(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
return 0;
}
-int config_parse_preferred_src(const char *unit,
+int config_parse_preferred_src(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
return 0;
}
-int config_parse_destination(const char *unit,
+int config_parse_destination(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
return 0;
}
-int config_parse_route_priority(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_priority(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
uint32_t k;
return 0;
}
-int config_parse_route_scope(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_scope(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
int r;
return 0;
}
-int config_parse_route_table(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_table(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
_cleanup_(route_freep) Route *n = NULL;
Network *network = userdata;
uint32_t k;
}
n->table = k;
-
n = NULL;
return 0;
}
-int config_parse_gateway_onlink(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_gateway_onlink(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
int r;
return 0;
}
-int config_parse_ipv6_route_preference(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_ipv6_route_preference(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
int r;
return 0;
}
-int config_parse_route_protocol(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_protocol(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
int r;
return 0;
}
-int config_parse_route_type(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_route_type(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
Network *network = userdata;
_cleanup_(route_freep) Route *n = NULL;
int r;
return 0;
}
-int config_parse_tcp_window(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_tcp_window(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
_cleanup_(route_freep) Route *n = NULL;
Network *network = userdata;
uint64_t k;
return 0;
}
-int config_parse_quickack(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_quickack(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
_cleanup_(route_freep) Route *n = NULL;
Network *network = userdata;
int k, r;
return 0;
}
+
+int config_parse_route_mtu(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *network = userdata;
+ _cleanup_(route_freep) Route *n = NULL;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = route_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &n->mtu, userdata);
+ if (r < 0)
+ return r;
+
+ n = NULL;
+
+ return 0;
+}
Copyright 2013 Tom Gundersen <teg@jklm.no>
***/
+#include "conf-parser.h"
+
typedef struct Route Route;
typedef struct NetworkConfigSection NetworkConfigSection;
DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
-int config_parse_gateway(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_preferred_src(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_destination(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_scope(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_gateway_onlink(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_ipv6_route_preference(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_protocol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_route_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tcp_window(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_quickack(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
+CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src);
+CONFIG_PARSER_PROTOTYPE(config_parse_destination);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_priority);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_scope);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_table);
+CONFIG_PARSER_PROTOTYPE(config_parse_gateway_onlink);
+CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_route_preference);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_protocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);
+CONFIG_PARSER_PROTOTYPE(config_parse_quickack);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
#include <stdbool.h>
#include "in-addr-util.h"
+#include "conf-parser.h"
typedef struct RoutingPolicyRule RoutingPolicyRule;
int routing_policy_load_rules(const char *state_file, Set **rules);
void routing_policy_rule_purge(Manager *m, Link *link);
-int config_parse_routing_policy_rule_tos(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data,void *userdata);
-int config_parse_routing_policy_rule_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_routing_policy_rule_fwmark_mask(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_routing_policy_rule_prefix(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_routing_policy_rule_priority(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data,void *userdata);
-int config_parse_routing_policy_rule_device(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data,void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_tos);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_table);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_fwmark_mask);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_prefix);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_priority);
+CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_device);
Copyright 2013 Tom Gundersen <teg@jklm.no>
***/
+#include "conf-parser.h"
#include "macro.h"
typedef enum AddressFamilyBoolean {
_ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
} AddressFamilyBoolean;
-int config_parse_address_family_boolean(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_address_family_boolean_with_kernel(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_family_boolean);
+CONFIG_PARSER_PROTOTYPE(config_parse_address_family_boolean_with_kernel);
const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
Copyright 2016 Zbigniew Jędrzejewski-Szmek
***/
+#include "ether-addr-util.h"
#include "hexdecoct.h"
#include "log.h"
#include "macro.h"
+#include "set.h"
#include "string-util.h"
-#include "ether-addr-util.h"
+#include "network-internal.h"
#include "networkd-conf.h"
#include "networkd-network.h"
-#include "network-internal.h"
static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected) {
DUIDType actual = 0;
assert_se(ret == r);
if (expected) {
assert_se(actual);
- assert(ether_addr_equal(expected, actual));
- } else {
+ assert_se(ether_addr_equal(expected, actual));
+ } else
assert_se(actual == NULL);
- }
+
free(actual);
}
+static void test_config_parse_hwaddrs_one(const char *rvalue, const struct ether_addr* list, size_t n) {
+ _cleanup_set_free_free_ Set *s = NULL;
+ size_t m;
+
+ assert_se(config_parse_hwaddrs("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &s, NULL) == 0);
+ assert_se(set_size(s) == n);
+
+ for (m = 0; m < n; m++) {
+ _cleanup_free_ struct ether_addr *q = NULL;
+
+ assert_se(q = set_remove(s, &list[m]));
+ }
+
+ assert_se(set_size(s) == 0);
+}
+
#define BYTES_0_128 "0:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:2f:30:31:32:33:34:35:36:37:38:39:3a:3b:3c:3d:3e:3f:40:41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54:55:56:57:58:59:5a:5b:5c:5d:5e:5f:60:61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:78:79:7a:7b:7c:7d:7e:7f:80"
#define BYTES_1_128 {0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80}
{ .ether_addr_octet = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } },
{ .ether_addr_octet = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } },
};
+
test_config_parse_hwaddr_one("", 0, NULL);
test_config_parse_hwaddr_one("no:ta:ma:ca:dd:re", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:fx", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff", 0, &t[0]);
test_config_parse_hwaddr_one(" aa:bb:cc:dd:ee:ff", 0, &t[0]);
- test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\n", 0, &t[0]);
+ test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\n", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\nxxx", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc: dd:ee:ff", 0, NULL);
test_config_parse_hwaddr_one("aa:bb:cc:d d:ee:ff", 0, NULL);
test_config_parse_hwaddr_one("aabbccddee:ff", 0, NULL);
test_config_parse_hwaddr_one("012345.6789ab", 0, NULL);
test_config_parse_hwaddr_one("123.4567.89ab", 0, &t[1]);
+
+ test_config_parse_hwaddrs_one("", t, 0);
+ test_config_parse_hwaddrs_one("no:ta:ma:ca:dd:re", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:fx", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff", t, 1);
+ test_config_parse_hwaddrs_one(" aa:bb:cc:dd:ee:ff", t, 1);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff \t\n", t, 1);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff \t\nxxx", t, 1);
+ test_config_parse_hwaddrs_one("aa:bb:cc: dd:ee:ff", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:d d:ee:ff", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee", t, 0);
+ test_config_parse_hwaddrs_one("9:aa:bb:cc:dd:ee:ff", t, 0);
+ test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff:gg", t, 0);
+ test_config_parse_hwaddrs_one("aa:Bb:CC:dd:ee:ff", t, 1);
+ test_config_parse_hwaddrs_one("01:23:45:67:89:aB", &t[1], 1);
+ test_config_parse_hwaddrs_one("1:23:45:67:89:aB", &t[1], 1);
+ test_config_parse_hwaddrs_one("aa-bb-cc-dd-ee-ff", t, 1);
+ test_config_parse_hwaddrs_one("AA-BB-CC-DD-EE-FF", t, 1);
+ test_config_parse_hwaddrs_one("01-23-45-67-89-ab", &t[1], 1);
+ test_config_parse_hwaddrs_one("aabb.ccdd.eeff", t, 1);
+ test_config_parse_hwaddrs_one("0123.4567.89ab", &t[1], 1);
+ test_config_parse_hwaddrs_one("123.4567.89ab.", t, 0);
+ test_config_parse_hwaddrs_one("aabbcc.ddeeff", t, 0);
+ test_config_parse_hwaddrs_one("aabbccddeeff", t, 0);
+ test_config_parse_hwaddrs_one("aabbccddee:ff", t, 0);
+ test_config_parse_hwaddrs_one("012345.6789ab", t, 0);
+ test_config_parse_hwaddrs_one("123.4567.89ab", &t[1], 1);
+
+ test_config_parse_hwaddrs_one("123.4567.89ab aa:bb:cc:dd:ee:ff 01-23-45-67-89-ab aa:Bb:CC:dd:ee:ff", t, 2);
+ test_config_parse_hwaddrs_one("123.4567.89ab aa:bb:cc:dd:ee:fx hogehoge 01-23-45-67-89-ab aaaa aa:Bb:CC:dd:ee:ff", t, 2);
}
int main(int argc, char **argv) {
return r;
}
-int create_subcgroup(pid_t pid, CGroupUnified unified_requested) {
+int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested) {
_cleanup_free_ char *cgroup = NULL;
- const char *child;
- int r;
CGroupMask supported;
+ const char *payload;
+ int r;
- /* In the unified hierarchy inner nodes may only contain
- * subgroups, but not processes. Hence, if we running in the
- * unified hierarchy and the container does the same, and we
- * did not create a scope unit for the container move us and
- * the container into two separate subcgroups. */
-
- if (unified_requested == CGROUP_UNIFIED_NONE)
- return 0;
-
- r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
- if (r < 0)
- return log_error_errno(r, "Failed to determine whether the systemd controller is unified: %m");
- if (r == 0)
- return 0;
+ assert(pid > 1);
+
+ /* In the unified hierarchy inner nodes may only contain subgroups, but not processes. Hence, if we running in
+ * the unified hierarchy and the container does the same, and we did not create a scope unit for the container
+ * move us and the container into two separate subcgroups.
+ *
+ * Moreover, container payloads such as systemd try to manage the cgroup they run in in full (i.e. including
+ * its attributes), while the host systemd will only delegate cgroups for children of the cgroup created for a
+ * delegation unit, instead of the cgroup itself. This means, if we'd pass on the cgroup allocated from the
+ * host systemd directly to the payload, the host and payload systemd might fight for the cgroup
+ * attributes. Hence, let's insert an intermediary cgroup to cover that case too.
+ *
+ * Note that we only bother with the main hierarchy here, not with any secondary ones. On the unified setup
+ * that's fine because there's only one hiearchy anyway and controllers are enabled directly on it. On the
+ * legacy setup, this is fine too, since delegation of controllers is generally not safe there, hence we won't
+ * do it. */
r = cg_mask_supported(&supported);
if (r < 0)
return log_error_errno(r, "Failed to determine supported controllers: %m");
- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
+ if (keep_unit)
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
+ else
+ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
if (r < 0)
return log_error_errno(r, "Failed to get our control group: %m");
- child = strjoina(cgroup, "/payload");
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, pid);
+ payload = strjoina(cgroup, "/payload");
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, payload, pid);
if (r < 0)
- return log_error_errno(r, "Failed to create %s subcgroup: %m", child);
+ return log_error_errno(r, "Failed to create %s subcgroup: %m", payload);
- child = strjoina(cgroup, "/supervisor");
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to create %s subcgroup: %m", child);
+ if (keep_unit) {
+ const char *supervisor;
+
+ supervisor = strjoina(cgroup, "/supervisor");
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, supervisor, 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create %s subcgroup: %m", supervisor);
+ }
/* Try to enable as many controllers as possible for the new payload. */
(void) cg_enable_everywhere(supported, supported, cgroup);
int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
-int create_subcgroup(pid_t pid, CGroupUnified unified_requested);
+int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested);
%struct-type
%includes
%%
-Exec.Boot, config_parse_boot, 0, 0
-Exec.ProcessTwo, config_parse_pid2, 0, 0
-Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
-Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
-Exec.User, config_parse_string, 0, offsetof(Settings, user)
-Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
-Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
-Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal)
-Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality)
-Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id)
-Exec.WorkingDirectory, config_parse_path, 0, offsetof(Settings, working_directory)
-Exec.PivotRoot, config_parse_pivot_root, 0, 0
-Exec.PrivateUsers, config_parse_private_users, 0, 0
-Exec.NotifyReady, config_parse_bool, 0, offsetof(Settings, notify_ready)
-Exec.SystemCallFilter, config_parse_syscall_filter,0, 0,
-Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
-Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
-Files.Bind, config_parse_bind, 0, 0
-Files.BindReadOnly, config_parse_bind, 1, 0
-Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0
-Files.Overlay, config_parse_overlay, 0, 0
-Files.OverlayReadOnly, config_parse_overlay, 1, 0
-Files.PrivateUsersChown, config_parse_tristate, 0, offsetof(Settings, userns_chown)
-Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
-Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces)
-Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan)
-Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan)
-Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
-Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0
-Network.Bridge, config_parse_ifname, 0, offsetof(Settings, network_bridge)
-Network.Zone, config_parse_network_zone, 0, 0
-Network.Port, config_parse_expose_port, 0, 0
+Exec.Boot, config_parse_boot, 0, 0
+Exec.ProcessTwo, config_parse_pid2, 0, 0
+Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
+Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
+Exec.User, config_parse_string, 0, offsetof(Settings, user)
+Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
+Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
+Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal)
+Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality)
+Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id)
+Exec.WorkingDirectory, config_parse_path, 0, offsetof(Settings, working_directory)
+Exec.PivotRoot, config_parse_pivot_root, 0, 0
+Exec.PrivateUsers, config_parse_private_users, 0, 0
+Exec.NotifyReady, config_parse_bool, 0, offsetof(Settings, notify_ready)
+Exec.SystemCallFilter, config_parse_syscall_filter, 0, 0,
+Exec.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof(Settings, rlimit)
+Exec.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof(Settings, rlimit)
+Exec.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof(Settings, rlimit)
+Exec.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof(Settings, rlimit)
+Exec.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof(Settings, rlimit)
+Exec.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof(Settings, rlimit)
+Exec.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof(Settings, rlimit)
+Exec.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof(Settings, rlimit)
+Exec.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof(Settings, rlimit)
+Exec.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof(Settings, rlimit)
+Exec.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof(Settings, rlimit)
+Exec.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof(Settings, rlimit)
+Exec.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof(Settings, rlimit)
+Exec.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof(Settings, rlimit)
+Exec.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof(Settings, rlimit)
+Exec.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof(Settings, rlimit)
+Exec.Hostname, config_parse_hostname, 0, offsetof(Settings, hostname)
+Exec.NoNewPrivileges, config_parse_tristate, 0, offsetof(Settings, no_new_privileges)
+Exec.OOMScoreAdjust, config_parse_oom_score_adjust, 0, 0
+Exec.CPUAffinity, config_parse_cpu_affinity, 0, 0
+Exec.ResolvConf, config_parse_resolv_conf, 0, offsetof(Settings, resolv_conf)
+Exec.LinkJournal, config_parse_link_journal, 0, 0
+Exec.Timezone, config_parse_timezone, 0, offsetof(Settings, timezone)
+Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
+Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
+Files.Bind, config_parse_bind, 0, 0
+Files.BindReadOnly, config_parse_bind, 1, 0
+Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0
+Files.Overlay, config_parse_overlay, 0, 0
+Files.OverlayReadOnly, config_parse_overlay, 1, 0
+Files.PrivateUsersChown, config_parse_tristate, 0, offsetof(Settings, userns_chown)
+Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network)
+Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces)
+Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan)
+Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan)
+Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth)
+Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0
+Network.Bridge, config_parse_ifname, 0, offsetof(Settings, network_bridge)
+Network.Zone, config_parse_network_zone, 0, 0
+Network.Port, config_parse_expose_port, 0, 0
#include "user-util.h"
#include "util.h"
-CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) {
+CustomMount* custom_mount_add(CustomMount **l, size_t *n, CustomMountType t) {
CustomMount *c, *ret;
assert(l);
return ret;
}
-void custom_mount_free_all(CustomMount *l, unsigned n) {
- unsigned i;
+void custom_mount_free_all(CustomMount *l, size_t n) {
+ size_t i;
for (i = 0; i < n; i++) {
CustomMount *m = l + i;
return strdup(source);
}
-int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
- unsigned i;
+int custom_mount_prepare_all(const char *dest, CustomMount *l, size_t n) {
+ size_t i;
int r;
/* Prepare all custom mounts. This will make source we know all temporary directories. This is called in the
if (!s)
return log_oom();
- free(m->source);
- m->source = s;
+ free_and_replace(m->source, s);
} else {
/* No source specified? In that case, use a throw-away temporary directory in /var/tmp */
if (!s)
return log_oom();
- free(*j);
- *j = s;
+ free_and_replace(*j, s);
}
if (m->work_dir) {
if (!s)
return log_oom();
- free(m->work_dir);
- m->work_dir = s;
+ free_and_replace(m->work_dir, s);
} else {
assert(m->source);
return 0;
}
-int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only) {
+int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) {
_cleanup_free_ char *source = NULL, *destination = NULL, *opts = NULL;
const char *p = s;
CustomMount *m;
return 0;
}
-int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s) {
+int tmpfs_mount_parse(CustomMount **l, size_t *n, const char *s) {
_cleanup_free_ char *path = NULL, *opts = NULL;
const char *p = s;
CustomMount *m;
return 0;
}
-int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only) {
+int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) {
_cleanup_free_ char *upper = NULL, *destination = NULL;
_cleanup_strv_free_ char **lower = NULL;
CustomMount *m;
uid_t uid_shift, uid_t uid_range,
const char *selinux_apifs_context) {
+#define PROC_INACCESSIBLE(path) \
+ { NULL, (path), NULL, NULL, MS_BIND, \
+ MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_INACCESSIBLE_REG }, /* Bind mount first ... */ \
+ { NULL, (path), NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, \
+ MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO } /* Then, make it r/o */
+
+#define PROC_READ_ONLY(path) \
+ { (path), (path), NULL, NULL, MS_BIND, \
+ MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */ \
+ { NULL, (path), NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, \
+ MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO } /* Then, make it r/o */
+
typedef struct MountPoint {
const char *what;
const char *where;
} MountPoint;
static const MountPoint mount_table[] = {
- /* inner child mounts */
- { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_IN_USERNS },
- { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
- { "/proc/sys/net", "/proc/sys/net", NULL, NULL, MS_BIND, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS }, /* (except for this) */
- { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
- { "/proc/sysrq-trigger", "/proc/sysrq-trigger", NULL, NULL, MS_BIND, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
- { NULL, "/proc/sysrq-trigger", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
-
- /* outer child mounts */
- { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
- { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
- { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */
- { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL }, /* skipped if above was mounted */
-
- { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, MOUNT_FATAL },
- { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
- { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
+ /* First we list inner child mounts (i.e. mounts applied *after* entering user namespacing) */
+ { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ MOUNT_FATAL|MOUNT_IN_USERNS },
+
+ { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND,
+ MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
+
+ { "/proc/sys/net", "/proc/sys/net", NULL, NULL, MS_BIND,
+ MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS }, /* (except for this) */
+
+ { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
+ MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
+
+ /* Make these files inaccessible to container payloads: they potentially leak information about kernel
+ * internals or the host's execution environment to the container */
+ PROC_INACCESSIBLE("/proc/kallsyms"),
+ PROC_INACCESSIBLE("/proc/kcore"),
+ PROC_INACCESSIBLE("/proc/keys"),
+ PROC_INACCESSIBLE("/proc/sysrq-trigger"),
+ PROC_INACCESSIBLE("/proc/timer_list"),
+
+ /* Make these directories read-only to container payloads: they show hardware information, and in some
+ * cases contain tunables the container really shouldn't have access to. */
+ PROC_READ_ONLY("/proc/acpi"),
+ PROC_READ_ONLY("/proc/apm"),
+ PROC_READ_ONLY("/proc/asound"),
+ PROC_READ_ONLY("/proc/bus"),
+ PROC_READ_ONLY("/proc/fs"),
+ PROC_READ_ONLY("/proc/irq"),
+ PROC_READ_ONLY("/proc/scsi"),
+
+ /* Then we list outer child mounts (i.e. mounts applied *before* entering user namespacing) */
+ { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
+ MOUNT_FATAL },
+ { "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
+ { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */
+ { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
+ MOUNT_FATAL }, /* skipped if above was mounted */
+ { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME,
+ MOUNT_FATAL },
+ { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
+ MOUNT_FATAL },
+ { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
+ MOUNT_FATAL },
+
#if HAVE_SELINUX
- { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, 0 }, /* Bind mount first */
- { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, 0 }, /* Then, make it r/o */
+ { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND,
+ 0 }, /* Bind mount first */
+ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
+ 0 }, /* Then, make it r/o */
#endif
};
- unsigned k;
- int r;
+ _cleanup_(unlink_and_freep) char *inaccessible = NULL;
bool use_userns = (mount_settings & MOUNT_USE_USERNS);
bool netns = (mount_settings & MOUNT_APPLY_APIVFS_NETNS);
bool ro = (mount_settings & MOUNT_APPLY_APIVFS_RO);
bool in_userns = (mount_settings & MOUNT_IN_USERNS);
+ size_t k;
+ int r;
for (k = 0; k < ELEMENTSOF(mount_table); k++) {
_cleanup_free_ char *where = NULL, *options = NULL;
- const char *o;
+ const char *o, *what;
bool fatal = (mount_table[k].mount_settings & MOUNT_FATAL);
if (in_userns != (bool)(mount_table[k].mount_settings & MOUNT_IN_USERNS))
if (r < 0)
return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].where);
+ if (mount_table[k].mount_settings & MOUNT_INACCESSIBLE_REG) {
+
+ if (!inaccessible) {
+ _cleanup_free_ char *np = NULL;
+
+ r = tempfn_random_child(NULL, "inaccessible", &np);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate inaccessible file node path: %m");
+
+ r = touch_file(np, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0000);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create inaccessible file node '%s': %m", np);
+
+ inaccessible = TAKE_PTR(np);
+ }
+
+ what = inaccessible;
+ } else
+ what = mount_table[k].what;
+
r = path_is_mount_point(where, NULL, 0);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to detect whether %s is a mount point: %m", where);
/* Skip this entry if it is not a remount. */
- if (mount_table[k].what && r > 0)
+ if (what && r > 0)
continue;
r = mkdir_userns_p(dest, where, 0755, mount_settings, uid_shift);
}
r = mount_verbose(fatal ? LOG_ERR : LOG_DEBUG,
- mount_table[k].what,
+ what,
where,
mount_table[k].type,
mount_table[k].flags,
int mount_custom(
const char *dest,
- CustomMount *mounts, unsigned n,
+ CustomMount *mounts, size_t n,
bool userns, uid_t uid_shift, uid_t uid_range,
const char *selinux_apifs_context) {
- unsigned i;
+ size_t i;
int r;
assert(dest);
#include "volatile-util.h"
typedef enum MountSettingsMask {
- MOUNT_FATAL = 1 << 0, /* if set, a mount error is considered fatal */
- MOUNT_USE_USERNS = 1 << 1, /* if set, mounts are patched considering uid/gid shifts in a user namespace */
- MOUNT_IN_USERNS = 1 << 2, /* if set, the mount is executed in the inner child, otherwise in the outer child */
- MOUNT_APPLY_APIVFS_RO = 1 << 3, /* if set, /proc/sys, and /sysfs will be mounted read-only, otherwise read-write. */
- MOUNT_APPLY_APIVFS_NETNS = 1 << 4, /* if set, /proc/sys/net will be mounted read-write.
- Works only if MOUNT_APPLY_APIVFS_RO is also set. */
+ MOUNT_FATAL = 1U << 0, /* if set, a mount error is considered fatal */
+ MOUNT_USE_USERNS = 1U << 1, /* if set, mounts are patched considering uid/gid shifts in a user namespace */
+ MOUNT_IN_USERNS = 1U << 2, /* if set, the mount is executed in the inner child, otherwise in the outer child */
+ MOUNT_APPLY_APIVFS_RO = 1U << 3, /* if set, /proc/sys, and /sys will be mounted read-only, otherwise read-write. */
+ MOUNT_APPLY_APIVFS_NETNS = 1U << 4, /* if set, /proc/sys/net will be mounted read-write.
+ Works only if MOUNT_APPLY_APIVFS_RO is also set. */
+ MOUNT_INACCESSIBLE_REG = 1U << 5, /* if set, create an inaccessible regular file first and use as bind mount source */
} MountSettingsMask;
typedef enum CustomMountType {
char *rm_rf_tmpdir;
} CustomMount;
-CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t);
-void custom_mount_free_all(CustomMount *l, unsigned n);
-int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n);
+CustomMount* custom_mount_add(CustomMount **l, size_t *n, CustomMountType t);
+void custom_mount_free_all(CustomMount *l, size_t n);
+int custom_mount_prepare_all(const char *dest, CustomMount *l, size_t n);
-int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only);
-int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s);
-int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only);
+int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only);
+int tmpfs_mount_parse(CustomMount **l, size_t *n, const char *s);
+int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only);
int mount_all(const char *dest, MountSettingsMask mount_settings, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
int mount_sysfs(const char *dest, MountSettingsMask mount_settings);
int mount_cgroups(const char *dest, CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns);
int mount_systemd_cgroup_writable(const char *dest, CGroupUnified unified_requested);
-int mount_custom(const char *dest, CustomMount *mounts, unsigned n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
+int mount_custom(const char *dest, CustomMount *mounts, size_t n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
int setup_volatile(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
int setup_volatile_state(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
#include "bus-unit-util.h"
#include "bus-util.h"
#include "nspawn-register.h"
+#include "special.h"
#include "stat-util.h"
#include "strv.h"
#include "util.h"
"PIDs", "au", 1, pid,
"Description", "s", description,
"Delegate", "b", 1,
- "Slice", "s", isempty(slice) ? "machine.slice" : slice);
+ "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
if (r < 0)
return bus_log_create_error(r);
#include "alloc-util.h"
#include "cap-list.h"
#include "conf-parser.h"
+#include "cpu-set-util.h"
+#include "hostname-util.h"
#include "nspawn-network.h"
#include "nspawn-settings.h"
#include "parse-util.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
s->start_mode = _START_MODE_INVALID;
s->personality = PERSONALITY_INVALID;
s->userns_mode = _USER_NAMESPACE_MODE_INVALID;
+ s->resolv_conf = _RESOLV_CONF_MODE_INVALID;
+ s->link_journal = _LINK_JOURNAL_INVALID;
+ s->timezone = _TIMEZONE_MODE_INVALID;
s->uid_shift = UID_INVALID;
s->uid_range = UID_INVALID;
+ s->no_new_privileges = -1;
s->read_only = -1;
s->volatile_mode = _VOLATILE_MODE_INVALID;
free(s->working_directory);
strv_free(s->syscall_whitelist);
strv_free(s->syscall_blacklist);
+ rlimit_free_all(s->rlimit);
+ free(s->hostname);
+ s->cpuset = cpu_set_mfree(s->cpuset);
strv_free(s->network_interfaces);
strv_free(s->network_macvlan);
return 0;
}
+
+int config_parse_hostname(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char **s = data;
+
+ assert(rvalue);
+ assert(s);
+
+ if (!hostname_is_valid(rvalue, false)) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid hostname, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (free_and_strdup(s, empty_to_null(rvalue)) < 0)
+ return log_oom();
+
+ return 0;
+}
+
+int config_parse_oom_score_adjust(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Settings *settings = data;
+ int oa, r;
+
+ assert(rvalue);
+ assert(settings);
+
+ if (isempty(rvalue)) {
+ settings->oom_score_adjust_set = false;
+ return 0;
+ }
+
+ r = parse_oom_score_adjust(rvalue, &oa);
+ if (r == -ERANGE) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ settings->oom_score_adjust = oa;
+ settings->oom_score_adjust_set = true;
+
+ return 0;
+}
+
+int config_parse_cpu_affinity(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
+ Settings *settings = data;
+ int ncpus;
+
+ assert(rvalue);
+ assert(settings);
+
+ ncpus = parse_cpu_set_and_warn(rvalue, &cpuset, unit, filename, line, lvalue);
+ if (ncpus < 0)
+ return ncpus;
+
+ if (ncpus == 0) {
+ /* An empty assignment resets the CPU list */
+ settings->cpuset = cpu_set_mfree(settings->cpuset);
+ settings->cpuset_ncpus = 0;
+ return 0;
+ }
+
+ if (!settings->cpuset) {
+ settings->cpuset = TAKE_PTR(cpuset);
+ settings->cpuset_ncpus = (unsigned) ncpus;
+ return 0;
+ }
+
+ if (settings->cpuset_ncpus < (unsigned) ncpus) {
+ CPU_OR_S(CPU_ALLOC_SIZE(settings->cpuset_ncpus), cpuset, settings->cpuset, cpuset);
+ CPU_FREE(settings->cpuset);
+ settings->cpuset = TAKE_PTR(cpuset);
+ settings->cpuset_ncpus = (unsigned) ncpus;
+ return 0;
+ }
+
+ CPU_OR_S(CPU_ALLOC_SIZE((unsigned) ncpus), settings->cpuset, settings->cpuset, cpuset);
+
+ return 0;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_resolv_conf, resolv_conf_mode, ResolvConfMode, "Failed to parse resolv.conf mode");
+
+static const char *const resolv_conf_mode_table[_RESOLV_CONF_MODE_MAX] = {
+ [RESOLV_CONF_OFF] = "off",
+ [RESOLV_CONF_COPY_HOST] = "copy-host",
+ [RESOLV_CONF_COPY_STATIC] = "copy-static",
+ [RESOLV_CONF_BIND_HOST] = "bind-host",
+ [RESOLV_CONF_BIND_STATIC] = "bind-static",
+ [RESOLV_CONF_DELETE] = "delete",
+ [RESOLV_CONF_AUTO] = "auto",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolv_conf_mode, ResolvConfMode, RESOLV_CONF_AUTO);
+
+int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try) {
+ assert(s);
+ assert(ret_mode);
+ assert(ret_try);
+
+ if (streq(s, "auto")) {
+ *ret_mode = LINK_AUTO;
+ *ret_try = false;
+ } else if (streq(s, "no")) {
+ *ret_mode = LINK_NO;
+ *ret_try = false;
+ } else if (streq(s, "guest")) {
+ *ret_mode = LINK_GUEST;
+ *ret_try = false;
+ } else if (streq(s, "host")) {
+ *ret_mode = LINK_HOST;
+ *ret_try = false;
+ } else if (streq(s, "try-guest")) {
+ *ret_mode = LINK_GUEST;
+ *ret_try = true;
+ } else if (streq(s, "try-host")) {
+ *ret_mode = LINK_HOST;
+ *ret_try = true;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+int config_parse_link_journal(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Settings *settings = data;
+ int r;
+
+ assert(rvalue);
+ assert(settings);
+
+ r = parse_link_journal(rvalue, &settings->link_journal, &settings->link_journal_try);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse link journal mode, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ return 0;
+}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_timezone, timezone_mode, TimezoneMode, "Failed to parse timezone mode");
+
+static const char *const timezone_mode_table[_TIMEZONE_MODE_MAX] = {
+ [TIMEZONE_OFF] = "off",
+ [TIMEZONE_COPY] = "copy",
+ [TIMEZONE_BIND] = "bind",
+ [TIMEZONE_SYMLINK] = "symlink",
+ [TIMEZONE_DELETE] = "delete",
+ [TIMEZONE_AUTO] = "auto",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(timezone_mode, TimezoneMode, TIMEZONE_AUTO);
Copyright 2015 Lennart Poettering
***/
+#include <sched.h>
#include <stdio.h>
#include "sd-id128.h"
+#include "conf-parser.h"
#include "macro.h"
#include "nspawn-expose-ports.h"
#include "nspawn-mount.h"
_USER_NAMESPACE_MODE_INVALID = -1,
} UserNamespaceMode;
+typedef enum ResolvConfMode {
+ RESOLV_CONF_OFF,
+ RESOLV_CONF_COPY_HOST,
+ RESOLV_CONF_COPY_STATIC,
+ RESOLV_CONF_BIND_HOST,
+ RESOLV_CONF_BIND_STATIC,
+ RESOLV_CONF_DELETE,
+ RESOLV_CONF_AUTO,
+ _RESOLV_CONF_MODE_MAX,
+ _RESOLV_CONF_MODE_INVALID = -1
+} ResolvConfMode;
+
+typedef enum LinkJournal {
+ LINK_NO,
+ LINK_AUTO,
+ LINK_HOST,
+ LINK_GUEST,
+ _LINK_JOURNAL_MAX,
+ _LINK_JOURNAL_INVALID = -1
+} LinkJournal;
+
+typedef enum TimezoneMode {
+ TIMEZONE_OFF,
+ TIMEZONE_COPY,
+ TIMEZONE_BIND,
+ TIMEZONE_SYMLINK,
+ TIMEZONE_DELETE,
+ TIMEZONE_AUTO,
+ _TIMEZONE_MODE_MAX,
+ _TIMEZONE_MODE_INVALID = -1
+} TimezoneMode;
+
typedef enum SettingsMask {
- SETTING_START_MODE = 1 << 0,
- SETTING_ENVIRONMENT = 1 << 1,
- SETTING_USER = 1 << 2,
- SETTING_CAPABILITY = 1 << 3,
- SETTING_KILL_SIGNAL = 1 << 4,
- SETTING_PERSONALITY = 1 << 5,
- SETTING_MACHINE_ID = 1 << 6,
- SETTING_NETWORK = 1 << 7,
- SETTING_EXPOSE_PORTS = 1 << 8,
- SETTING_READ_ONLY = 1 << 9,
- SETTING_VOLATILE_MODE = 1 << 10,
- SETTING_CUSTOM_MOUNTS = 1 << 11,
- SETTING_WORKING_DIRECTORY = 1 << 12,
- SETTING_USERNS = 1 << 13,
- SETTING_NOTIFY_READY = 1 << 14,
- SETTING_PIVOT_ROOT = 1 << 15,
- SETTING_SYSCALL_FILTER = 1 << 16,
- _SETTINGS_MASK_ALL = (1 << 17) -1
+ SETTING_START_MODE = UINT64_C(1) << 0,
+ SETTING_ENVIRONMENT = UINT64_C(1) << 1,
+ SETTING_USER = UINT64_C(1) << 2,
+ SETTING_CAPABILITY = UINT64_C(1) << 3,
+ SETTING_KILL_SIGNAL = UINT64_C(1) << 4,
+ SETTING_PERSONALITY = UINT64_C(1) << 5,
+ SETTING_MACHINE_ID = UINT64_C(1) << 6,
+ SETTING_NETWORK = UINT64_C(1) << 7,
+ SETTING_EXPOSE_PORTS = UINT64_C(1) << 8,
+ SETTING_READ_ONLY = UINT64_C(1) << 9,
+ SETTING_VOLATILE_MODE = UINT64_C(1) << 10,
+ SETTING_CUSTOM_MOUNTS = UINT64_C(1) << 11,
+ SETTING_WORKING_DIRECTORY = UINT64_C(1) << 12,
+ SETTING_USERNS = UINT64_C(1) << 13,
+ SETTING_NOTIFY_READY = UINT64_C(1) << 14,
+ SETTING_PIVOT_ROOT = UINT64_C(1) << 15,
+ SETTING_SYSCALL_FILTER = UINT64_C(1) << 16,
+ SETTING_HOSTNAME = UINT64_C(1) << 17,
+ SETTING_NO_NEW_PRIVILEGES = UINT64_C(1) << 18,
+ SETTING_OOM_SCORE_ADJUST = UINT64_C(1) << 19,
+ SETTING_CPU_AFFINITY = UINT64_C(1) << 20,
+ SETTING_RESOLV_CONF = UINT64_C(1) << 21,
+ SETTING_LINK_JOURNAL = UINT64_C(1) << 22,
+ SETTING_TIMEZONE = UINT64_C(1) << 23,
+ SETTING_RLIMIT_FIRST = UINT64_C(1) << 24, /* we define one bit per resource limit here */
+ SETTING_RLIMIT_LAST = UINT64_C(1) << (24 + _RLIMIT_MAX - 1),
+ _SETTINGS_MASK_ALL = (UINT64_C(1) << (24 + _RLIMIT_MAX)) -1,
+ _SETTING_FORCE_ENUM_WIDTH = UINT64_MAX
} SettingsMask;
+/* We want to use SETTING_RLIMIT_FIRST in shifts, so make sure it is really 64 bits
+ * when used in expressions. */
+#define SETTING_RLIMIT_FIRST ((uint64_t) SETTING_RLIMIT_FIRST)
+#define SETTING_RLIMIT_LAST ((uint64_t) SETTING_RLIMIT_LAST)
+
+assert_cc(sizeof(SettingsMask) == 8);
+assert_cc(sizeof(SETTING_RLIMIT_FIRST) == 8);
+assert_cc(sizeof(SETTING_RLIMIT_LAST) == 8);
+
typedef struct Settings {
/* [Run] */
StartMode start_mode;
bool notify_ready;
char **syscall_whitelist;
char **syscall_blacklist;
+ struct rlimit *rlimit[_RLIMIT_MAX];
+ char *hostname;
+ int no_new_privileges;
+ int oom_score_adjust;
+ bool oom_score_adjust_set;
+ cpu_set_t *cpuset;
+ unsigned cpuset_ncpus;
+ ResolvConfMode resolv_conf;
+ LinkJournal link_journal;
+ bool link_journal_try;
+ TimezoneMode timezone;
/* [Image] */
int read_only;
VolatileMode volatile_mode;
CustomMount *custom_mounts;
- unsigned n_custom_mounts;
+ size_t n_custom_mounts;
int userns_chown;
/* [Network] */
const struct ConfigPerfItem* nspawn_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-int config_parse_capability(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_id128(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_expose_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_volatile_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_pivot_root(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_bind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_tmpfs(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_overlay(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_veth_extra(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_network_zone(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_boot(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_pid2(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_private_users(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_syscall_filter(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_capability);
+CONFIG_PARSER_PROTOTYPE(config_parse_id128);
+CONFIG_PARSER_PROTOTYPE(config_parse_expose_port);
+CONFIG_PARSER_PROTOTYPE(config_parse_volatile_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_pivot_root);
+CONFIG_PARSER_PROTOTYPE(config_parse_bind);
+CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs);
+CONFIG_PARSER_PROTOTYPE(config_parse_overlay);
+CONFIG_PARSER_PROTOTYPE(config_parse_veth_extra);
+CONFIG_PARSER_PROTOTYPE(config_parse_network_zone);
+CONFIG_PARSER_PROTOTYPE(config_parse_boot);
+CONFIG_PARSER_PROTOTYPE(config_parse_pid2);
+CONFIG_PARSER_PROTOTYPE(config_parse_private_users);
+CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter);
+CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
+CONFIG_PARSER_PROTOTYPE(config_parse_oom_score_adjust);
+CONFIG_PARSER_PROTOTYPE(config_parse_cpu_affinity);
+CONFIG_PARSER_PROTOTYPE(config_parse_resolv_conf);
+CONFIG_PARSER_PROTOTYPE(config_parse_link_journal);
+CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
+
+const char *resolv_conf_mode_to_string(ResolvConfMode a) _const_;
+ResolvConfMode resolv_conf_mode_from_string(const char *s) _pure_;
+
+const char *timezone_mode_to_string(TimezoneMode a) _const_;
+TimezoneMode timezone_mode_from_string(const char *s) _pure_;
+
+int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try);
#include "base-filesystem.h"
#include "blkid-util.h"
#include "btrfs-util.h"
+#include "bus-error.h"
#include "bus-util.h"
#include "cap-list.h"
#include "capability-util.h"
#include "cgroup-util.h"
#include "copy.h"
+#include "cpu-set-util.h"
#include "dev-setup.h"
#include "dissect-image.h"
#include "env-util.h"
#include "nspawn-settings.h"
#include "nspawn-setuid.h"
#include "nspawn-stub-pid1.h"
+#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "ptyfwd.h"
#include "random-util.h"
#include "raw-clone.h"
+#include "rlimit-util.h"
#include "rm-rf.h"
#include "selinux-util.h"
#include "signal-util.h"
#include "socket-util.h"
#include "stat-util.h"
#include "stdio-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
CONTAINER_REBOOTED
} ContainerStatus;
-typedef enum LinkJournal {
- LINK_NO,
- LINK_AUTO,
- LINK_HOST,
- LINK_GUEST
-} LinkJournal;
-
static char *arg_directory = NULL;
static char *arg_template = NULL;
static char *arg_chdir = NULL;
static char *arg_pivot_root_old = NULL;
static char *arg_user = NULL;
static sd_id128_t arg_uuid = {};
-static char *arg_machine = NULL;
+static char *arg_machine = NULL; /* The name used by the host to refer to this */
+static char *arg_hostname = NULL; /* The name the payload sees by default */
static const char *arg_selinux_context = NULL;
static const char *arg_selinux_apifs_context = NULL;
static const char *arg_slice = NULL;
(1ULL << CAP_SYS_RESOURCE) |
(1ULL << CAP_SYS_TTY_CONFIG);
static CustomMount *arg_custom_mounts = NULL;
-static unsigned arg_n_custom_mounts = 0;
+static size_t arg_n_custom_mounts = 0;
static char **arg_setenv = NULL;
static bool arg_quiet = false;
static bool arg_register = true;
static size_t arg_root_hash_size = 0;
static char **arg_syscall_whitelist = NULL;
static char **arg_syscall_blacklist = NULL;
+static struct rlimit *arg_rlimit[_RLIMIT_MAX] = {};
+static bool arg_no_new_privileges = false;
+static int arg_oom_score_adjust = 0;
+static bool arg_oom_score_adjust_set = false;
+static cpu_set_t *arg_cpuset = NULL;
+static unsigned arg_cpuset_ncpus = 0;
+static ResolvConfMode arg_resolv_conf = RESOLV_CONF_AUTO;
+static TimezoneMode arg_timezone = TIMEZONE_AUTO;
static void help(void) {
+
+ (void) pager_open(false, false);
+
printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
"Spawn a minimal namespace container for debugging, testing and building.\n\n"
" -h --help Show this help\n"
" Pivot root to given directory in the container\n"
" -u --user=USER Run the command under specified user or uid\n"
" -M --machine=NAME Set the machine name for the container\n"
+ " --hostname=NAME Override the hostname for the container\n"
" --uuid=UUID Set a specific machine UUID for the container\n"
" -S --slice=SLICE Place the container in the specified slice\n"
" --property=NAME=VALUE Set scope unit property\n"
" --drop-capability=CAP Drop the specified capability from the default set\n"
" --system-call-filter=LIST|~LIST\n"
" Permit/prohibit specific system calls\n"
+ " --rlimit=NAME=LIMIT Set a resource limit for the payload\n"
+ " --oom-score-adjust=VALUE\n"
+ " Adjust the OOM score value for the payload\n"
+ " --cpu-affinity=CPUS Adjust the CPU affinity of the container\n"
" --kill-signal=SIGNAL Select signal to use for shutting down PID 1\n"
" --link-journal=MODE Link up guest journal, one of no, auto, guest, \n"
" host, try-guest, try-host\n"
" -j Equivalent to --link-journal=try-guest\n"
+ " --resolv-conf=MODE Select mode of /etc/resolv.conf initialization\n"
+ " --timezone=MODE Select mode of /etc/localtime initialization\n"
" --read-only Mount the root directory read-only\n"
" --bind=PATH[:PATH[:OPTIONS]]\n"
" Bind mount a file or directory from the host into\n"
}
static int custom_mount_check_all(void) {
- unsigned i;
+ size_t i;
for (i = 0; i < arg_n_custom_mounts; i++) {
CustomMount *m = &arg_custom_mounts[i];
ARG_NOTIFY_READY,
ARG_ROOT_HASH,
ARG_SYSTEM_CALL_FILTER,
+ ARG_RLIMIT,
+ ARG_HOSTNAME,
+ ARG_NO_NEW_PRIVILEGES,
+ ARG_OOM_SCORE_ADJUST,
+ ARG_CPU_AFFINITY,
+ ARG_RESOLV_CONF,
+ ARG_TIMEZONE,
};
static const struct option options[] = {
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
{ "capability", required_argument, NULL, ARG_CAPABILITY },
{ "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY },
+ { "no-new-privileges", required_argument, NULL, ARG_NO_NEW_PRIVILEGES },
{ "link-journal", required_argument, NULL, ARG_LINK_JOURNAL },
{ "bind", required_argument, NULL, ARG_BIND },
{ "bind-ro", required_argument, NULL, ARG_BIND_RO },
{ "overlay", required_argument, NULL, ARG_OVERLAY },
{ "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO },
{ "machine", required_argument, NULL, 'M' },
+ { "hostname", required_argument, NULL, ARG_HOSTNAME },
{ "slice", required_argument, NULL, 'S' },
{ "setenv", required_argument, NULL, 'E' },
{ "selinux-context", required_argument, NULL, 'Z' },
{ "notify-ready", required_argument, NULL, ARG_NOTIFY_READY },
{ "root-hash", required_argument, NULL, ARG_ROOT_HASH },
{ "system-call-filter", required_argument, NULL, ARG_SYSTEM_CALL_FILTER },
+ { "rlimit", required_argument, NULL, ARG_RLIMIT },
+ { "oom-score-adjust", required_argument, NULL, ARG_OOM_SCORE_ADJUST },
+ { "cpu-affinity", required_argument, NULL, ARG_CPU_AFFINITY },
+ { "resolv-conf", required_argument, NULL, ARG_RESOLV_CONF },
+ { "timezone", required_argument, NULL, ARG_TIMEZONE },
{}
};
}
break;
+ case ARG_HOSTNAME:
+ if (isempty(optarg))
+ arg_hostname = mfree(arg_hostname);
+ else {
+ if (!hostname_is_valid(optarg, false)) {
+ log_error("Invalid hostname: %s", optarg);
+ return -EINVAL;
+ }
+
+ r = free_and_strdup(&arg_hostname, optarg);
+ if (r < 0)
+ return log_oom();
+ }
+
+ arg_settings_mask |= SETTING_HOSTNAME;
+ break;
+
case 'Z':
arg_selinux_context = optarg;
break;
break;
}
+ case ARG_NO_NEW_PRIVILEGES:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --no-new-privileges= argument: %s", optarg);
+
+ arg_no_new_privileges = r;
+ arg_settings_mask |= SETTING_NO_NEW_PRIVILEGES;
+ break;
+
case 'j':
arg_link_journal = LINK_GUEST;
arg_link_journal_try = true;
+ arg_settings_mask |= SETTING_LINK_JOURNAL;
break;
case ARG_LINK_JOURNAL:
- if (streq(optarg, "auto")) {
- arg_link_journal = LINK_AUTO;
- arg_link_journal_try = false;
- } else if (streq(optarg, "no")) {
- arg_link_journal = LINK_NO;
- arg_link_journal_try = false;
- } else if (streq(optarg, "guest")) {
- arg_link_journal = LINK_GUEST;
- arg_link_journal_try = false;
- } else if (streq(optarg, "host")) {
- arg_link_journal = LINK_HOST;
- arg_link_journal_try = false;
- } else if (streq(optarg, "try-guest")) {
- arg_link_journal = LINK_GUEST;
- arg_link_journal_try = true;
- } else if (streq(optarg, "try-host")) {
- arg_link_journal = LINK_HOST;
- arg_link_journal_try = true;
- } else {
- log_error("Failed to parse link journal mode %s", optarg);
+ r = parse_link_journal(optarg, &arg_link_journal, &arg_link_journal_try);
+ if (r < 0) {
+ log_error_errno(r, "Failed to parse link journal mode %s", optarg);
return -EINVAL;
}
+ arg_settings_mask |= SETTING_LINK_JOURNAL;
break;
case ARG_BIND:
if (!n)
return log_oom();
- strv_free(arg_setenv);
- arg_setenv = n;
-
+ strv_free_and_replace(arg_setenv, n);
arg_settings_mask |= SETTING_ENVIRONMENT;
break;
}
case ARG_SHARE_SYSTEM:
/* We don't officially support this anymore, except for compat reasons. People should use the
* $SYSTEMD_NSPAWN_SHARE_* environment variables instead. */
+ log_warning("Please do not use --share-system anymore, use $SYSTEMD_NSPAWN_SHARE_* instead.");
arg_clone_ns_flags = 0;
break;
if (!optarg)
arg_volatile_mode = VOLATILE_YES;
- else {
+ else if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(volatile_mode, VolatileMode, _VOLATILE_MODE_MAX);
+ return 0;
+ } else {
VolatileMode m;
m = volatile_mode_from_string(optarg);
break;
case ARG_KILL_SIGNAL:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
arg_kill_signal = signal_from_string(optarg);
if (arg_kill_signal < 0) {
log_error("Cannot parse signal: %s", optarg);
break;
}
+ case ARG_RLIMIT: {
+ const char *eq;
+ char *name;
+ int rl;
+
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(rlimit, int, _RLIMIT_MAX);
+ return 0;
+ }
+
+ eq = strchr(optarg, '=');
+ if (!eq) {
+ log_error("--rlimit= expects an '=' assignment.");
+ return -EINVAL;
+ }
+
+ name = strndup(optarg, eq - optarg);
+ if (!name)
+ return log_oom();
+
+ rl = rlimit_from_string_harder(name);
+ if (rl < 0) {
+ log_error("Unknown resource limit: %s", name);
+ return -EINVAL;
+ }
+
+ if (!arg_rlimit[rl]) {
+ arg_rlimit[rl] = new0(struct rlimit, 1);
+ if (!arg_rlimit[rl])
+ return log_oom();
+ }
+
+ r = rlimit_parse(rl, eq + 1, arg_rlimit[rl]);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse resource limit: %s", eq + 1);
+
+ arg_settings_mask |= SETTING_RLIMIT_FIRST << rl;
+ break;
+ }
+
+ case ARG_OOM_SCORE_ADJUST:
+ r = parse_oom_score_adjust(optarg, &arg_oom_score_adjust);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --oom-score-adjust= parameter: %s", optarg);
+
+ arg_oom_score_adjust_set = true;
+ arg_settings_mask |= SETTING_OOM_SCORE_ADJUST;
+ break;
+
+ case ARG_CPU_AFFINITY: {
+ _cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
+
+ r = parse_cpu_set(optarg, &cpuset);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse CPU affinity mask: %s", optarg);
+
+ if (arg_cpuset)
+ CPU_FREE(arg_cpuset);
+
+ arg_cpuset = TAKE_PTR(cpuset);
+ arg_cpuset_ncpus = r;
+ arg_settings_mask |= SETTING_CPU_AFFINITY;
+ break;
+ }
+
+ case ARG_RESOLV_CONF:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(resolv_conf_mode, ResolvConfMode, _RESOLV_CONF_MODE_MAX);
+ return 0;
+ }
+
+ arg_resolv_conf = resolv_conf_mode_from_string(optarg);
+ if (arg_resolv_conf < 0) {
+ log_error("Failed to parse /etc/resolv.conf mode: %s", optarg);
+ return -EINVAL;
+ }
+
+ arg_settings_mask |= SETTING_RESOLV_CONF;
+ break;
+
+ case ARG_TIMEZONE:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(timezone_mode, TimezoneMode, _TIMEZONE_MODE_MAX);
+ return 0;
+ }
+
+ arg_timezone = timezone_mode_from_string(optarg);
+ if (arg_timezone < 0) {
+ log_error("Failed to parse /etc/localtime mode: %s", optarg);
+ return -EINVAL;
+ }
+
+ arg_settings_mask |= SETTING_TIMEZONE;
+ break;
+
case '?':
return -EINVAL;
return userns_lchown(q, uid, gid);
}
+static const char *timezone_from_path(const char *path) {
+ const char *z;
+
+ z = path_startswith(path, "../usr/share/zoneinfo/");
+ if (z)
+ return z;
+
+ z = path_startswith(path, "/usr/share/zoneinfo/");
+ if (z)
+ return z;
+
+ return NULL;
+}
+
static int setup_timezone(const char *dest) {
- _cleanup_free_ char *p = NULL, *q = NULL;
- const char *where, *check, *what;
- char *z, *y;
+ _cleanup_free_ char *p = NULL, *etc = NULL;
+ const char *where, *check;
+ TimezoneMode m;
int r;
assert(dest);
- /* Fix the timezone, if possible */
- r = readlink_malloc("/etc/localtime", &p);
+ if (IN_SET(arg_timezone, TIMEZONE_AUTO, TIMEZONE_SYMLINK)) {
+
+ r = readlink_malloc("/etc/localtime", &p);
+ if (r == -ENOENT && arg_timezone == TIMEZONE_AUTO)
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? TIMEZONE_OFF : TIMEZONE_DELETE;
+ else if (r == -EINVAL && arg_timezone == TIMEZONE_AUTO) /* regular file? */
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? TIMEZONE_BIND : TIMEZONE_COPY;
+ else if (r < 0) {
+ log_warning_errno(r, "Failed to read host's /etc/localtime symlink, not updating container timezone: %m");
+ /* To handle warning, delete /etc/localtime and replace it with a symbolic link to a time zone data
+ * file.
+ *
+ * Example:
+ * ln -s /usr/share/zoneinfo/UTC /etc/localtime
+ */
+ return 0;
+ } else if (arg_timezone == TIMEZONE_AUTO)
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? TIMEZONE_BIND : TIMEZONE_SYMLINK;
+ else
+ m = arg_timezone;
+ } else
+ m = arg_timezone;
+
+ if (m == TIMEZONE_OFF)
+ return 0;
+
+ r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
if (r < 0) {
- log_warning("host's /etc/localtime is not a symlink, not updating container timezone.");
- /* to handle warning, delete /etc/localtime and replace it
- * with a symbolic link to a time zone data file.
- *
- * Example:
- * ln -s /usr/share/zoneinfo/UTC /etc/localtime
- */
+ log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m");
return 0;
}
- z = path_startswith(p, "../usr/share/zoneinfo/");
- if (!z)
- z = path_startswith(p, "/usr/share/zoneinfo/");
- if (!z) {
- log_warning("/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone.");
+ where = strjoina(etc, "/localtime");
+
+ switch (m) {
+
+ case TIMEZONE_DELETE:
+ if (unlink(where) < 0)
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to remove '%s', ignoring: %m", where);
+
return 0;
- }
- where = prefix_roota(dest, "/etc/localtime");
- r = readlink_malloc(where, &q);
- if (r >= 0) {
- y = path_startswith(q, "../usr/share/zoneinfo/");
- if (!y)
- y = path_startswith(q, "/usr/share/zoneinfo/");
+ case TIMEZONE_SYMLINK: {
+ _cleanup_free_ char *q = NULL;
+ const char *z, *what;
- /* Already pointing to the right place? Then do nothing .. */
- if (y && streq(y, z))
+ z = timezone_from_path(p);
+ if (!z) {
+ log_warning("/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone.");
return 0;
- }
+ }
- check = strjoina("/usr/share/zoneinfo/", z);
- check = prefix_roota(dest, check);
- if (laccess(check, F_OK) < 0) {
- log_warning("Timezone %s does not exist in container, not updating container timezone.", z);
- return 0;
+ r = readlink_malloc(where, &q);
+ if (r >= 0 && streq_ptr(timezone_from_path(q), z))
+ return 0; /* Already pointing to the right place? Then do nothing .. */
+
+ check = strjoina(dest, "/usr/share/zoneinfo/", z);
+ r = chase_symlinks(check, dest, 0, NULL);
+ if (r < 0)
+ log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z);
+ else {
+ if (unlink(where) < 0 && errno != ENOENT) {
+ log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING, /* Don't complain on read-only images */
+ errno, "Failed to remove existing timezone info %s in container, ignoring: %m", where);
+ return 0;
+ }
+
+ what = strjoina("../usr/share/zoneinfo/", z);
+ if (symlink(what, where) < 0) {
+ log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING,
+ errno, "Failed to correct timezone of container, ignoring: %m");
+ return 0;
+ }
+
+ break;
+ }
+
+ _fallthrough_;
}
- if (unlink(where) < 0 && errno != ENOENT) {
- log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING, /* Don't complain on read-only images */
- errno,
- "Failed to remove existing timezone info %s in container, ignoring: %m", where);
- return 0;
+ case TIMEZONE_BIND: {
+ _cleanup_free_ char *resolved = NULL;
+ int found;
+
+ found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
+ if (found < 0) {
+ log_warning_errno(found, "Failed to resolve /etc/localtime path in container, ignoring: %m");
+ return 0;
+ }
+
+ if (found == 0) /* missing? */
+ (void) touch(resolved);
+
+ r = mount_verbose(LOG_WARNING, "/etc/localtime", resolved, NULL, MS_BIND, NULL);
+ if (r >= 0)
+ return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL);
+
+ _fallthrough_;
}
- what = strjoina("../usr/share/zoneinfo/", z);
- if (symlink(what, where) < 0) {
- log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING,
- errno,
- "Failed to correct timezone of container, ignoring: %m");
- return 0;
+ case TIMEZONE_COPY:
+ /* If mounting failed, try to copy */
+ r = copy_file_atomic("/etc/localtime", where, 0644, 0, COPY_REFLINK|COPY_REPLACE);
+ if (r < 0) {
+ log_full_errno(IN_SET(r, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to copy /etc/localtime to %s, ignoring: %m", where);
+ return 0;
+ }
+
+ break;
+
+ default:
+ assert_not_reached("unexpected mode");
}
+ /* Fix permissions of the symlink or file copy we just created */
r = userns_lchown(where, 0, 0);
if (r < 0)
- return log_warning_errno(r, "Failed to chown /etc/localtime: %m");
+ log_warning_errno(r, "Failed to chown /etc/localtime, ignoring: %m");
return 0;
}
+static int have_resolv_conf(const char *path) {
+ assert(path);
+
+ if (access(path, F_OK) < 0) {
+ if (errno == ENOENT)
+ return 0;
+
+ return log_debug_errno(errno, "Failed to determine whether '%s' is available: %m", path);
+ }
+
+ return 1;
+}
+
static int resolved_listening(void) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_free_ char *dns_stub_listener_mode = NULL;
int r;
r = sd_bus_open_system(&bus);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to open system bus: %m");
r = bus_name_has_owner(bus, "org.freedesktop.resolve1", NULL);
- if (r <= 0)
- return r;
+ if (r < 0)
+ return log_debug_errno(r, "Failed to check whether the 'org.freedesktop.resolve1' bus name is taken: %m");
+ if (r == 0)
+ return 0;
r = sd_bus_get_property_string(bus,
"org.freedesktop.resolve1",
"/org/freedesktop/resolve1",
"org.freedesktop.resolve1.Manager",
"DNSStubListener",
- NULL,
+ &error,
&dns_stub_listener_mode);
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to query DNSStubListener property: %s", bus_error_message(&error, r));
return STR_IN_SET(dns_stub_listener_mode, "udp", "yes");
}
static int setup_resolv_conf(const char *dest) {
- _cleanup_free_ char *resolved = NULL, *etc = NULL;
- const char *where;
- int r, found;
+ _cleanup_free_ char *etc = NULL;
+ const char *where, *what;
+ ResolvConfMode m;
+ int r;
assert(dest);
- if (arg_private_network)
+ if (arg_resolv_conf == RESOLV_CONF_AUTO) {
+ if (arg_private_network)
+ m = RESOLV_CONF_OFF;
+ else if (have_resolv_conf(STATIC_RESOLV_CONF) > 0 && resolved_listening() > 0)
+ /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the
+ * container, so that the container can use the host's resolver. Given that network namespacing is
+ * disabled it's only natural of the container also uses the host's resolver. It also has the big
+ * advantage that the container will be able to follow the host's DNS server configuration changes
+ * transparently. */
+ m = RESOLV_CONF_BIND_STATIC;
+ else if (have_resolv_conf("/etc/resolv.conf") > 0)
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? RESOLV_CONF_BIND_HOST : RESOLV_CONF_COPY_HOST;
+ else
+ m = arg_read_only && arg_volatile_mode != VOLATILE_YES ? RESOLV_CONF_OFF : RESOLV_CONF_DELETE;
+ } else
+ m = arg_resolv_conf;
+
+ if (m == RESOLV_CONF_OFF)
return 0;
r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc);
}
where = strjoina(etc, "/resolv.conf");
- found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
- if (found < 0) {
- log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m");
+
+ if (m == RESOLV_CONF_DELETE) {
+ if (unlink(where) < 0)
+ log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to remove '%s', ignoring: %m", where);
+
return 0;
}
- if (access(STATIC_RESOLV_CONF, F_OK) >= 0 &&
- resolved_listening() > 0) {
+ if (IN_SET(m, RESOLV_CONF_BIND_STATIC, RESOLV_CONF_COPY_STATIC))
+ what = STATIC_RESOLV_CONF;
+ else
+ what = "/etc/resolv.conf";
- /* resolved is enabled on the host. In this, case bind mount its static resolv.conf file into the
- * container, so that the container can use the host's resolver. Given that network namespacing is
- * disabled it's only natural of the container also uses the host's resolver. It also has the big
- * advantage that the container will be able to follow the host's DNS server configuration changes
- * transparently. */
+ if (IN_SET(m, RESOLV_CONF_BIND_HOST, RESOLV_CONF_BIND_STATIC)) {
+ _cleanup_free_ char *resolved = NULL;
+ int found;
+
+ found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved);
+ if (found < 0) {
+ log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m");
+ return 0;
+ }
if (found == 0) /* missing? */
(void) touch(resolved);
- r = mount_verbose(LOG_DEBUG, STATIC_RESOLV_CONF, resolved, NULL, MS_BIND, NULL);
+ r = mount_verbose(LOG_WARNING, what, resolved, NULL, MS_BIND, NULL);
if (r >= 0)
return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL);
}
/* If that didn't work, let's copy the file */
- r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644, 0, COPY_REFLINK);
+ r = copy_file(what, where, O_TRUNC|O_NOFOLLOW, 0644, 0, COPY_REFLINK);
if (r < 0) {
/* If the file already exists as symlink, let's suppress the warning, under the assumption that
* resolved or something similar runs inside and the symlink points there.
*
* If the disk image is read-only, there's also no point in complaining.
*/
- log_full_errno(IN_SET(r, -ELOOP, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
+ log_full_errno(!IN_SET(RESOLV_CONF_COPY_HOST, RESOLV_CONF_COPY_STATIC) && IN_SET(r, -ELOOP, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to copy /etc/resolv.conf to %s, ignoring: %m", where);
return 0;
}
}
static int setup_boot_id(void) {
+ _cleanup_(unlink_and_freep) char *from = NULL;
+ _cleanup_free_ char *path = NULL;
sd_id128_t rnd = SD_ID128_NULL;
- const char *from, *to;
+ const char *to;
int r;
/* Generate a new randomized boot ID, so that each boot-up of
* the container gets a new one */
- from = "/run/proc-sys-kernel-random-boot-id";
- to = "/proc/sys/kernel/random/boot_id";
+ r = tempfn_random_child(NULL, "proc-sys-kernel-random-boot-id", &path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate random boot ID path: %m");
r = sd_id128_randomize(&rnd);
if (r < 0)
return log_error_errno(r, "Failed to generate random boot id: %m");
- r = id128_write(from, ID128_UUID, rnd, false);
+ r = id128_write(path, ID128_UUID, rnd, false);
if (r < 0)
return log_error_errno(r, "Failed to write boot id: %m");
+ from = TAKE_PTR(path);
+ to = "/proc/sys/kernel/random/boot_id";
+
r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL);
- if (r >= 0)
- r = mount_verbose(LOG_ERR, NULL, to, NULL,
- MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL);
+ if (r < 0)
+ return r;
- (void) unlink(from);
- return r;
+ return mount_verbose(LOG_ERR, NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
}
static int copy_devnodes(const char *dest) {
}
static int setup_kmsg(int kmsg_socket) {
- const char *from, *to;
+ _cleanup_(unlink_and_freep) char *from = NULL;
+ _cleanup_free_ char *fifo = NULL;
+ _cleanup_close_ int fd = -1;
_cleanup_umask_ mode_t u;
- int fd, r;
+ const char *to;
+ int r;
assert(kmsg_socket >= 0);
u = umask(0000);
- /* We create the kmsg FIFO as /run/kmsg, but immediately
- * delete it after bind mounting it to /proc/kmsg. While FIFOs
- * on the reading side behave very similar to /proc/kmsg,
- * their writing side behaves differently from /dev/kmsg in
- * that writing blocks when nothing is reading. In order to
- * avoid any problems with containers deadlocking due to this
- * we simply make /dev/kmsg unavailable to the container. */
- from = "/run/kmsg";
- to = "/proc/kmsg";
+ /* We create the kmsg FIFO as as temporary file in /tmp, but immediately delete it after bind mounting it to
+ * /proc/kmsg. While FIFOs on the reading side behave very similar to /proc/kmsg, their writing side behaves
+ * differently from /dev/kmsg in that writing blocks when nothing is reading. In order to avoid any problems
+ * with containers deadlocking due to this we simply make /dev/kmsg unavailable to the container. */
+
+ r = tempfn_random_child(NULL, "proc-kmsg", &fifo);
+ if (r < 0)
+ return log_error_errno(r, "Failed to generate kmsg path: %m");
- if (mkfifo(from, 0600) < 0)
+ if (mkfifo(fifo, 0600) < 0)
return log_error_errno(errno, "mkfifo() for /run/kmsg failed: %m");
+
+ from = TAKE_PTR(fifo);
+ to = "/proc/kmsg";
+
r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL);
if (r < 0)
return r;
if (fd < 0)
return log_error_errno(errno, "Failed to open fifo: %m");
- /* Store away the fd in the socket, so that it stays open as
- * long as we run the child */
+ /* Store away the fd in the socket, so that it stays open as long as we run the child */
r = send_one_fd(kmsg_socket, fd, 0);
- safe_close(fd);
-
if (r < 0)
return log_error_errno(r, "Failed to send FIFO fd: %m");
- /* And now make the FIFO unavailable as /run/kmsg... */
- (void) unlink(from);
-
return 0;
}
}
static int setup_hostname(void) {
+ int r;
if ((arg_clone_ns_flags & CLONE_NEWUTS) == 0)
return 0;
- if (sethostname_idempotent(arg_machine) < 0)
- return -errno;
+ r = sethostname_idempotent(arg_hostname ?: arg_machine);
+ if (r < 0)
+ return log_error_errno(r, "Failed to set hostname: %m");
return 0;
}
_cleanup_free_ char *home = NULL;
char as_uuid[37];
- unsigned n_env = 1;
+ size_t n_env = 1;
const char *envp[] = {
"PATH=" DEFAULT_PATH_COMPAT,
NULL, /* container */
NULL
};
const char *exec_target;
-
_cleanup_strv_free_ char **env_use = NULL;
int r;
rtnl_socket = safe_close(rtnl_socket);
}
+ if (arg_oom_score_adjust_set) {
+ r = set_oom_score_adjust(arg_oom_score_adjust);
+ if (r < 0)
+ return log_error_errno(r, "Failed to adjust OOM score: %m");
+ }
+
+ if (arg_cpuset)
+ if (sched_setaffinity(0, CPU_ALLOC_SIZE(arg_cpuset_ncpus), arg_cpuset) < 0)
+ return log_error_errno(errno, "Failed to set CPU affinity: %m");
+
r = drop_capabilities();
if (r < 0)
return log_error_errno(r, "drop_capabilities() failed: %m");
- setup_hostname();
+ (void) setup_hostname();
if (arg_personality != PERSONALITY_INVALID) {
r = safe_personality(arg_personality);
if (r < 0)
return r;
+ if (arg_no_new_privileges)
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
+ return log_error_errno(errno, "Failed to disable new privileges: %m");
+
/* LXC sets container=lxc, so follow the scheme here */
envp[n_env++] = strjoina("container=", arg_container_service_name);
return r;
}
- /* Now, explicitly close the log, so that we
- * then can close all remaining fds. Closing
- * the log explicitly first has the benefit
- * that the logging subsystem knows about it,
- * and is thus ready to be reopened should we
- * need it again. Note that the other fds
- * closed here are at least the locking and
- * barrier fds. */
+ /* Now, explicitly close the log, so that we then can close all remaining fds. Closing the log explicitly first
+ * has the benefit that the logging subsystem knows about it, and is thus ready to be reopened should we need
+ * it again. Note that the other fds closed here are at least the locking and barrier fds. */
log_close();
+ log_set_open_when_needed(true);
+
(void) fdset_close_others(fds);
if (arg_start_mode == START_BOOT) {
exec_target = "/bin/bash, /bin/sh";
}
- r = -errno;
- (void) log_open();
- return log_error_errno(r, "execv(%s) failed: %m", exec_target);
+ return log_error_errno(errno, "execv(%s) failed: %m", exec_target);
}
static int setup_sd_notify_child(void) {
FDSet *fds,
int netns_fd) {
+ _cleanup_close_ int fd = -1;
+ int r, which_failed;
pid_t pid;
ssize_t l;
- int r;
- _cleanup_close_ int fd = -1;
assert(barrier);
assert(directory);
if (terminal < 0)
return log_error_errno(terminal, "Failed to open console: %m");
+ /* Make sure we can continue logging to the original stderr, even if stderr points elsewhere now */
+ r = log_dup_console();
+ if (r < 0)
+ return log_error_errno(r, "Failed to duplicate stderr: %m");
+
r = rearrange_stdio(terminal, terminal, terminal); /* invalidates 'terminal' on success and failure */
if (r < 0)
return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");
if (fd < 0)
return fd;
+ r = setrlimit_closest_all((const struct rlimit *const*) arg_rlimit, &which_failed);
+ if (r < 0)
+ return log_error_errno(r, "Failed to apply resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed));
+
pid = raw_clone(SIGCHLD|CLONE_NEWNS|
arg_clone_ns_flags |
(arg_userns_mode != USER_NAMESPACE_NO ? CLONE_NEWUSER : 0));
return 0;
}
-static int load_settings(void) {
- _cleanup_(settings_freep) Settings *settings = NULL;
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *p = NULL;
- const char *fn, *i;
- int r;
-
- /* If all settings are masked, there's no point in looking for
- * the settings file */
- if ((arg_settings_mask & _SETTINGS_MASK_ALL) == _SETTINGS_MASK_ALL)
- return 0;
-
- fn = strjoina(arg_machine, ".nspawn");
-
- /* We first look in the admin's directories in /etc and /run */
- FOREACH_STRING(i, "/etc/systemd/nspawn", "/run/systemd/nspawn") {
- _cleanup_free_ char *j = NULL;
-
- j = strjoin(i, "/", fn);
- if (!j)
- return log_oom();
-
- f = fopen(j, "re");
- if (f) {
- p = TAKE_PTR(j);
+static int merge_settings(Settings *settings, const char *path) {
+ int rl;
- /* By default, we trust configuration from /etc and /run */
- if (arg_settings_trusted < 0)
- arg_settings_trusted = true;
+ assert(settings);
+ assert(path);
- break;
- }
-
- if (errno != ENOENT)
- return log_error_errno(errno, "Failed to open %s: %m", j);
- }
-
- if (!f) {
- /* After that, let's look for a file next to the
- * actual image we shall boot. */
-
- if (arg_image) {
- p = file_in_same_dir(arg_image, fn);
- if (!p)
- return log_oom();
- } else if (arg_directory) {
- p = file_in_same_dir(arg_directory, fn);
- if (!p)
- return log_oom();
- }
-
- if (p) {
- f = fopen(p, "re");
- if (!f && errno != ENOENT)
- return log_error_errno(errno, "Failed to open %s: %m", p);
-
- /* By default, we do not trust configuration from /var/lib/machines */
- if (arg_settings_trusted < 0)
- arg_settings_trusted = false;
- }
- }
-
- if (!f)
- return 0;
-
- log_debug("Settings are trusted: %s", yes_no(arg_settings_trusted));
-
- r = settings_load(f, p, &settings);
- if (r < 0)
- return r;
-
- /* Copy over bits from the settings, unless they have been
- * explicitly masked by command line switches. */
+ /* Copy over bits from the settings, unless they have been explicitly masked by command line switches. Note
+ * that this steals the fields of the Settings* structure, and hence modifies it. */
if ((arg_settings_mask & SETTING_START_MODE) == 0 &&
settings->start_mode >= 0) {
arg_start_mode = settings->start_mode;
-
- strv_free(arg_parameters);
- arg_parameters = TAKE_PTR(settings->parameters);
+ strv_free_and_replace(arg_parameters, settings->parameters);
}
if ((arg_settings_mask & SETTING_PIVOT_ROOT) == 0 &&
free_and_replace(arg_chdir, settings->working_directory);
if ((arg_settings_mask & SETTING_ENVIRONMENT) == 0 &&
- settings->environment) {
- strv_free(arg_setenv);
- arg_setenv = TAKE_PTR(settings->environment);
- }
+ settings->environment)
+ strv_free_and_replace(arg_setenv, settings->environment);
if ((arg_settings_mask & SETTING_USER) == 0 &&
settings->user)
if (!arg_settings_trusted && plus != 0) {
if (settings->capability != 0)
- log_warning("Ignoring Capability= setting, file %s is not trusted.", p);
+ log_warning("Ignoring Capability= setting, file %s is not trusted.", path);
} else
arg_caps_retain |= plus;
!sd_id128_is_null(settings->machine_id)) {
if (!arg_settings_trusted)
- log_warning("Ignoring MachineID= setting, file %s is not trusted.", p);
+ log_warning("Ignoring MachineID= setting, file %s is not trusted.", path);
else
arg_uuid = settings->machine_id;
}
settings->n_custom_mounts > 0) {
if (!arg_settings_trusted)
- log_warning("Ignoring TemporaryFileSystem=, Bind= and BindReadOnly= settings, file %s is not trusted.", p);
+ log_warning("Ignoring TemporaryFileSystem=, Bind= and BindReadOnly= settings, file %s is not trusted.", path);
else {
custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts);
arg_custom_mounts = TAKE_PTR(settings->custom_mounts);
settings->network_veth_extra)) {
if (!arg_settings_trusted)
- log_warning("Ignoring network settings, file %s is not trusted.", p);
+ log_warning("Ignoring network settings, file %s is not trusted.", path);
else {
arg_network_veth = settings_network_veth(settings);
arg_private_network = settings_private_network(settings);
- strv_free(arg_network_interfaces);
- arg_network_interfaces = TAKE_PTR(settings->network_interfaces);
-
- strv_free(arg_network_macvlan);
- arg_network_macvlan = TAKE_PTR(settings->network_macvlan);
-
- strv_free(arg_network_ipvlan);
- arg_network_ipvlan = TAKE_PTR(settings->network_ipvlan);
-
- strv_free(arg_network_veth_extra);
- arg_network_veth_extra = TAKE_PTR(settings->network_veth_extra);
+ strv_free_and_replace(arg_network_interfaces, settings->network_interfaces);
+ strv_free_and_replace(arg_network_macvlan, settings->network_macvlan);
+ strv_free_and_replace(arg_network_ipvlan, settings->network_ipvlan);
+ strv_free_and_replace(arg_network_veth_extra, settings->network_veth_extra);
free_and_replace(arg_network_bridge, settings->network_bridge);
free_and_replace(arg_network_zone, settings->network_zone);
settings->expose_ports) {
if (!arg_settings_trusted)
- log_warning("Ignoring Port= setting, file %s is not trusted.", p);
+ log_warning("Ignoring Port= setting, file %s is not trusted.", path);
else {
expose_port_free_all(arg_expose_ports);
arg_expose_ports = TAKE_PTR(settings->expose_ports);
settings->userns_mode != _USER_NAMESPACE_MODE_INVALID) {
if (!arg_settings_trusted)
- log_warning("Ignoring PrivateUsers= and PrivateUsersChown= settings, file %s is not trusted.", p);
+ log_warning("Ignoring PrivateUsers= and PrivateUsersChown= settings, file %s is not trusted.", path);
else {
arg_userns_mode = settings->userns_mode;
arg_uid_shift = settings->uid_shift;
if ((arg_settings_mask & SETTING_SYSCALL_FILTER) == 0) {
if (!arg_settings_trusted && !strv_isempty(arg_syscall_whitelist))
- log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", p);
+ log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", path);
+ else {
+ strv_free_and_replace(arg_syscall_whitelist, settings->syscall_whitelist);
+ strv_free_and_replace(arg_syscall_blacklist, settings->syscall_blacklist);
+ }
+ }
+
+ for (rl = 0; rl < _RLIMIT_MAX; rl ++) {
+ if ((arg_settings_mask & (SETTING_RLIMIT_FIRST << rl)))
+ continue;
+
+ if (!settings->rlimit[rl])
+ continue;
+
+ if (!arg_settings_trusted) {
+ log_warning("Ignoring Limit%s= setting, file '%s' is not trusted.", rlimit_to_string(rl), path);
+ continue;
+ }
+
+ free_and_replace(arg_rlimit[rl], settings->rlimit[rl]);
+ }
+
+ if ((arg_settings_mask & SETTING_HOSTNAME) == 0 &&
+ settings->hostname)
+ free_and_replace(arg_hostname, settings->hostname);
+
+ if ((arg_settings_mask & SETTING_NO_NEW_PRIVILEGES) == 0 &&
+ settings->no_new_privileges >= 0)
+ arg_no_new_privileges = settings->no_new_privileges;
+
+ if ((arg_settings_mask & SETTING_OOM_SCORE_ADJUST) == 0 &&
+ settings->oom_score_adjust_set) {
+
+ if (!arg_settings_trusted)
+ log_warning("Ignoring OOMScoreAdjust= setting, file '%s' is not trusted.", path);
else {
- strv_free(arg_syscall_whitelist);
- strv_free(arg_syscall_blacklist);
+ arg_oom_score_adjust = settings->oom_score_adjust;
+ arg_oom_score_adjust_set = true;
+ }
+ }
+
+ if ((arg_settings_mask & SETTING_CPU_AFFINITY) == 0 &&
+ settings->cpuset) {
- arg_syscall_whitelist = TAKE_PTR(settings->syscall_whitelist);
- arg_syscall_blacklist = TAKE_PTR(settings->syscall_blacklist);
+ if (!arg_settings_trusted)
+ log_warning("Ignoring CPUAffinity= setting, file '%s' is not trusted.", path);
+ else {
+ if (arg_cpuset)
+ CPU_FREE(arg_cpuset);
+ arg_cpuset = TAKE_PTR(settings->cpuset);
+ arg_cpuset_ncpus = settings->cpuset_ncpus;
}
}
+ if ((arg_settings_mask & SETTING_RESOLV_CONF) == 0 &&
+ settings->resolv_conf != _RESOLV_CONF_MODE_INVALID)
+ arg_resolv_conf = settings->resolv_conf;
+
+ if ((arg_settings_mask & SETTING_LINK_JOURNAL) == 0 &&
+ settings->link_journal != _LINK_JOURNAL_INVALID) {
+
+ if (!arg_settings_trusted)
+ log_warning("Ignoring journal link setting, file '%s' is not trusted.", path);
+ else {
+ arg_link_journal = settings->link_journal;
+ arg_link_journal_try = settings->link_journal_try;
+ }
+ }
+
+ if ((arg_settings_mask & SETTING_TIMEZONE) == 0 &&
+ settings->timezone != _TIMEZONE_MODE_INVALID)
+ arg_timezone = settings->timezone;
+
return 0;
}
+static int load_settings(void) {
+ _cleanup_(settings_freep) Settings *settings = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ _cleanup_free_ char *p = NULL;
+ const char *fn, *i;
+ int r;
+
+ /* If all settings are masked, there's no point in looking for
+ * the settings file */
+ if ((arg_settings_mask & _SETTINGS_MASK_ALL) == _SETTINGS_MASK_ALL)
+ return 0;
+
+ fn = strjoina(arg_machine, ".nspawn");
+
+ /* We first look in the admin's directories in /etc and /run */
+ FOREACH_STRING(i, "/etc/systemd/nspawn", "/run/systemd/nspawn") {
+ _cleanup_free_ char *j = NULL;
+
+ j = strjoin(i, "/", fn);
+ if (!j)
+ return log_oom();
+
+ f = fopen(j, "re");
+ if (f) {
+ p = TAKE_PTR(j);
+
+ /* By default, we trust configuration from /etc and /run */
+ if (arg_settings_trusted < 0)
+ arg_settings_trusted = true;
+
+ break;
+ }
+
+ if (errno != ENOENT)
+ return log_error_errno(errno, "Failed to open %s: %m", j);
+ }
+
+ if (!f) {
+ /* After that, let's look for a file next to the
+ * actual image we shall boot. */
+
+ if (arg_image) {
+ p = file_in_same_dir(arg_image, fn);
+ if (!p)
+ return log_oom();
+ } else if (arg_directory) {
+ p = file_in_same_dir(arg_directory, fn);
+ if (!p)
+ return log_oom();
+ }
+
+ if (p) {
+ f = fopen(p, "re");
+ if (!f && errno != ENOENT)
+ return log_error_errno(errno, "Failed to open %s: %m", p);
+
+ /* By default, we do not trust configuration from /var/lib/machines */
+ if (arg_settings_trusted < 0)
+ arg_settings_trusted = false;
+ }
+ }
+
+ if (!f)
+ return 0;
+
+ log_debug("Settings are trusted: %s", yes_no(arg_settings_trusted));
+
+ r = settings_load(f, p, &settings);
+ if (r < 0)
+ return r;
+
+ return merge_settings(settings, p);
+}
+
static int run(int master,
const char* console,
DissectedImage *dissected_image,
if (r < 0)
return r;
- if (arg_keep_unit) {
- r = create_subcgroup(*pid, arg_unified_cgroup_hierarchy);
- if (r < 0)
- return r;
- }
+ r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy);
+ if (r < 0)
+ return r;
r = chown_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
if (r < 0)
"STATUS=Container running.\n"
"X_NSPAWN_LEADER_PID=" PID_FMT, *pid);
if (!arg_notify_ready)
- sd_notify(false, "READY=1\n");
+ (void) sd_notify(false, "READY=1\n");
if (arg_kill_signal > 0) {
/* Try to kill the init system on SIGINT or SIGTERM */
- sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, PID_TO_PTR(*pid));
- sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, PID_TO_PTR(*pid));
+ (void) sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, PID_TO_PTR(*pid));
+ (void) sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, PID_TO_PTR(*pid));
} else {
/* Immediately exit */
- sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
- sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+ (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+ (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
}
/* Exit when the child exits */
- sd_event_add_signal(event, NULL, SIGCHLD, on_sigchld, PID_TO_PTR(*pid));
+ (void) sd_event_add_signal(event, NULL, SIGCHLD, on_sigchld, PID_TO_PTR(*pid));
if (arg_expose_ports) {
r = expose_port_watch_rtnl(event, rtnl_socket_pair[0], on_address_change, exposed, &rtnl);
return 1; /* loop again */
}
+static int initialize_rlimits(void) {
+
+ /* The default resource limits the kernel passes to PID 1, as per kernel 4.16. Let's pass our container payload
+ * the same values as the kernel originally passed to PID 1, in order to minimize differences between host and
+ * container execution environments. */
+
+ static const struct rlimit kernel_defaults[_RLIMIT_MAX] = {
+ [RLIMIT_AS] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_CORE] = { 0, RLIM_INFINITY },
+ [RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_MEMLOCK] = { 65536, 65536 },
+ [RLIMIT_MSGQUEUE] = { 819200, 819200 },
+ [RLIMIT_NICE] = { 0, 0 },
+ [RLIMIT_NOFILE] = { 1024, 4096 },
+ [RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_RTPRIO] = { 0, 0 },
+ [RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY },
+ [RLIMIT_STACK] = { 8388608, RLIM_INFINITY },
+
+ /* The kernel scales the default for RLIMIT_NPROC and RLIMIT_SIGPENDING based on the system's amount of
+ * RAM. To provide best compatibility we'll read these limits off PID 1 instead of hardcoding them
+ * here. This is safe as we know that PID 1 doesn't change these two limits and thus the original
+ * kernel's initialization should still be valid during runtime — at least if PID 1 is systemd. Note
+ * that PID 1 changes a number of other resource limits during early initialization which is why we
+ * don't read the other limits from PID 1 but prefer the static table above. */
+ };
+
+ int rl;
+
+ for (rl = 0; rl < _RLIMIT_MAX; rl++) {
+
+ /* Let's only fill in what the user hasn't explicitly configured anyway */
+ if ((arg_settings_mask & (SETTING_RLIMIT_FIRST << rl)) == 0) {
+ const struct rlimit *v;
+ struct rlimit buffer;
+
+ if (IN_SET(rl, RLIMIT_NPROC, RLIMIT_SIGPENDING)) {
+ /* For these two let's read the limits off PID 1. See above for an explanation. */
+
+ if (prlimit(1, rl, NULL, &buffer) < 0)
+ return log_error_errno(errno, "Failed to read resource limit RLIMIT_%s of PID 1: %m", rlimit_to_string(rl));
+
+ v = &buffer;
+ } else
+ v = kernel_defaults + rl;
+
+ arg_rlimit[rl] = newdup(struct rlimit, v, 1);
+ if (!arg_rlimit[rl])
+ return log_oom();
+ }
+
+ if (DEBUG_LOGGING) {
+ _cleanup_free_ char *k = NULL;
+
+ (void) rlimit_format(arg_rlimit[rl], &k);
+ log_debug("Setting RLIMIT_%s to %s.", rlimit_to_string(rl), k);
+ }
+ }
+
+ return 0;
+}
+
int main(int argc, char *argv[]) {
_cleanup_free_ char *console = NULL;
if (r < 0)
goto finish;
+ r = initialize_rlimits();
+ if (r < 0)
+ goto finish;
+
r = determine_names();
if (r < 0)
goto finish;
}
if (arg_start_mode == START_BOOT) {
- if (path_is_os_tree(arg_directory) <= 0) {
- log_error("Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", arg_directory);
+ const char *p;
+
+ if (arg_pivot_root_new)
+ p = prefix_roota(arg_directory, arg_pivot_root_new);
+ else
+ p = arg_directory;
+
+ if (path_is_os_tree(p) <= 0) {
+ log_error("Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", p);
r = -EINVAL;
goto finish;
}
} else {
- const char *p;
+ const char *p, *q;
+
+ if (arg_pivot_root_new)
+ p = prefix_roota(arg_directory, arg_pivot_root_new);
+ else
+ p = arg_directory;
+
+ q = strjoina(p, "/usr/");
- p = strjoina(arg_directory, "/usr/");
- if (laccess(p, F_OK) < 0) {
- log_error("Directory %s doesn't look like it has an OS tree. Refusing.", arg_directory);
+ if (laccess(q, F_OK) < 0) {
+ log_error("Directory %s doesn't look like it has an OS tree. Refusing.", p);
r = -EINVAL;
goto finish;
}
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1) >= 0);
- if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) {
+ if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) < 0) {
r = log_error_errno(errno, "Failed to become subreaper: %m");
goto finish;
}
if (pid > 0)
(void) wait_for_terminate(pid, NULL);
+ pager_close();
+
if (remove_directory && arg_directory) {
int k;
free(arg_template);
free(arg_image);
free(arg_machine);
+ free(arg_hostname);
free(arg_user);
free(arg_pivot_root_new);
free(arg_pivot_root_old);
custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts);
expose_port_free_all(arg_expose_ports);
free(arg_root_hash);
+ rlimit_free_all(arg_rlimit);
+ arg_cpuset = cpu_set_mfree(arg_cpuset);
return r < 0 ? EXIT_FAILURE : ret;
}
#include "resolvectl.h"
#include "resolved-def.h"
#include "resolved-dns-packet.h"
+#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
#include "verbs.h"
static uint64_t arg_flags = 0;
static bool arg_no_pager = false;
bool arg_ifindex_permissive = false; /* If true, don't generate an error if the specified interface index doesn't exist */
-
-typedef enum ServiceFamily {
- SERVICE_FAMILY_TCP,
- SERVICE_FAMILY_UDP,
- SERVICE_FAMILY_SCTP,
- _SERVICE_FAMILY_INVALID = -1,
-} ServiceFamily;
static const char *arg_service_family = NULL;
typedef enum RawType {
return ifi;
}
-static ServiceFamily service_family_from_string(const char *s) {
- if (!s || streq(s, "tcp"))
- return SERVICE_FAMILY_TCP;
- if (streq(s, "udp"))
- return SERVICE_FAMILY_UDP;
- if (streq(s, "sctp"))
- return SERVICE_FAMILY_SCTP;
- return _SERVICE_FAMILY_INVALID;
-}
-
-static const char* service_family_to_string(ServiceFamily service) {
- switch(service) {
- case SERVICE_FAMILY_TCP:
- return "_tcp";
- case SERVICE_FAMILY_UDP:
- return "_udp";
- case SERVICE_FAMILY_SCTP:
- return "_sctp";
- default:
- assert_not_reached("invalid service");
- }
-}
-
static void print_source(uint64_t flags, usec_t rtt) {
char rtt_str[FORMAT_TIMESTAMP_MAX];
return r;
}
-static int resolve_tlsa(sd_bus *bus, ServiceFamily family, const char *address) {
+static int resolve_tlsa(sd_bus *bus, const char *family, const char *address) {
const char *port;
uint16_t port_num = 443;
_cleanup_free_ char *full = NULL;
address = strndupa(address, port - address);
}
- r = asprintf(&full, "_%u.%s.%s",
+ r = asprintf(&full, "_%u._%s.%s",
port_num,
- service_family_to_string(family),
+ family,
address);
if (r < 0)
return log_oom();
arg_type ?: DNS_TYPE_TLSA, true);
}
+static bool service_family_is_valid(const char *s) {
+ return STR_IN_SET(s, "tcp", "udp", "sctp");
+}
+
static int verb_tlsa(int argc, char **argv, void *userdata) {
sd_bus *bus = userdata;
- ServiceFamily family;
char **p, **args = argv + 1;
+ const char *family = "tcp";
int q, r = 0;
- family = service_family_from_string(argv[1]);
- if (family < 0)
- family = SERVICE_FAMILY_TCP;
- else
+ if (service_family_is_valid(argv[1])) {
+ family = argv[1];
args++;
+ }
STRV_FOREACH(p, args) {
q = resolve_tlsa(bus, family, *p);
printf(" LLMNR setting: %s\n"
"MulticastDNS setting: %s\n"
" DNSSEC setting: %s\n"
- " DNSSEC supported: %s\n"
- " Current DNS Server: %s\n",
+ " DNSSEC supported: %s\n",
strna(link_info.llmnr),
strna(link_info.mdns),
strna(link_info.dnssec),
- yes_no(link_info.dnssec_supported),
- strna(link_info.current_dns));
+ yes_no(link_info.dnssec_supported));
+
+ if (link_info.current_dns)
+ printf(" Current DNS Server: %s\n", link_info.current_dns);
STRV_FOREACH(i, link_info.dns) {
printf(" %s %s\n",
struct global_info {
char *current_dns;
char **dns;
+ char **fallback_dns;
char **domains;
char **ntas;
const char *llmnr;
static const struct bus_properties_map property_map[] = {
{ "DNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, dns) },
+ { "FallbackDNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, fallback_dns) },
{ "CurrentDNSServer", "(iiay)", map_global_current_dns_server, offsetof(struct global_info, current_dns) },
{ "Domains", "a(isb)", map_global_domains, offsetof(struct global_info, domains) },
{ "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct global_info, ntas) },
printf(" LLMNR setting: %s\n"
"MulticastDNS setting: %s\n"
" DNSSEC setting: %s\n"
- " DNSSEC supported: %s\n"
- " Current DNS Server: %s\n",
+ " DNSSEC supported: %s\n",
strna(global_info.llmnr),
strna(global_info.mdns),
strna(global_info.dnssec),
- yes_no(global_info.dnssec_supported),
- strna(global_info.current_dns));
+ yes_no(global_info.dnssec_supported));
+
+ if (global_info.current_dns)
+ printf(" Current DNS Server: %s\n", global_info.current_dns);
STRV_FOREACH(i, global_info.dns) {
printf(" %s %s\n",
*i);
}
+ STRV_FOREACH(i, global_info.fallback_dns) {
+ printf("%s %s\n",
+ i == global_info.fallback_dns ? "Fallback DNS Servers:" : " ",
+ *i);
+ }
+
STRV_FOREACH(i, global_info.domains) {
printf(" %s %s\n",
i == global_info.domains ? "DNS Domain:" : " ",
finish:
free(global_info.current_dns);
strv_free(global_info.dns);
+ strv_free(global_info.fallback_dns);
strv_free(global_info.domains);
strv_free(global_info.ntas);
}
static void help_dns_types(void) {
- const char *t;
- int i;
-
if (arg_legend)
puts("Known DNS RR types:");
- for (i = 0; i < _DNS_TYPE_MAX; i++) {
- t = dns_type_to_string(i);
- if (t)
- puts(t);
- }
+
+ DUMP_STRING_TABLE(dns_type, int, _DNS_TYPE_MAX);
}
static void help_dns_classes(void) {
- const char *t;
- int i;
-
if (arg_legend)
puts("Known DNS RR classes:");
- for (i = 0; i < _DNS_CLASS_MAX; i++) {
- t = dns_class_to_string(i);
- if (t)
- puts(t);
- }
+
+ DUMP_STRING_TABLE(dns_class, int, _DNS_CLASS_MAX);
}
static void compat_help(void) {
case ARG_TLSA:
arg_mode = MODE_RESOLVE_TLSA;
- if (service_family_from_string(arg_service_family) < 0) {
+ if (!optarg || service_family_is_valid(optarg))
+ arg_service_family = optarg;
+ else {
log_error("Unknown service family \"%s\".", optarg);
return -EINVAL;
}
- arg_service_family = optarg;
break;
case ARG_RAW:
sd_bus_error *error) {
Manager *m = userdata;
- unsigned c = 0;
DnsServer *s;
Iterator i;
Link *l;
r = bus_dns_server_append(reply, s, true);
if (r < 0)
return r;
-
- c++;
}
HASHMAP_FOREACH(l, m->links, i) {
r = bus_dns_server_append(reply, s, true);
if (r < 0)
return r;
- c++;
}
}
- if (c == 0) {
- LIST_FOREACH(servers, s, m->fallback_dns_servers) {
- r = bus_dns_server_append(reply, s, true);
- if (r < 0)
- return r;
- }
+ return sd_bus_message_close_container(reply);
+}
+
+static int bus_property_get_fallback_dns_servers(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ DnsServer *s, **f = userdata;
+ int r;
+
+ assert(reply);
+ assert(f);
+
+ r = sd_bus_message_open_container(reply, 'a', "(iiay)");
+ if (r < 0)
+ return r;
+
+ LIST_FOREACH(servers, s, *f) {
+ r = bus_dns_server_append(reply, s, true);
+ if (r < 0)
+ return r;
}
return sd_bus_message_close_container(reply);
(uint64_t) m->n_dnssec_verdict[DNSSEC_INDETERMINATE]);
}
-static int bus_property_get_dnssec_supported(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "b", manager_dnssec_supported(m));
-}
-
-static int bus_property_get_dnssec_mode(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Manager *m = userdata;
-
- assert(reply);
- assert(m);
-
- return sd_bus_message_append(reply, "s", dnssec_mode_to_string(manager_get_dnssec_mode(m)));
-}
-
static int bus_property_get_ntas(
sd_bus *bus,
const char *path,
}
static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode);
+static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported, "b", Manager, manager_dnssec_supported);
+static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode, "s", Manager, manager_get_dnssec_mode, dnssec_mode_to_string);
static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Manager, llmnr_support), 0),
SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Manager, mdns_support), 0),
SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0),
+ SD_BUS_PROPERTY("FallbackDNS", "a(iiay)", bus_property_get_fallback_dns_servers, offsetof(Manager, fallback_dns_servers), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CurrentDNSServer", "(iiay)", bus_property_get_current_dns_server, offsetof(Manager, current_dns_server), 0),
SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains, 0, 0),
SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
if (r < 0)
return log_error_errno(r, "Failed to register dnssd enumerator: %m");
- r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL, NULL);
+ r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL);
if (r < 0)
return log_error_errno(r, "Failed to request name: %m");
Copyright 2014 Tom Gundersen <teg@jklm.no>
***/
+#include "conf-parser.h"
+
typedef enum DnsStubListenerMode DnsStubListenerMode;
enum DnsStubListenerMode {
int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string);
const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-
const struct ConfigPerfItem* resolved_dnssd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
-int config_parse_dns_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_search_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dns_stub_listener_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssd_service_name(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssd_service_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns_servers);
+CONFIG_PARSER_PROTOTYPE(config_parse_search_domains);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt);
const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_;
DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_;
int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl);
-
int dnssec_test_positive_wildcard(DnsAnswer *a, const char *name, const char *source, const char *zone, bool *authenticated);
const char* dnssec_result_to_string(DnssecResult m) _const_;
Copyright 2014 Lennart Poettering
***/
-
#include "sd-bus.h"
#include "set.h"
._name = (char*) n, \
})
-
struct DnsTxtItem {
size_t length;
LIST_FIELDS(DnsTxtItem, items);
if (DNS_PACKET_QDCOUNT(p) > 1)
return -EOPNOTSUPP;
- if (!ratelimit_test(&s->ratelimit))
+ if (!ratelimit_below(&s->ratelimit))
return -EBUSY;
family = s->family;
case DNS_PROTOCOL_MDNS:
assert(fd < 0);
- if (!ratelimit_test(&s->ratelimit))
+ if (!ratelimit_below(&s->ratelimit))
return -EBUSY;
family = s->family;
} else {
int fd;
- if (!ratelimit_test(&s->ratelimit))
+ if (!ratelimit_below(&s->ratelimit))
return;
if (p->family == AF_INET)
}
if (strcaseeq(type, "DS")) {
- _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL, *digest = NULL;
+ _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL;
_cleanup_free_ void *dd = NULL;
uint16_t kt;
int a, dt;
size_t l;
- r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, &digest, NULL);
+ r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, NULL);
if (r < 0) {
log_warning_errno(r, "Failed to parse DS parameters on line %s:%u: %m", path, line);
return -EINVAL;
}
- if (r != 4) {
+ if (r != 3) {
log_warning("Missing DS parameters on line %s:%u", path, line);
return -EINVAL;
}
return -EINVAL;
}
- r = unhexmem(digest, strlen(digest), &dd, &l);
+ if (isempty(p)) {
+ log_warning("Missing DS digest on line %s:%u", path, line);
+ return -EINVAL;
+ }
+
+ r = unhexmem(p, strlen(p), &dd, &l);
if (r < 0) {
- log_warning("Failed to parse DS digest %s on line %s:%u", digest, path, line);
+ log_warning("Failed to parse DS digest %s on line %s:%u", p, path, line);
return -EINVAL;
}
rr->ds.digest = TAKE_PTR(dd);
} else if (strcaseeq(type, "DNSKEY")) {
- _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL, *key = NULL;
+ _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL;
_cleanup_free_ void *k = NULL;
uint16_t f;
size_t l;
int a;
- r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, &key, NULL);
+ r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, NULL);
if (r < 0)
return log_warning_errno(r, "Failed to parse DNSKEY parameters on line %s:%u: %m", path, line);
- if (r != 4) {
+ if (r != 3) {
log_warning("Missing DNSKEY parameters on line %s:%u", path, line);
return -EINVAL;
}
return -EINVAL;
}
- r = unbase64mem(key, strlen(key), &k, &l);
+ if (isempty(p)) {
+ log_warning("Missing DNSKEY key on line %s:%u", path, line);
+ return -EINVAL;
+ }
+
+ r = unbase64mem(p, strlen(p), &k, &l);
if (r < 0)
- return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", key, path, line);
+ return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", p, path, line);
rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, domain);
if (!rr)
return -EINVAL;
}
- if (!isempty(p)) {
- log_warning("Trailing garbage on line %s:%u, ignoring line.", path, line);
- return -EINVAL;
- }
-
r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops);
if (r < 0)
return log_oom();
#include "resolved-resolv-conf.h"
#include "strv.h"
-static int property_get_dnssec_mode(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Link *l = userdata;
-
- assert(reply);
- assert(l);
-
- return sd_bus_message_append(reply, "s", dnssec_mode_to_string(link_get_dnssec_mode(l)));
-}
+static BUS_DEFINE_PROPERTY_GET(property_get_dnssec_supported, "b", Link, link_dnssec_supported);
+static BUS_DEFINE_PROPERTY_GET2(property_get_dnssec_mode, "s", Link, link_get_dnssec_mode, dnssec_mode_to_string);
static int property_get_dns(
sd_bus *bus,
return sd_bus_message_close_container(reply);
}
-static int property_get_dnssec_supported(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Link *l = userdata;
-
- assert(reply);
- assert(l);
-
- return sd_bus_message_append(reply, "b", link_dnssec_supported(l));
-}
-
static int verify_unmanaged_link(Link *l, sd_bus_error *error) {
assert(l);
if (r < 0)
return log_debug_errno(r, "Failed to build reply packet: %m");
- if (!ratelimit_test(&s->ratelimit))
+ if (!ratelimit_below(&s->ratelimit))
return 0;
r = dns_scope_emit_udp(s, -1, reply);
}
static int bus_append_execute_property(sd_bus_message *m, const char *field, const char *eq) {
- int r, rl;
+ const char *suffix;
+ int r;
if (STR_IN_SET(field,
"User", "Group",
return bus_append_byte_array(m, field, decoded, sz);
}
- rl = rlimit_from_string(field);
- if (rl >= 0) {
- const char *sn;
- struct rlimit l;
+ if ((suffix = startswith(field, "Limit"))) {
+ int rl;
- r = rlimit_parse(rl, eq, &l);
- if (r < 0)
- return log_error_errno(r, "Failed to parse resource limit: %s", eq);
+ rl = rlimit_from_string(suffix);
+ if (rl >= 0) {
+ const char *sn;
+ struct rlimit l;
- r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max);
- if (r < 0)
- return bus_log_create_error(r);
+ r = rlimit_parse(rl, eq, &l);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse resource limit: %s", eq);
- sn = strjoina(field, "Soft");
- r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur);
- if (r < 0)
- return bus_log_create_error(r);
+ r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max);
+ if (r < 0)
+ return bus_log_create_error(r);
- return 1;
+ sn = strjoina(field, "Soft");
+ r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 1;
+ }
}
if (STR_IN_SET(field, "AppArmorProfile", "SmackProcessLabel")) {
if (r < 0)
return r;
- strv_free(*p);
- *p = TAKE_PTR(l);
- return 0;
+ return strv_free_and_replace(*p, l);
}
case SD_BUS_TYPE_BOOLEAN: {
case BUS_TRANSPORT_LOCAL:
if (user)
r = sd_bus_default_user(&bus);
- else
- r = sd_bus_default_system(&bus);
+ else {
+ if (sd_booted() <= 0) {
+ /* Print a friendly message when the local system is actually not running systemd as PID 1. */
+ log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
+ return -EHOSTDOWN;
+ }
+ r = sd_bus_default_system(&bus);
+ }
break;
case BUS_TRANSPORT_REMOTE:
case BUS_TRANSPORT_LOCAL:
if (user)
r = bus_connect_user_systemd(bus);
- else
- r = bus_connect_system_systemd(bus);
+ else {
+ if (sd_booted() <= 0) {
+ /* Print a friendly message when the local system is actually not running systemd as PID 1. */
+ log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
+ return -EHOSTDOWN;
+ }
+ r = bus_connect_system_systemd(bus);
+ }
break;
case BUS_TRANSPORT_REMOTE:
void *userdata,
sd_bus_error *error) {
+ const char *is_soft;
struct rlimit *rl;
uint64_t u;
rlim_t x;
- const char *is_soft;
assert(bus);
assert(reply);
assert(userdata);
is_soft = endswith(property, "Soft");
+
rl = *(struct rlimit**) userdata;
if (rl)
x = is_soft ? rl->rlim_cur : rl->rlim_max;
else {
struct rlimit buf = {};
+ const char *s, *p;
int z;
- const char *s;
+ /* Chop off "Soft" suffix */
s = is_soft ? strndupa(property, is_soft - property) : property;
- z = rlimit_from_string(strstr(s, "Limit"));
+ /* Skip over any prefix, such as "Default" */
+ assert_se(p = strstr(s, "Limit"));
+
+ z = rlimit_from_string(p + 5);
assert(z >= 0);
- getrlimit(z, &buf);
+ (void) getrlimit(z, &buf);
x = is_soft ? buf.rlim_cur : buf.rlim_max;
}
- /* rlim_t might have different sizes, let's map
- * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
- * all archs */
+ /* rlim_t might have different sizes, let's map RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on all
+ * archs */
u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
return sd_bus_message_append(reply, "t", u);
return 0;
}
+
+struct request_name_data {
+ const char *name;
+ uint64_t flags;
+ void *userdata;
+};
+
+static int reload_dbus_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ _cleanup_free_ struct request_name_data *data = userdata;
+ const sd_bus_error *e;
+ int r;
+
+ assert(m);
+ assert(data);
+ assert(data->name);
+
+ e = sd_bus_message_get_error(m);
+ if (e) {
+ log_error_errno(sd_bus_error_get_errno(e), "Failed to reload DBus configuration: %s", e->message);
+ return 1;
+ }
+
+ /* Here, use the default request name handler to avoid an infinite loop of reloading and requesting. */
+ r = sd_bus_request_name_async(sd_bus_message_get_bus(m), NULL, data->name, data->flags, NULL, data->userdata);
+ if (r < 0)
+ log_error_errno(r, "Failed to request name: %m");
+
+ return 1;
+}
+
+static int request_name_handler_may_reload_dbus(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+ _cleanup_free_ struct request_name_data *data = userdata;
+ uint32_t ret;
+ int r;
+
+ assert(m);
+ assert(userdata);
+
+ if (sd_bus_message_is_method_error(m, NULL)) {
+ const sd_bus_error *e = sd_bus_message_get_error(m);
+
+ if (!sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) {
+ log_debug_errno(sd_bus_error_get_errno(e),
+ "Unable to request name, failing connection: %s",
+ e->message);
+
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ log_debug_errno(sd_bus_error_get_errno(e),
+ "Unable to request name, retry after reloading DBus configuration: %s",
+ e->message);
+
+ /* If systemd-timesyncd.service enables DynamicUser= and dbus.service
+ * started before the dynamic user is realized, then the DBus policy
+ * about timesyncd has not been enabled yet. So, let's try to reload
+ * DBus configuration, and after that request name again. Note that it
+ * seems that no privileges are necessary to call the following method. */
+
+ r = sd_bus_call_method_async(
+ sd_bus_message_get_bus(m),
+ NULL,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "ReloadConfig",
+ reload_dbus_handler,
+ userdata, NULL);
+ if (r < 0) {
+ log_error_errno(r, "Failed to reload DBus configuration: %m");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ data = NULL; /* Avoid free() */
+ return 1;
+ }
+
+ r = sd_bus_message_read(m, "u", &ret);
+ if (r < 0)
+ return r;
+
+ switch (ret) {
+
+ case BUS_NAME_ALREADY_OWNER:
+ log_debug("Already owner of requested service name, ignoring.");
+ return 1;
+
+ case BUS_NAME_IN_QUEUE:
+ log_debug("In queue for requested service name.");
+ return 1;
+
+ case BUS_NAME_PRIMARY_OWNER:
+ log_debug("Successfully acquired requested service name.");
+ return 1;
+
+ case BUS_NAME_EXISTS:
+ log_debug("Requested service name already owned, failing connection.");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+ }
+
+ log_debug("Unexpected response from RequestName(), failing connection.");
+ bus_enter_closing(sd_bus_message_get_bus(m));
+ return 1;
+}
+
+int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata) {
+ struct request_name_data *data;
+
+ data = new0(struct request_name_data, 1);
+ if (!data)
+ return -ENOMEM;
+
+ data->name = name;
+ data->flags = flags;
+ data->userdata = userdata;
+
+ return sd_bus_request_name_async(bus, ret_slot, name, flags, request_name_handler_may_reload_dbus, data);
+}
int bus_log_parse_error(int r);
int bus_log_create_error(int r);
-#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \
+#define BUS_DEFINE_PROPERTY_GET_GLOBAL(function, bus_type, val) \
int function(sd_bus *bus, \
const char *path, \
const char *interface, \
void *userdata, \
sd_bus_error *error) { \
\
- const char *value; \
- type *field = userdata; \
- int r; \
- \
assert(bus); \
assert(reply); \
- assert(field); \
\
- value = strempty(name##_to_string(*field)); \
+ return sd_bus_message_append(reply, bus_type, val); \
+ }
+
+#define BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, get2) \
+ int function(sd_bus *bus, \
+ const char *path, \
+ const char *interface, \
+ const char *property, \
+ sd_bus_message *reply, \
+ void *userdata, \
+ sd_bus_error *error) { \
\
- r = sd_bus_message_append_basic(reply, 's', value); \
- if (r < 0) \
- return r; \
+ data_type *data = userdata; \
\
- return 1; \
+ assert(bus); \
+ assert(reply); \
+ assert(data); \
+ \
+ return sd_bus_message_append(reply, bus_type, \
+ get2(get1(data))); \
}
+#define ident(x) (x)
+#define BUS_DEFINE_PROPERTY_GET(function, bus_type, data_type, get1) \
+ BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, ident)
+
+#define ref(x) (*(x))
+#define BUS_DEFINE_PROPERTY_GET_REF(function, bus_type, data_type, get) \
+ BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, ref, get)
+
+#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \
+ BUS_DEFINE_PROPERTY_GET_REF(function, "s", type, name##_to_string)
+
#define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \
SD_BUS_PROPERTY(name, "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, realtime), (flags)), \
SD_BUS_PROPERTY(name "Monotonic", "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, monotonic), (flags))
static inline int bus_open_system_watch_bind(sd_bus **ret) {
return bus_open_system_watch_bind_with_description(ret, NULL);
}
+
+int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata);
#include "syslog-util.h"
#include "time-util.h"
#include "utf8.h"
+#include "rlimit-util.h"
int config_item_table_lookup(
const void *table,
continuation = mfree(continuation);
}
+ if (continuation) {
+ r = parse_line(unit,
+ filename,
+ ++line,
+ sections,
+ lookup,
+ table,
+ flags,
+ §ion,
+ §ion_line,
+ §ion_ignored,
+ continuation,
+ userdata);
+ if (r < 0) {
+ if (flags & CONFIG_PARSE_WARN)
+ log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line);
+ return r;
+
+ }
+ }
+
return 0;
}
void *data,
void *userdata) {
- char **s = data, *n;
+ char **s = data;
assert(filename);
assert(lvalue);
return 0;
}
- if (isempty(rvalue))
- n = NULL;
- else {
- n = strdup(rvalue);
- if (!n)
- return log_oom();
- }
-
- free(*s);
- *s = n;
+ if (free_and_strdup(s, empty_to_null(rvalue)) < 0)
+ return log_oom();
return 0;
}
return 0;
}
+
+int config_parse_rlimit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ struct rlimit **rl = data, d = {};
+ int r;
+
+ assert(rvalue);
+ assert(rl);
+
+ r = rlimit_parse(ltype, rvalue, &d);
+ if (r == -EILSEQ) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue);
+ return 0;
+ }
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (rl[ltype])
+ *rl[ltype] = d;
+ else {
+ rl[ltype] = newdup(struct rlimit, &d, 1);
+ if (!rl[ltype])
+ return log_oom();
+ }
+
+ return 0;
+}
CONFIG_PARSE_REFUSE_BOM = 1U << 3,
} ConfigParseFlags;
+/* Argument list for parsers of specific configuration settings. */
+#define CONFIG_PARSER_ARGUMENTS \
+ const char *unit, \
+ const char *filename, \
+ unsigned line, \
+ const char *section, \
+ unsigned section_line, \
+ const char *lvalue, \
+ int ltype, \
+ const char *rvalue, \
+ void *data, \
+ void *userdata
+
/* Prototype for a parser for a specific configuration setting */
-typedef int (*ConfigParserCallback)(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
+typedef int (*ConfigParserCallback)(CONFIG_PARSER_ARGUMENTS);
+
+/* A macro declaring the a function prototype, following the typedef above, simply because it's so cumbersomely long
+ * otherwise. (And current emacs gets irritatingly slow when editing files that contain lots of very long function
+ * prototypes on the same screen…) */
+#define CONFIG_PARSER_PROTOTYPE(name) int name(CONFIG_PARSER_ARGUMENTS)
/* Wraps information for parsing a specific configuration variable, to
* be stored in a simple array */
ConfigParseFlags flags,
void *userdata);
-/* Generic parsers */
-#define GENERIC_PARSER_ARGS \
- const char *unit, \
- const char *filename, \
- unsigned line, \
- const char *section, \
- unsigned section_line, \
- const char *lvalue, \
- int ltype, \
- const char *rvalue, \
- void *data, \
- void *userdata
-int config_parse_int(GENERIC_PARSER_ARGS);
-int config_parse_unsigned(GENERIC_PARSER_ARGS);
-int config_parse_long(GENERIC_PARSER_ARGS);
-int config_parse_uint8(GENERIC_PARSER_ARGS);
-int config_parse_uint16(GENERIC_PARSER_ARGS);
-int config_parse_uint32(GENERIC_PARSER_ARGS);
-int config_parse_uint64(GENERIC_PARSER_ARGS);
-int config_parse_double(GENERIC_PARSER_ARGS);
-int config_parse_iec_size(GENERIC_PARSER_ARGS);
-int config_parse_si_size(GENERIC_PARSER_ARGS);
-int config_parse_iec_uint64(GENERIC_PARSER_ARGS);
-int config_parse_bool(GENERIC_PARSER_ARGS);
-int config_parse_tristate(GENERIC_PARSER_ARGS);
-int config_parse_string(GENERIC_PARSER_ARGS);
-int config_parse_path(GENERIC_PARSER_ARGS);
-int config_parse_strv(GENERIC_PARSER_ARGS);
-int config_parse_sec(GENERIC_PARSER_ARGS);
-int config_parse_nsec(GENERIC_PARSER_ARGS);
-int config_parse_mode(GENERIC_PARSER_ARGS);
-int config_parse_warn_compat(GENERIC_PARSER_ARGS);
-int config_parse_log_facility(GENERIC_PARSER_ARGS);
-int config_parse_log_level(GENERIC_PARSER_ARGS);
-int config_parse_signal(GENERIC_PARSER_ARGS);
-int config_parse_personality(GENERIC_PARSER_ARGS);
-int config_parse_ifname(GENERIC_PARSER_ARGS);
-int config_parse_ip_port(GENERIC_PARSER_ARGS);
-int config_parse_join_controllers(GENERIC_PARSER_ARGS);
-int config_parse_mtu(GENERIC_PARSER_ARGS);
+CONFIG_PARSER_PROTOTYPE(config_parse_int);
+CONFIG_PARSER_PROTOTYPE(config_parse_unsigned);
+CONFIG_PARSER_PROTOTYPE(config_parse_long);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint8);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint16);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint32);
+CONFIG_PARSER_PROTOTYPE(config_parse_uint64);
+CONFIG_PARSER_PROTOTYPE(config_parse_double);
+CONFIG_PARSER_PROTOTYPE(config_parse_iec_size);
+CONFIG_PARSER_PROTOTYPE(config_parse_si_size);
+CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64);
+CONFIG_PARSER_PROTOTYPE(config_parse_bool);
+CONFIG_PARSER_PROTOTYPE(config_parse_tristate);
+CONFIG_PARSER_PROTOTYPE(config_parse_string);
+CONFIG_PARSER_PROTOTYPE(config_parse_path);
+CONFIG_PARSER_PROTOTYPE(config_parse_strv);
+CONFIG_PARSER_PROTOTYPE(config_parse_sec);
+CONFIG_PARSER_PROTOTYPE(config_parse_nsec);
+CONFIG_PARSER_PROTOTYPE(config_parse_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_warn_compat);
+CONFIG_PARSER_PROTOTYPE(config_parse_log_facility);
+CONFIG_PARSER_PROTOTYPE(config_parse_log_level);
+CONFIG_PARSER_PROTOTYPE(config_parse_signal);
+CONFIG_PARSER_PROTOTYPE(config_parse_personality);
+CONFIG_PARSER_PROTOTYPE(config_parse_ifname);
+CONFIG_PARSER_PROTOTYPE(config_parse_ip_port);
+CONFIG_PARSER_PROTOTYPE(config_parse_join_controllers);
+CONFIG_PARSER_PROTOTYPE(config_parse_mtu);
+CONFIG_PARSER_PROTOTYPE(config_parse_rlimit);
typedef enum Disabled {
DISABLED_CONFIGURATION,
} Disabled;
#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
- int function(GENERIC_PARSER_ARGS) { \
+ CONFIG_PARSER_PROTOTYPE(function) { \
type *i = data, x; \
\
assert(filename); \
}
#define DEFINE_CONFIG_PARSE_ENUMV(function,name,type,invalid,msg) \
- int function(GENERIC_PARSER_ARGS) { \
+ CONFIG_PARSER_PROTOTYPE(function) { \
type **enums = data, x, *ys; \
_cleanup_free_ type *xs = NULL; \
const char *word, *state; \
*(xs + i) = invalid; \
} \
\
- free(*enums); \
- *enums = xs; \
- xs = NULL; \
- \
+ free_and_replace(*enums, xs); \
return 0; \
}
#define GPT_ROOT_ARM_64_VERITY SD_ID128_MAKE(df,33,00,ce,d6,9f,4c,92,97,8c,9b,fb,0f,38,d8,20)
#define GPT_ROOT_IA64_VERITY SD_ID128_MAKE(86,ed,10,d5,b6,07,45,bb,89,57,d3,50,f2,3d,05,71)
-
#if defined(__x86_64__)
# define GPT_ROOT_NATIVE GPT_ROOT_X86_64
# define GPT_ROOT_SECONDARY GPT_ROOT_X86
char reserved[128]; /* For future expansion. */
};
-
/*
* Because of legacy interfaces, "runlevel" and "sleeptime"
* aren't in a separate struct in the union.
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(presets);
- if (scope == UNIT_FILE_SYSTEM)
+ switch (scope) {
+ case UNIT_FILE_SYSTEM:
r = conf_files_list(&files, ".preset", root_dir, 0,
"/etc/systemd/system-preset",
"/run/systemd/system-preset",
"/lib/systemd/system-preset",
#endif
NULL);
- else if (scope == UNIT_FILE_GLOBAL)
+ break;
+
+ case UNIT_FILE_GLOBAL:
+ case UNIT_FILE_USER:
r = conf_files_list(&files, ".preset", root_dir, 0,
"/etc/systemd/user-preset",
"/run/systemd/user-preset",
"/usr/local/lib/systemd/user-preset",
"/usr/lib/systemd/user-preset",
NULL);
- else {
- *presets = (Presets){};
+ break;
- return 0;
+ default:
+ assert_not_reached("Invalid unit file scope");
}
if (r < 0)
#
# Copyright 2017 Zbigniew Jędrzejewski-Szmek
-shared_sources = '''
+shared_sources = files('''
acl-util.h
acpi-fpdt.c
acpi-fpdt.h
watchdog.c
watchdog.h
wireguard-netlink.h
-'''.split()
+'''.split())
test_tables_h = files('test-tables.h')
shared_sources += [test_tables_h]
if conf.get('HAVE_ACL') == 1
- shared_sources += ['acl-util.c']
+ shared_sources += files('acl-util.c')
endif
if conf.get('ENABLE_UTMP') == 1
- shared_sources += ['utmp-wtmp.c']
+ shared_sources += files('utmp-wtmp.c')
endif
if conf.get('HAVE_SECCOMP') == 1
- shared_sources += ['seccomp-util.c']
+ shared_sources += files('seccomp-util.c')
endif
if conf.get('HAVE_LIBIPTC') == 1
- shared_sources += ['firewall-util.c']
+ shared_sources += files('firewall-util.c')
endif
libshared_name = 'systemd-shared-@0@'.format(meson.project_version())
/* Flush the generated unit files in full */
if (p->generator)
- (void) rm_rf(p->generator, REMOVE_ROOT);
+ (void) rm_rf(p->generator, REMOVE_ROOT|REMOVE_PHYSICAL);
if (p->generator_early)
- (void) rm_rf(p->generator_early, REMOVE_ROOT);
+ (void) rm_rf(p->generator_early, REMOVE_ROOT|REMOVE_PHYSICAL);
if (p->generator_late)
- (void) rm_rf(p->generator_late, REMOVE_ROOT);
+ (void) rm_rf(p->generator_late, REMOVE_ROOT|REMOVE_PHYSICAL);
if (p->temporary_dir)
- (void) rm_rf(p->temporary_dir, REMOVE_ROOT);
+ (void) rm_rf(p->temporary_dir, REMOVE_ROOT|REMOVE_PHYSICAL);
}
char **generator_binary_paths(UnitFileScope scope) {
Copyright 2016 Lennart Poettering
***/
+#include "conf-parser.h"
#include "macro.h"
typedef enum ResolveSupport ResolveSupport;
_DNSSEC_MODE_INVALID = -1
};
-int config_parse_resolve_support(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dnssec_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_resolve_support);
+CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_mode);
const char* resolve_support_to_string(ResolveSupport p) _const_;
ResolveSupport resolve_support_from_string(const char *s) _pure_;
**suspend_mode = NULL, **suspend_state = NULL,
**hibernate_mode = NULL, **hibernate_state = NULL,
**hybrid_mode = NULL, **hybrid_state = NULL;
- char **modes, **states;
+ _cleanup_strv_free_ char **modes, **states; /* always initialized below */
usec_t delay = 180 * USEC_PER_MINUTE;
const ConfigTableItem items[] = {
assert_not_reached("what verb");
if ((!modes && STR_IN_SET(verb, "hibernate", "hybrid-sleep")) ||
- (!states && !streq(verb, "suspend-then-hibernate"))) {
- strv_free(modes);
- strv_free(states);
+ (!states && !streq(verb, "suspend-then-hibernate")))
return log_oom();
- }
if (_modes)
- *_modes = modes;
+ *_modes = TAKE_PTR(modes);
if (_states)
- *_states = states;
+ *_states = TAKE_PTR(states);
if (_delay)
*_delay = delay;
#include <stdbool.h>
#include <inttypes.h>
+#include "conf-parser.h"
+
#define VLANID_MAX 4094
#define VLANID_INVALID UINT16_MAX
int parse_vlanid(const char *p, uint16_t *ret);
-int config_parse_default_port_vlanid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_vlanid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_default_port_vlanid);
+CONFIG_PARSER_PROTOTYPE(config_parse_vlanid);
#include "macro.h"
#include "parse-util.h"
#include "proc-cmdline.h"
+#include "string-table.h"
#include "string-util.h"
#include "volatile-util.h"
-VolatileMode volatile_mode_from_string(const char *s) {
- int b;
-
- if (isempty(s))
- return _VOLATILE_MODE_INVALID;
-
- b = parse_boolean(s);
- if (b > 0)
- return VOLATILE_YES;
- if (b == 0)
- return VOLATILE_NO;
-
- if (streq(s, "state"))
- return VOLATILE_STATE;
-
- return _VOLATILE_MODE_INVALID;
-}
-
int query_volatile_mode(VolatileMode *ret) {
_cleanup_free_ char *mode = NULL;
VolatileMode m = VOLATILE_NO;
*ret = m;
return r;
}
+
+static const char* const volatile_mode_table[_VOLATILE_MODE_MAX] = {
+ [VOLATILE_NO] = "no",
+ [VOLATILE_YES] = "yes",
+ [VOLATILE_STATE] = "state",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(volatile_mode, VolatileMode, VOLATILE_YES);
} VolatileMode;
VolatileMode volatile_mode_from_string(const char *s);
+const char* volatile_mode_to_string(VolatileMode m);
int query_volatile_mode(VolatileMode *ret);
#include "string-util.h"
#include "strv.h"
#include "sysctl-util.h"
+#include "terminal-util.h"
#include "util.h"
static char **arg_prefixes = NULL;
-
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysctl.d");
+static bool arg_cat_config = false;
static int apply_all(OrderedHashmap *sysctl_options) {
char *property, *value;
assert(path);
- r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
+ r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f);
if (r < 0) {
if (ignore_enoent && r == -ENOENT)
return 0;
"Applies kernel sysctl settings.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --cat-config Show configuration files\n"
" --prefix=PATH Only apply rules with the specified prefix\n"
, program_invocation_short_name);
}
enum {
ARG_VERSION = 0x100,
- ARG_PREFIX
+ ARG_CAT_CONFIG,
+ ARG_PREFIX,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "prefix", required_argument, NULL, ARG_PREFIX },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
+ { "prefix", required_argument, NULL, ARG_PREFIX },
{}
};
case ARG_VERSION:
return version();
+ case ARG_CAT_CONFIG:
+ arg_cat_config = true;
+ break;
+
case ARG_PREFIX: {
char *p;
assert_not_reached("Unhandled option");
}
+ if (arg_cat_config && argc > optind) {
+ log_error("Positional arguments are not allowed with --cat-config");
+ return -EINVAL;
+ }
+
return 1;
}
_cleanup_strv_free_ char **files = NULL;
char **f;
- r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
+ r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("sysctl.d"));
if (r < 0) {
log_error_errno(r, "Failed to enumerate sysctl.d files: %m");
goto finish;
}
+ if (arg_cat_config) {
+ r = cat_files(NULL, files, 0);
+ goto finish;
+ }
+
STRV_FOREACH(f, files) {
k = parse_file(sysctl_options, *f, true);
if (k < 0 && r == 0)
user = arg_scope != UNIT_FILE_SYSTEM;
- if (!user && sd_booted() <= 0) {
- /* Print a friendly message when the local system is actually not running systemd as PID 1. */
- log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
- return -EHOSTDOWN;
- }
-
if (focus == BUS_MANAGER)
r = bus_connect_transport_systemd(arg_transport, arg_host, user, &busses[focus]);
else
return ret;
}
-static int cat_file(const char *filename, bool newline) {
- _cleanup_close_ int fd;
-
- fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0)
- return -errno;
-
- printf("%s%s# %s%s\n",
- newline ? "\n" : "",
- ansi_highlight_blue(),
- filename,
- ansi_normal());
- fflush(stdout);
-
- return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0);
-}
-
static int cat(int argc, char *argv[], void *userdata) {
_cleanup_(lookup_paths_free) LookupPaths lp = {};
_cleanup_strv_free_ char **names = NULL;
STRV_FOREACH(name, names) {
_cleanup_free_ char *fragment_path = NULL;
_cleanup_strv_free_ char **dropin_paths = NULL;
- char **path;
r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths);
if (r < 0)
arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
ansi_normal());
- if (fragment_path) {
- r = cat_file(fragment_path, false);
- if (r < 0)
- return log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
- }
-
- STRV_FOREACH(path, dropin_paths) {
- r = cat_file(*path, path == dropin_paths);
- if (r < 0)
- return log_warning_errno(r, "Failed to cat %s: %m", *path);
- }
+ r = cat_files(fragment_path, dropin_paths, 0);
+ if (r < 0)
+ return r;
}
return 0;
}
static void help_types(void) {
- int i;
-
if (!arg_no_legend)
puts("Available unit types:");
- for (i = 0; i < _UNIT_TYPE_MAX; i++)
- puts(unit_type_to_string(i));
+
+ DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX);
}
static void help_states(void) {
- int i;
-
if (!arg_no_legend)
puts("Available unit load states:");
- for (i = 0; i < _UNIT_LOAD_STATE_MAX; i++)
- puts(unit_load_state_to_string(i));
+ DUMP_STRING_TABLE(unit_load_state, UnitLoadState, _UNIT_LOAD_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable unit active states:");
- for (i = 0; i < _UNIT_ACTIVE_STATE_MAX; i++)
- puts(unit_active_state_to_string(i));
+ DUMP_STRING_TABLE(unit_active_state, UnitActiveState, _UNIT_ACTIVE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable automount unit substates:");
- for (i = 0; i < _AUTOMOUNT_STATE_MAX; i++)
- puts(automount_state_to_string(i));
+ DUMP_STRING_TABLE(automount_state, AutomountState, _AUTOMOUNT_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable device unit substates:");
- for (i = 0; i < _DEVICE_STATE_MAX; i++)
- puts(device_state_to_string(i));
+ DUMP_STRING_TABLE(device_state, DeviceState, _DEVICE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable mount unit substates:");
- for (i = 0; i < _MOUNT_STATE_MAX; i++)
- puts(mount_state_to_string(i));
+ DUMP_STRING_TABLE(mount_state, MountState, _MOUNT_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable path unit substates:");
- for (i = 0; i < _PATH_STATE_MAX; i++)
- puts(path_state_to_string(i));
+ DUMP_STRING_TABLE(path_state, PathState, _PATH_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable scope unit substates:");
- for (i = 0; i < _SCOPE_STATE_MAX; i++)
- puts(scope_state_to_string(i));
+ DUMP_STRING_TABLE(scope_state, ScopeState, _SCOPE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable service unit substates:");
- for (i = 0; i < _SERVICE_STATE_MAX; i++)
- puts(service_state_to_string(i));
+ DUMP_STRING_TABLE(service_state, ServiceState, _SERVICE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable slice unit substates:");
- for (i = 0; i < _SLICE_STATE_MAX; i++)
- puts(slice_state_to_string(i));
+ DUMP_STRING_TABLE(slice_state, SliceState, _SLICE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable socket unit substates:");
- for (i = 0; i < _SOCKET_STATE_MAX; i++)
- puts(socket_state_to_string(i));
+ DUMP_STRING_TABLE(socket_state, SocketState, _SOCKET_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable swap unit substates:");
- for (i = 0; i < _SWAP_STATE_MAX; i++)
- puts(swap_state_to_string(i));
+ DUMP_STRING_TABLE(swap_state, SwapState, _SWAP_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable target unit substates:");
- for (i = 0; i < _TARGET_STATE_MAX; i++)
- puts(target_state_to_string(i));
+ DUMP_STRING_TABLE(target_state, TargetState, _TARGET_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable timer unit substates:");
- for (i = 0; i < _TIMER_STATE_MAX; i++)
- puts(timer_state_to_string(i));
+ DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
}
static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case 's':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
break;
case ARG_PRESET_MODE:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(unit_file_preset_mode, UnitFilePresetMode, _UNIT_FILE_PRESET_MAX);
+ return 0;
+ }
arg_preset_mode = unit_file_preset_mode_from_string(optarg);
if (arg_preset_mode < 0) {
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
+ SD_DHCP_OPTION_USER_CLASS = 77,
SD_DHCP_OPTION_FQDN = 81,
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
int sd_dhcp_client_set_vendor_class_identifier(
sd_dhcp_client *client,
const char *vci);
+int sd_dhcp_client_set_user_class(
+ sd_dhcp_client *client,
+ const char* const *user_class);
int sd_dhcp_client_get_lease(
sd_dhcp_client *client,
sd_dhcp_lease **ret);
typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata);
enum {
- SD_RESOLVE_GET_HOST = UINT64_C(1),
- SD_RESOLVE_GET_SERVICE = UINT64_C(2),
- SD_RESOLVE_GET_BOTH = UINT64_C(3),
+ SD_RESOLVE_GET_HOST = 1 << 0,
+ SD_RESOLVE_GET_SERVICE = 1 << 1,
+ SD_RESOLVE_GET_BOTH = SD_RESOLVE_GET_HOST | SD_RESOLVE_GET_SERVICE,
};
int sd_resolve_default(sd_resolve **ret);
#include "specifier.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
#include "uid-range.h"
#include "user-util.h"
#include "utf8.h"
} Item;
static char *arg_root = NULL;
+static bool arg_cat_config = false;
static const char *arg_replace = NULL;
static bool arg_inline = false;
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysusers.d");
-
static OrderedHashmap *users = NULL, *groups = NULL;
static OrderedHashmap *todo_uids = NULL, *todo_gids = NULL;
static OrderedHashmap *members = NULL;
if (streq(fn, "-"))
f = stdin;
else {
- r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &rf);
+ r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf);
if (r < 0) {
if (ignore_enoent && r == -ENOENT)
return 0;
hashmap_free(by_id);
}
+static int cat_config(void) {
+ _cleanup_strv_free_ char **files = NULL;
+ int r;
+
+ r = conf_files_list_with_replacement(arg_root, CONF_PATHS_STRV("sysusers.d"), arg_replace, &files, NULL);
+ if (r < 0)
+ return r;
+
+ return cat_files(NULL, files, 0);
+}
+
static void help(void) {
printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
"Creates system user accounts.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --cat-config Show configuration files\n"
" --root=PATH Operate on an alternate filesystem root\n"
" --replace=PATH Treat arguments as replacement for PATH\n"
" --inline Treat arguments as configuration lines\n"
enum {
ARG_VERSION = 0x100,
+ ARG_CAT_CONFIG,
ARG_ROOT,
ARG_REPLACE,
ARG_INLINE,
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "root", required_argument, NULL, ARG_ROOT },
- { "replace", required_argument, NULL, ARG_REPLACE },
- { "inline", no_argument, NULL, ARG_INLINE },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
+ { "root", required_argument, NULL, ARG_ROOT },
+ { "replace", required_argument, NULL, ARG_REPLACE },
+ { "inline", no_argument, NULL, ARG_INLINE },
{}
};
case ARG_VERSION:
return version();
+ case ARG_CAT_CONFIG:
+ arg_cat_config = true;
+ break;
+
case ARG_ROOT:
r = parse_path_argument_and_warn(optarg, true, &arg_root);
if (r < 0)
assert_not_reached("Unhandled option");
}
+ if (arg_replace && arg_cat_config) {
+ log_error("Option --replace= is not supported with --cat-config");
+ return -EINVAL;
+ }
+
if (arg_replace && optind >= argc) {
log_error("When --replace= is given, some configuration items must be specified");
return -EINVAL;
return 0;
}
-static int read_config_files(const char* dirs, char **args) {
+static int read_config_files(char **args) {
_cleanup_strv_free_ char **files = NULL;
_cleanup_free_ char *p = NULL;
char **f;
int r;
- r = conf_files_list_nulstr(&files, ".conf", arg_root, 0, dirs);
+ r = conf_files_list_with_replacement(arg_root, CONF_PATHS_STRV("sysusers.d"), arg_replace, &files, &p);
if (r < 0)
- return log_error_errno(r, "Failed to enumerate sysusers.d files: %m");
-
- if (arg_replace) {
- r = conf_files_insert_nulstr(&files, arg_root, dirs, arg_replace);
- if (r < 0)
- return log_error_errno(r, "Failed to extend sysusers.d file list: %m");
-
- p = path_join(arg_root, arg_replace, NULL);
- if (!p)
- return log_oom();
- }
+ return r;
STRV_FOREACH(f, files)
if (p && path_equal(*f, p)) {
}
int main(int argc, char *argv[]) {
-
_cleanup_close_ int lock = -1;
Iterator iterator;
int r;
log_parse_environment();
log_open();
+ if (arg_cat_config) {
+ r = cat_config();
+ goto finish;
+ }
+
umask(0022);
r = mac_selinux_init();
* read configuration and execute it.
*/
if (arg_replace || optind >= argc)
- r = read_config_files(conf_file_dirs, argv + optind);
+ r = read_config_files(argv + optind);
else
r = parse_arguments(argv + optind);
if (r < 0)
#include "conf-parser.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "log.h"
#include "macro.h"
#include "string-util.h"
"2\\\n"
"3\n",
+ "[Section]\n"
+ "setting1=1\\\n" /* continuation with extra trailing backslash at the end */
+ "2\\\n"
+ "3\\\n",
+
"[Section]\n"
"setting1=1\\\\\\\n" /* continuation with trailing escape symbols */
"\\\\2\n", /* note that C requires one level of escaping, so the
x1000("ABCD") "\\\n"
"foobar",
+ "[Section]\n"
+ "setting1=" /* a line above LINE_MAX length, with continuation */
+ x1000("ABCD") "\\\n" /* and an extra trailing backslash */
+ "foobar\\\n",
+
"[Section]\n"
"setting1=" /* a line above the allowed limit: 9 + 1050000 + 1 */
x1000(x1000("x") x10("abcde")) "\n",
};
static void test_config_parse(unsigned i, const char *s) {
- char name[] = "/tmp/test-conf-parser.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-conf-parser.XXXXXX";
int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *setting1 = NULL;
assert_se(streq(setting1, "1"));
break;
- case 4:
+ case 4 ... 5:
assert_se(r == 0);
assert_se(streq(setting1, "1 2 3"));
break;
- case 5:
+ case 6:
assert_se(r == 0);
assert_se(streq(setting1, "1\\\\ \\\\2"));
break;
- case 6:
+ case 7:
assert_se(r == 0);
assert_se(streq(setting1, x1000("ABCD")));
break;
- case 7:
+ case 8 ... 9:
assert_se(r == 0);
assert_se(streq(setting1, x1000("ABCD") " foobar"));
break;
- case 8 ... 9:
+ case 10 ... 11:
assert_se(r == -ENOBUFS);
assert_se(setting1 == NULL);
break;
STRV_FOREACH(p, files) {
_cleanup_free_ char *f;
- assert_se((f = strappend(original_dir, *p)));
+ assert_se(f = strappend(original_dir, *p));
assert_se(mkdir_parents(f, 0755) >= 0);
assert_se(write_string_file(f, "file", WRITE_STRING_FILE_CREATE) == 0);
STRV_FOREACH_PAIR(link, p, links) {
_cleanup_free_ char *f, *l;
- assert_se((f = strappend(original_dir, *p)));
- assert_se((l = strappend(original_dir, *link)));
+ assert_se(f = strappend(original_dir, *p));
+ assert_se(l = strappend(original_dir, *link));
assert_se(mkdir_parents(l, 0755) >= 0);
assert_se(symlink(f, l) == 0);
assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE) == 0);
STRV_FOREACH(p, files) {
- _cleanup_free_ char *buf = NULL, *f;
- size_t sz = 0;
+ _cleanup_free_ char *buf, *f;
+ size_t sz;
- assert_se((f = strappend(copy_dir, *p)));
+ assert_se(f = strappend(copy_dir, *p));
assert_se(access(f, F_OK) == 0);
assert_se(read_full_file(f, &buf, &sz) == 0);
}
STRV_FOREACH_PAIR(link, p, links) {
- _cleanup_free_ char *target = NULL, *f, *l;
+ _cleanup_free_ char *target, *f, *l;
- assert_se((f = strjoin(original_dir, *p)));
- assert_se((l = strjoin(copy_dir, *link)));
+ assert_se(f = strjoin(original_dir, *p));
+ assert_se(l = strjoin(copy_dir, *link));
assert_se(chase_symlinks(l, NULL, 0, &target) == 1);
assert_se(path_equal(f, target));
int main(int argc, char **argv) {
void *handle;
- assert_se((handle = dlopen(argv[1], RTLD_NOW)));
+ assert_se(handle = dlopen(argv[1], RTLD_NOW));
assert_se(dlclose(handle) == 0);
return EXIT_SUCCESS;
#if HAVE_SECCOMP
#include "seccomp-util.h"
#endif
+#include "service.h"
#include "stat-util.h"
#include "test-helper.h"
#include "tests.h"
test(m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED);
test(m, "exec-dynamicuser-statedir.service", 0, CLD_EXITED);
+ (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
+ (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
+ (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
+ (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
+
test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
test(m, "exec-dynamicuser-statedir-migrate-step2.service", 0, CLD_EXITED);
+
(void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
(void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
" ; # comment3\n"
"line without an equal\n"
"VAR3='$word 5 6'\n"
- "VAR4='new\nline'\n";
+ "VAR4='new\nline'\n"
+ "VAR5=password\\with\\backslashes";
int r;
r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE);
assert_se(setenv("VAR2", "word3", 1) == 0);
assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
assert_se(setenv("VAR4", "new\nline", 1) == 0);
+ assert_se(setenv("VAR5", "passwordwithbackslashes", 1) == 0);
test(m, "exec-passenvironment.service", 0, CLD_EXITED);
test(m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
test(m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
assert_se(unsetenv("VAR2") == 0);
assert_se(unsetenv("VAR3") == 0);
assert_se(unsetenv("VAR4") == 0);
+ assert_se(unsetenv("VAR5") == 0);
test(m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
}
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "io-util.h"
#include "parse-util.h"
#include "process-util.h"
#include "util.h"
static void test_parse_env_file(void) {
- char t[] = "/tmp/test-fileio-in-XXXXXX",
+ _cleanup_(unlink_tempfilep) char
+ t[] = "/tmp/test-fileio-in-XXXXXX",
p[] = "/tmp/test-fileio-out-XXXXXX";
int fd, r;
FILE *f;
r = load_env_file(NULL, p, NULL, &b);
assert_se(r >= 0);
-
- unlink(t);
- unlink(p);
}
static void test_parse_multiline_env_file(void) {
- char t[] = "/tmp/test-fileio-in-XXXXXX",
+ _cleanup_(unlink_tempfilep) char
+ t[] = "/tmp/test-fileio-in-XXXXXX",
p[] = "/tmp/test-fileio-out-XXXXXX";
int fd, r;
FILE *f;
r = load_env_file(NULL, p, NULL, &b);
assert_se(r >= 0);
-
- unlink(t);
- unlink(p);
}
static void test_merge_env_file(void) {
- char t[] = "/tmp/test-fileio-XXXXXX";
+ _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **a = NULL;
}
static void test_merge_env_file_invalid(void) {
- char t[] = "/tmp/test-fileio-XXXXXX";
+ _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **a = NULL;
}
static void test_executable_is_script(void) {
- char t[] = "/tmp/test-executable-XXXXXX";
+ _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX";
int fd, r;
- FILE *f;
+ _cleanup_fclose_ FILE *f = NULL;
char *command;
fd = mkostemp_safe(t);
assert_se(startswith(command, "/"));
free(command);
}
-
- fclose(f);
- unlink(t);
}
static void test_status_field(void) {
}
static void test_write_string_stream(void) {
- char fn[] = "/tmp/test-write_string_stream-XXXXXX";
- FILE *f = NULL;
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_stream-XXXXXX";
+ _cleanup_fclose_ FILE *f = NULL;
int fd;
char buf[64];
assert_se(fgets(buf, sizeof(buf), f));
printf(">%s<", buf);
assert_se(streq(buf, "boohoo"));
- f = safe_fclose(f);
-
- unlink(fn);
}
static void test_write_string_file(void) {
- char fn[] = "/tmp/test-write_string_file-XXXXXX";
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file-XXXXXX";
char buf[64] = {};
_cleanup_close_ int fd;
assert_se(read(fd, buf, sizeof(buf)) == 7);
assert_se(streq(buf, "boohoo\n"));
-
- unlink(fn);
}
static void test_write_string_file_no_create(void) {
- char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX";
_cleanup_close_ int fd;
char buf[64] = {0};
assert_se(read(fd, buf, sizeof(buf)) == STRLEN("boohoo\n"));
assert_se(streq(buf, "boohoo\n"));
-
- unlink(fn);
}
static void test_write_string_file_verify(void) {
int r;
assert_se(read_one_line_file("/proc/cmdline", &buf) >= 0);
- assert_se((buf2 = strjoin(buf, "\n")));
+ assert_se(buf2 = strjoin(buf, "\n"));
r = write_string_file("/proc/cmdline", buf, 0);
assert_se(IN_SET(r, -EACCES, -EIO));
}
static void test_load_env_file_pairs(void) {
- char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
- int fd;
- int r;
+ _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
+ int fd, r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_strv_free_ char **l = NULL;
char **k, **v;
if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/"));
if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/"));
}
-
- unlink(fn);
}
static void test_search_and_fopen(void) {
const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL};
+
char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
+ int fd, r;
FILE *f;
fd = mkostemp_safe(name);
static void test_search_and_fopen_nulstr(void) {
const char dirs[] = "/tmp/foo/bar\0/tmp\0";
- char name[] = "/tmp/test-search_and_fopen.XXXXXX";
- int fd = -1;
- int r;
+
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX";
+ int fd, r;
FILE *f;
fd = mkostemp_safe(name);
}
static void test_writing_tmpfile(void) {
- char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX";
_cleanup_free_ char *contents = NULL;
size_t size;
- int r;
_cleanup_close_ int fd = -1;
struct iovec iov[3];
+ int r;
iov[0] = IOVEC_MAKE_STRING("abc\n");
iov[1] = IOVEC_MAKE_STRING(ALPHANUMERICAL "\n");
assert_se(r == 0);
printf("contents: %s", contents);
assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n"));
-
- unlink(name);
}
static void test_tempfn(void) {
}
static void test_read_line2(void) {
- char name[] = "/tmp/test-fileio.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-fileio.XXXXXX";
int fd;
_cleanup_fclose_ FILE *f = NULL;
}
static void test_path_hashmap(void) {
- _cleanup_(hashmap_freep) Hashmap *h = NULL;
+ _cleanup_hashmap_free_ Hashmap *h = NULL;
assert_se(h = hashmap_new(&path_hash_ops));
assert_se(undecchar('9') == 9);
}
-static void test_unhexmem(void) {
- const char *hex = "efa2149213";
- const char *hex_invalid = "efa214921o";
- _cleanup_free_ char *hex2 = NULL;
+static void test_unhexmem_one(const char *s, size_t l, int retval) {
+ _cleanup_free_ char *hex = NULL;
_cleanup_free_ void *mem = NULL;
size_t len;
- assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == -EINVAL);
- assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
+ assert_se(unhexmem(s, l, &mem, &len) == retval);
+ if (retval == 0) {
+ char *answer;
+
+ if (l == (size_t) -1)
+ l = strlen(s);
+
+ assert_se(hex = hexmem(mem, len));
+ answer = strndupa(s, l);
+ assert_se(streq(delete_chars(answer, WHITESPACE), hex));
+ }
+}
+
+static void test_unhexmem(void) {
+ const char *hex = "efa2149213";
+ const char *hex_space = " e f a\n 2\r 14\n\r\t9\t2 \n1\r3 \r\r\t";
+ const char *hex_invalid = "efa214921o";
- assert_se((hex2 = hexmem(mem, len)));
- assert_se(streq(hex, hex2));
+ test_unhexmem_one(NULL, 0, 0);
+ test_unhexmem_one("", 0, 0);
+ test_unhexmem_one("", (size_t) -1, 0);
+ test_unhexmem_one(" \n \t\r \t\t \n\n\n", (size_t) -1, 0);
+ test_unhexmem_one(hex_invalid, strlen(hex_invalid), -EINVAL);
+ test_unhexmem_one(hex_invalid, (size_t) - 1, -EINVAL);
+ test_unhexmem_one(hex, strlen(hex) - 1, -EPIPE);
+ test_unhexmem_one(hex, strlen(hex), 0);
+ test_unhexmem_one(hex, (size_t) -1, 0);
+ test_unhexmem_one(hex_space, strlen(hex_space), 0);
+ test_unhexmem_one(hex_space, (size_t) -1, 0);
}
/* https://tools.ietf.org/html/rfc4648#section-10 */
free(b32);
}
-static void test_unbase32hexmem(void) {
- void *mem;
+static void test_unbase32hexmem_one(const char *hex, bool padding, int retval, const char *ans) {
+ _cleanup_free_ void *mem = NULL;
size_t len;
- assert_se(unbase32hexmem("", STRLEN(""), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO======", STRLEN("CO======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG====", STRLEN("CPNG===="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU===", STRLEN("CPNMU==="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", STRLEN("CPNMUOG="), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8======", STRLEN("CPNMUOJ1E8======"), true, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("A", STRLEN("A"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A=======", STRLEN("A======="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA=====", STRLEN("AAA====="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA==", STRLEN("AAAAAA=="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB======", STRLEN("AB======"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB====", STRLEN("AAAB===="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB===", STRLEN("AAAAB==="), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB=", STRLEN("AAAAAAB="), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("XPNMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CXNMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPXMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNXUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMXOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUXJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOX1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJX", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL);
-
- assert_se(unbase32hexmem("", STRLEN(""), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), ""));
- free(mem);
-
- assert_se(unbase32hexmem("CO", STRLEN("CO"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "f"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNG", STRLEN("CPNG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMU", STRLEN("CPNMU"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foo"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG", STRLEN("CPNMUOG"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foob"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1", STRLEN("CPNMUOJ1"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "fooba"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOJ1E8", STRLEN("CPNMUOJ1E8"), false, &mem, &len) == 0);
- assert_se(streq(strndupa(mem, len), "foobar"));
- free(mem);
-
- assert_se(unbase32hexmem("CPNMUOG=", STRLEN("CPNMUOG="), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("CPNMUOJ1E8======", STRLEN("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", STRLEN("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("A", STRLEN("A"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAA", STRLEN("AAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAA", STRLEN("AAAAAA"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AB", STRLEN("AB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAB", STRLEN("AAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAB", STRLEN("AAAAB"), false, &mem, &len) == -EINVAL);
- assert_se(unbase32hexmem("AAAAAAB", STRLEN("AAAAAAB"), false, &mem, &len) == -EINVAL);
+ assert_se(unbase32hexmem(hex, (size_t) -1, padding, &mem, &len) == retval);
+ if (retval == 0) {
+ char *str;
+
+ str = strndupa(mem, len);
+ assert_se(streq(str, ans));
+ }
+}
+
+static void test_unbase32hexmem(void) {
+ test_unbase32hexmem_one("", true, 0, "");
+
+ test_unbase32hexmem_one("CO======", true, 0, "f");
+ test_unbase32hexmem_one("CPNG====", true, 0, "fo");
+ test_unbase32hexmem_one("CPNMU===", true, 0, "foo");
+ test_unbase32hexmem_one("CPNMUOG=", true, 0, "foob");
+ test_unbase32hexmem_one("CPNMUOJ1", true, 0, "fooba");
+ test_unbase32hexmem_one("CPNMUOJ1E8======", true, 0, "foobar");
+
+ test_unbase32hexmem_one("A", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("A=======", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAA=====", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAA==", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AB======", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAB====", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAB===", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAAB=", true, -EINVAL, NULL);
+
+ test_unbase32hexmem_one("XPNMUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CXNMUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPXMUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNXUOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMXOJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUXJ1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUOX1", true, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUOJX", true, -EINVAL, NULL);
+
+ test_unbase32hexmem_one("", false, 0, "");
+ test_unbase32hexmem_one("CO", false, 0, "f");
+ test_unbase32hexmem_one("CPNG", false, 0, "fo");
+ test_unbase32hexmem_one("CPNMU", false, 0, "foo");
+ test_unbase32hexmem_one("CPNMUOG", false, 0, "foob");
+ test_unbase32hexmem_one("CPNMUOJ1", false, 0, "fooba");
+ test_unbase32hexmem_one("CPNMUOJ1E8", false, 0, "foobar");
+ test_unbase32hexmem_one("CPNMUOG=", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("CPNMUOJ1E8======", false, -EINVAL, NULL);
+
+ test_unbase32hexmem_one("A", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("A", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAA", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAA", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AB", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAB", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAB", false, -EINVAL, NULL);
+ test_unbase32hexmem_one("AAAAAAB", false, -EINVAL, NULL);
}
/* https://tools.ietf.org/html/rfc4648#section-10 */
r = in_addr_to_string(it->family, &u, &a);
assert_se(IN_SET(r, 0, -EAFNOSUPPORT));
if (r == -EAFNOSUPPORT)
- assert_se((a = hexmem(it->addr, 16)));
+ assert_se(a = hexmem(it->addr, 16));
if (it->scopeid == 0)
goto numerical_index;
#include <sys/types.h>
#include "alloc-util.h"
+#include "all-units.h"
#include "fd-util.h"
#include "fs-util.h"
#include "macro.h"
#include "ratelimit.h"
#include "time-util.h"
-static void test_ratelimit_test(void) {
+static void test_ratelimit_below(void) {
int i;
RATELIMIT_DEFINE(ratelimit, 1 * USEC_PER_SEC, 10);
for (i = 0; i < 10; i++)
- assert_se(ratelimit_test(&ratelimit));
- assert_se(!ratelimit_test(&ratelimit));
+ assert_se(ratelimit_below(&ratelimit));
+ assert_se(!ratelimit_below(&ratelimit));
sleep(1);
for (i = 0; i < 10; i++)
- assert_se(ratelimit_test(&ratelimit));
+ assert_se(ratelimit_below(&ratelimit));
RATELIMIT_INIT(ratelimit, 0, 10);
for (i = 0; i < 10000; i++)
- assert_se(ratelimit_test(&ratelimit));
+ assert_se(ratelimit_below(&ratelimit));
}
int main(int argc, char *argv[]) {
- test_ratelimit_test();
+ test_ratelimit_below();
return 0;
}
.rlim_cur = 10,
.rlim_max = 5,
};
+ int i;
log_parse_environment();
log_open();
new.rlim_max = old.rlim_max;
assert_se(setrlimit(RLIMIT_NOFILE, &new) >= 0);
- assert_se(rlimit_from_string("LimitNOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string("NOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string("LimitNOFILE") == -1);
+ assert_se(rlimit_from_string("RLIMIT_NOFILE") == -1);
+ assert_se(rlimit_from_string("xxxNOFILE") == -1);
assert_se(rlimit_from_string("DefaultLimitNOFILE") == -1);
- assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "LimitNOFILE"));
+ assert_se(rlimit_from_string_harder("NOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string_harder("LimitNOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string_harder("RLIMIT_NOFILE") == RLIMIT_NOFILE);
+ assert_se(rlimit_from_string_harder("xxxNOFILE") == -1);
+ assert_se(rlimit_from_string_harder("DefaultLimitNOFILE") == -1);
+
+ for (i = 0; i < _RLIMIT_MAX; i++) {
+ _cleanup_free_ char *prefixed = NULL;
+ const char *p;
+
+ assert_se(p = rlimit_to_string(i));
+ log_info("%i = %s", i, p);
+
+ assert_se(rlimit_from_string(p) == i);
+ assert_se(rlimit_from_string_harder(p) == i);
+
+ assert_se(prefixed = strjoin("Limit", p));
+
+ assert_se(rlimit_from_string(prefixed) < 0);
+ assert_se(rlimit_from_string_harder(prefixed) == i);
+
+ prefixed = mfree(prefixed);
+ assert_se(prefixed = strjoin("RLIMIT_", p));
+
+ assert_se(rlimit_from_string(prefixed) < 0);
+ assert_se(rlimit_from_string_harder(prefixed) == i);
+ }
+
+ assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "NOFILE"));
assert_se(rlimit_to_string(-1) == NULL);
assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0);
#include <sched.h>
+#include "all-units.h"
#include "macro.h"
#include "manager.h"
#include "rm-rf.h"
};
enum BigEnum {
- big_enum_value = UINT64_C(-1),
+ big_enum_value = UINT64_C(1),
+};
+
+enum BigEnum2 {
+ big_enum2_pos = UINT64_C(1),
+ big_enum2_neg = UINT64_C(-1),
};
int main(void) {
info(enum Enum);
info(enum BigEnum);
+ info(enum BigEnum2);
+ assert_cc(sizeof(enum BigEnum2) == 8);
+ printf("big_enum2_pos → %zu\n", sizeof(big_enum2_pos));
+ printf("big_enum2_neg → %zu\n", sizeof(big_enum2_neg));
return 0;
}
#include "strv.h"
#include "util.h"
+static void test_parse_sleep_config(void) {
+ const char *verb;
+
+ FOREACH_STRING(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")
+ assert_se(parse_sleep_config(verb, NULL, NULL, NULL) == 0);
+}
+
static int test_fiemap(const char *path) {
_cleanup_free_ struct fiemap *fiemap = NULL;
_cleanup_close_ int fd = -1;
if (getuid() != 0)
log_warning("This program is unlikely to work for unprivileged users");
+ test_parse_sleep_config();
test_sleep();
if (argc <= 1)
}
static void test_strbuf(void) {
- struct strbuf *sb;
+ _cleanup_(strbuf_cleanupp) struct strbuf *sb;
_cleanup_strv_free_ char **l;
ssize_t a, b, c, d, e, f, g, h;
strbuf_complete(sb);
assert_se(sb->root == NULL);
-
- strbuf_cleanup(sb);
}
int main(int argc, const char *argv[]) {
#include "fileio.h"
#include "log.h"
#include "macro.h"
+#include "strv.h"
#include "terminal-util.h"
#include "util.h"
printf("Or click on %s to have a look at it!\n", formatted);
}
+static void test_cat_files(void) {
+ assert_se(cat_files("/no/such/file", NULL, 0) == -ENOENT);
+ assert_se(cat_files("/no/such/file", NULL, CAT_FLAGS_MAIN_FILE_OPTIONAL) == 0);
+
+ if (access("/etc/fstab", R_OK) >= 0)
+ assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab"), 0) == 0);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
test_default_term_for_tty();
test_read_one_char();
test_terminal_urlify();
+ test_cat_files();
+
+ print_separator();
return 0;
}
}
static void test_timezone_is_valid(void) {
- assert_se(timezone_is_valid("Europe/Berlin"));
- assert_se(timezone_is_valid("Australia/Sydney"));
- assert_se(!timezone_is_valid("Europe/Do not exist"));
+ assert_se(timezone_is_valid("Europe/Berlin", LOG_ERR));
+ assert_se(timezone_is_valid("Australia/Sydney", LOG_ERR));
+ assert_se(!timezone_is_valid("Europe/Do not exist", LOG_ERR));
}
static void test_get_timezones(void) {
assert_se(r == 0);
STRV_FOREACH(zone, zones)
- assert_se(timezone_is_valid(*zone));
+ assert_se(timezone_is_valid(*zone, LOG_ERR));
}
static void test_usec_add(void) {
#include <unistd.h>
#include "alloc-util.h"
+#include "all-units.h"
#include "capability-util.h"
+#include "conf-parser.h"
#include "fd-util.h"
#include "fileio.h"
+#include "fs-util.h"
#include "hashmap.h"
#include "hostname-util.h"
#include "install-printf.h"
_cleanup_strv_free_ char **data = NULL;
int r;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
fd = mkostemp_safe(name);
assert_se(streq(data[4], "h=h"));
assert_se(streq(data[5], "i=i"));
assert_se(data[6] == NULL);
- unlink(name);
}
static void test_load_env_file_2(void) {
_cleanup_strv_free_ char **data = NULL;
int r;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
fd = mkostemp_safe(name);
assert_se(r == 0);
assert_se(streq(data[0], "a=a"));
assert_se(data[1] == NULL);
- unlink(name);
}
static void test_load_env_file_3(void) {
_cleanup_strv_free_ char **data = NULL;
int r;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
fd = mkostemp_safe(name);
r = load_env_file(NULL, name, NULL, &data);
assert_se(r == 0);
assert_se(data == NULL);
- unlink(name);
}
static void test_load_env_file_4(void) {
_cleanup_strv_free_ char **data = NULL;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
int r;
assert_se(streq(data[1], "MODULE_0=coretemp"));
assert_se(streq(data[2], "MODULE_1=f71882fg"));
assert_se(data[3] == NULL);
- unlink(name);
}
static void test_load_env_file_5(void) {
_cleanup_strv_free_ char **data = NULL;
int r;
- char name[] = "/tmp/test-load-env-file.XXXXXX";
+ _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX";
_cleanup_close_ int fd;
fd = mkostemp_safe(name);
assert_se(streq(data[0], "a="));
assert_se(streq(data[1], "b="));
assert_se(data[2] == NULL);
- unlink(name);
}
static void test_install_printf(void) {
assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid);
assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid);
- assert_se((host = gethostname_malloc()));
- assert_se((user = uid_to_name(getuid())));
+ assert_se(host = gethostname_malloc());
+ assert_se(user = uid_to_name(getuid()));
assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0);
#define expect(src, pattern, result) \
static void test_config_parse_rlimit(void) {
struct rlimit * rl[_RLIMIT_MAX] = {};
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max);
rl[RLIMIT_NOFILE]->rlim_max = 20;
/* Invalid values don't change rl */
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0);
assert_se(rl[RLIMIT_NOFILE]);
assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10);
assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20);
rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == 56);
assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == 57);
assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == 40);
assert_se(rl[RLIMIT_CPU]->rlim_max == 60);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0);
assert_se(rl[RLIMIT_CPU]);
assert_se(rl[RLIMIT_CPU]->rlim_cur == 2);
assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max);
rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58);
assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC);
assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
- assert_se(config_parse_limit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
+ assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0);
assert_se(rl[RLIMIT_RTTIME]);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC);
assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max);
#include <string.h>
#include "alloc-util.h"
+#include "all-units.h"
#include "glob-util.h"
#include "hostname-util.h"
#include "macro.h"
#include "string-util.h"
#include "test-helper.h"
#include "tests.h"
+#include "unit-def.h"
#include "unit-name.h"
#include "unit-printf.h"
#include "unit.h"
_cleanup_free_ char *k = NULL;
assert_se(unit_name_to_path(t, &k) == 0);
puts(strna(k));
- assert_se(path_equal(k, isempty(path) ? "/" : path));
+ assert_se(path_equal(k, empty_to_root(path)));
}
}
assert_se(unit_name_to_instance(t, &k) > 0);
assert_se(unit_name_path_unescape(k, &v) == 0);
- assert_se(path_equal(v, isempty(path) ? "/" : path));
+ assert_se(path_equal(v, empty_to_root(path)));
}
}
test_unit_name_to_prefix_one("@.mount", -EINVAL, NULL);
}
+static void test_unit_name_from_dbus_path_one(const char *input, int ret, const char *output) {
+ _cleanup_free_ char *k = NULL;
+
+ assert_se(unit_name_from_dbus_path(input, &k) == ret);
+ assert_se(streq_ptr(k, output));
+}
+
+static void test_unit_name_from_dbus_path(void) {
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2esocket", 0, "dbus.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2emount", 0, "-.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2eslice", 0, "-.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/accounts_2ddaemon_2eservice", 0, "accounts-daemon.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/auditd_2eservice", 0, "auditd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/basic_2etarget", 0, "basic.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/bluetooth_2etarget", 0, "bluetooth.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/boot_2eautomount", 0, "boot.automount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/boot_2emount", 0, "boot.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/btrfs_2emount", 0, "btrfs.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/cryptsetup_2dpre_2etarget", 0, "cryptsetup-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/cryptsetup_2etarget", 0, "cryptsetup.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2eservice", 0, "dbus.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2esocket", 0, "dbus.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dcdrom_2edevice", 0, "dev-cdrom.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M120G2GC_5fCVPO044405HH120QGN_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M120G2GC_CVPO044405HH120QGN.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M120G2GC_5fCVPO044405HH120QGN_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M120G2GC_CVPO044405HH120QGN\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_5cx2dpart2_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN\\x2dpart2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_5cx2dpart3_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN\\x2dpart3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dTSSTcorp_5fCDDVDW_5fTS_5cx2dL633C_5fR6176GLZB14646_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dTSSTcorp_CDDVDW_TS\\x2dL633C_R6176GLZB14646.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_5cx2dpart2_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae\\x2dpart2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_5cx2dpart3_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae\\x2dpart3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x500151795946eab5_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x500151795946eab5.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x500151795946eab5_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x500151795946eab5\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dlabel_2d_5cxe3_5cx82_5cxb7_5cxe3_5cx82_5cxb9_5cxe3_5cx83_5cx86_5cxe3_5cx83_5cxa0_5cxe3_5cx81_5cxa7_5cxe4_5cxba_5cx88_5cxe7_5cxb4_5cx84_5cxe6_5cxb8_5cx88_5cxe3_5cx81_5cxbf_2edevice", 0, "dev-disk-by\\x2dlabel-\\xe3\\x82\\xb7\\xe3\\x82\\xb9\\xe3\\x83\\x86\\xe3\\x83\\xa0\\xe3\\x81\\xa7\\xe4\\xba\\x88\\xe7\\xb4\\x84\\xe6\\xb8\\x88\\xe3\\x81\\xbf.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d59834e50_5cx2d01_2edevice", 0, "dev-disk-by\\x2dpartuuid-59834e50\\x2d01.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d63e2a7b3_5cx2d01_2edevice", 0, "dev-disk-by\\x2dpartuuid-63e2a7b3\\x2d01.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d63e2a7b3_5cx2d02_2edevice", 0, "dev-disk-by\\x2dpartuuid-63e2a7b3\\x2d02.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d63e2a7b3_5cx2d03_2edevice", 0, "dev-disk-by\\x2dpartuuid-63e2a7b3\\x2d03.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_5cx2dpart2_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1\\x2dpart2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_5cx2dpart3_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1\\x2dpart3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d2_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d6_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d6.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d6_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d6\\x2dpart1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2d1A34E3F034E3CD37_2edevice", 0, "dev-disk-by\\x2duuid-1A34E3F034E3CD37.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2dB670EBFE70EBC2EB_2edevice", 0, "dev-disk-by\\x2duuid-B670EBFE70EBC2EB.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2dFCD4F509D4F4C6C4_2edevice", 0, "dev-disk-by\\x2duuid-FCD4F509D4F4C6C4.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2db49ead57_5cx2d907c_5cx2d446c_5cx2db405_5cx2d5ca6cd865f5e_2edevice", 0, "dev-disk-by\\x2duuid-b49ead57\\x2d907c\\x2d446c\\x2db405\\x2d5ca6cd865f5e.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dhugepages_2emount", 0, "dev-hugepages.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dmqueue_2emount", 0, "dev-mqueue.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2drfkill_2edevice", 0, "dev-rfkill.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda1_2edevice", 0, "dev-sda1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda2_2edevice", 0, "dev-sda2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda3_2edevice", 0, "dev-sda3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda_2edevice", 0, "dev-sda.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsdb1_2edevice", 0, "dev-sdb1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsdb_2edevice", 0, "dev-sdb.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsr0_2edevice", 0, "dev-sr0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS0_2edevice", 0, "dev-ttyS0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS10_2edevice", 0, "dev-ttyS10.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS11_2edevice", 0, "dev-ttyS11.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS12_2edevice", 0, "dev-ttyS12.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS13_2edevice", 0, "dev-ttyS13.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS14_2edevice", 0, "dev-ttyS14.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS15_2edevice", 0, "dev-ttyS15.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS16_2edevice", 0, "dev-ttyS16.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS17_2edevice", 0, "dev-ttyS17.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS18_2edevice", 0, "dev-ttyS18.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS19_2edevice", 0, "dev-ttyS19.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS1_2edevice", 0, "dev-ttyS1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS20_2edevice", 0, "dev-ttyS20.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS21_2edevice", 0, "dev-ttyS21.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS22_2edevice", 0, "dev-ttyS22.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS23_2edevice", 0, "dev-ttyS23.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS24_2edevice", 0, "dev-ttyS24.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS25_2edevice", 0, "dev-ttyS25.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS26_2edevice", 0, "dev-ttyS26.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS27_2edevice", 0, "dev-ttyS27.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS28_2edevice", 0, "dev-ttyS28.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS29_2edevice", 0, "dev-ttyS29.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS2_2edevice", 0, "dev-ttyS2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS30_2edevice", 0, "dev-ttyS30.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS31_2edevice", 0, "dev-ttyS31.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS3_2edevice", 0, "dev-ttyS3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS4_2edevice", 0, "dev-ttyS4.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS5_2edevice", 0, "dev-ttyS5.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS6_2edevice", 0, "dev-ttyS6.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS7_2edevice", 0, "dev-ttyS7.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS8_2edevice", 0, "dev-ttyS8.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS9_2edevice", 0, "dev-ttyS9.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dcmdline_2eservice", 0, "dracut-cmdline.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dinitqueue_2eservice", 0, "dracut-initqueue.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dmount_2eservice", 0, "dracut-mount.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dmount_2eservice", 0, "dracut-pre-mount.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dpivot_2eservice", 0, "dracut-pre-pivot.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dtrigger_2eservice", 0, "dracut-pre-trigger.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dudev_2eservice", 0, "dracut-pre-udev.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dshutdown_2eservice", 0, "dracut-shutdown.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ebtables_2eservice", 0, "ebtables.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/emergency_2eservice", 0, "emergency.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/emergency_2etarget", 0, "emergency.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/fedora_2dimport_2dstate_2eservice", 0, "fedora-import-state.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/fedora_2dreadonly_2eservice", 0, "fedora-readonly.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/firewalld_2eservice", 0, "firewalld.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/getty_2dpre_2etarget", 0, "getty-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/getty_2etarget", 0, "getty.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/getty_40tty1_2eservice", 0, "getty@tty1.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/graphical_2etarget", 0, "graphical.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/home_2emount", 0, "home.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/init_2escope", 0, "init.scope");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dcleanup_2eservice", 0, "initrd-cleanup.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dfs_2etarget", 0, "initrd-fs.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dparse_2detc_2eservice", 0, "initrd-parse-etc.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2droot_2ddevice_2etarget", 0, "initrd-root-device.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2droot_2dfs_2etarget", 0, "initrd-root-fs.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dswitch_2droot_2eservice", 0, "initrd-switch-root.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dswitch_2droot_2etarget", 0, "initrd-switch-root.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dudevadm_2dcleanup_2ddb_2eservice", 0, "initrd-udevadm-cleanup-db.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2etarget", 0, "initrd.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ip6tables_2eservice", 0, "ip6tables.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ipset_2eservice", 0, "ipset.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/iptables_2eservice", 0, "iptables.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/irqbalance_2eservice", 0, "irqbalance.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/kmod_2dstatic_2dnodes_2eservice", 0, "kmod-static-nodes.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ldconfig_2eservice", 0, "ldconfig.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/lightdm_2eservice", 0, "lightdm.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/livesys_2dlate_2eservice", 0, "livesys-late.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/lm_5fsensors_2eservice", 0, "lm_sensors.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/local_2dfs_2dpre_2etarget", 0, "local-fs-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/local_2dfs_2etarget", 0, "local-fs.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/machines_2etarget", 0, "machines.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/mcelog_2eservice", 0, "mcelog.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/multi_2duser_2etarget", 0, "multi-user.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/network_2dpre_2etarget", 0, "network-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/network_2etarget", 0, "network.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/nss_2dlookup_2etarget", 0, "nss-lookup.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/nss_2duser_2dlookup_2etarget", 0, "nss-user-lookup.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/paths_2etarget", 0, "paths.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/plymouth_2dquit_2dwait_2eservice", 0, "plymouth-quit-wait.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/plymouth_2dquit_2eservice", 0, "plymouth-quit.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/plymouth_2dstart_2eservice", 0, "plymouth-start.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/polkit_2eservice", 0, "polkit.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount", 0, "proc-sys-fs-binfmt_misc.automount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2emount", 0, "proc-sys-fs-binfmt_misc.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/rc_2dlocal_2eservice", 0, "rc-local.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/remote_2dcryptsetup_2etarget", 0, "remote-cryptsetup.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/remote_2dfs_2dpre_2etarget", 0, "remote-fs-pre.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/remote_2dfs_2etarget", 0, "remote-fs.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/rescue_2eservice", 0, "rescue.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/rescue_2etarget", 0, "rescue.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/run_2duser_2d1000_2emount", 0, "run-user-1000.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/session_2d2_2escope", 0, "session-2.scope");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/shutdown_2etarget", 0, "shutdown.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/slices_2etarget", 0, "slices.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/smartd_2eservice", 0, "smartd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sockets_2etarget", 0, "sockets.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sound_2etarget", 0, "sound.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_2etarget", 0, "sshd-keygen.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_40ecdsa_2eservice", 0, "sshd-keygen@ecdsa.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_40ed25519_2eservice", 0, "sshd-keygen@ed25519.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_40rsa_2eservice", 0, "sshd-keygen@rsa.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2eservice", 0, "sshd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/swap_2etarget", 0, "swap.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a02_2e0_2dbacklight_2dacpi_5fvideo0_2edevice", 0, "sys-devices-pci0000:00-0000:00:02.0-backlight-acpi_video0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a02_2e0_2ddrm_2dcard0_2dcard0_5cx2dLVDS_5cx2d1_2dintel_5fbacklight_2edevice", 0, "sys-devices-pci0000:00-0000:00:02.0-drm-card0-card0\\x2dLVDS\\x2d1-intel_backlight.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1a_2e0_2dusb1_2d1_5cx2d1_2d1_5cx2d1_2e6_2d1_5cx2d1_2e6_3a1_2e0_2dbluetooth_2dhci0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1a.0-usb1-1\\x2d1-1\\x2d1.6-1\\x2d1.6:1.0-bluetooth-hci0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1b_2e0_2dsound_2dcard0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1b.0-sound-card0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1c_2e0_2d0000_3a02_3a00_2e0_2dnet_2dwlp2s0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1c.0-0000:02:00.0-net-wlp2s0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1c_2e2_2d0000_3a04_3a00_2e0_2dnet_2denp4s0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1c.2-0000:04:00.0-net-enp4s0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2dsda1_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2dsda2_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2dsda3_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data2_2dhost1_2dtarget1_3a0_3a0_2d1_3a0_3a0_3a0_2dblock_2dsr0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata2-host1-target1:0:0-1:0:0:0-block-sr0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data6_2dhost5_2dtarget5_3a0_3a0_2d5_3a0_3a0_3a0_2dblock_2dsdb_2dsdb1_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata6-host5-target5:0:0-5:0:0:0-block-sdb-sdb1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data6_2dhost5_2dtarget5_3a0_3a0_2d5_3a0_3a0_3a0_2dblock_2dsdb_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata6-host5-target5:0:0-5:0:0:0-block-sdb.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS0_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS10_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS10.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS11_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS11.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS12_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS12.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS13_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS13.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS14_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS14.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS15_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS15.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS16_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS16.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS17_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS17.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS18_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS18.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS19_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS19.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS1_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS1.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS20_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS20.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS21_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS21.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS22_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS22.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS23_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS23.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS24_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS24.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS25_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS25.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS26_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS26.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS27_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS27.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS28_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS28.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS29_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS29.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS2_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS2.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS30_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS30.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS31_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS31.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS3_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS3.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS4_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS4.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS5_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS5.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS6_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS6.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS7_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS7.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS8_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS8.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS9_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS9.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dvirtual_2dmisc_2drfkill_2edevice", 0, "sys-devices-virtual-misc-rfkill.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dfs_2dfuse_2dconnections_2emount", 0, "sys-fs-fuse-connections.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dkernel_2dconfig_2emount", 0, "sys-kernel-config.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dkernel_2ddebug_2emount", 0, "sys-kernel-debug.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dmodule_2dconfigfs_2edevice", 0, "sys-module-configfs.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dbluetooth_2ddevices_2dhci0_2edevice", 0, "sys-subsystem-bluetooth-devices-hci0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2denp4s0_2edevice", 0, "sys-subsystem-net-devices-enp4s0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2dwlp2s0_2edevice", 0, "sys-subsystem-net-devices-wlp2s0.device");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sysinit_2etarget", 0, "sysinit.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/syslog_2eservice", 0, "syslog.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/syslog_2esocket", 0, "syslog.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/syslog_2etarget", 0, "syslog.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sysroot_2emount", 0, "sysroot.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dgetty_2eslice", 0, "system-getty.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dsshd_5cx2dkeygen_2eslice", 0, "system-sshd\\x2dkeygen.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dsystemd_5cx2dbacklight_2eslice", 0, "system-systemd\\x2dbacklight.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dsystemd_5cx2dcoredump_2eslice", 0, "system-systemd\\x2dcoredump.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2duser_5cx2druntime_5cx2ddir_2eslice", 0, "system-user\\x2druntime\\x2ddir.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2eslice", 0, "system.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dconsole_2epath", 0, "systemd-ask-password-console.path");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dconsole_2eservice", 0, "systemd-ask-password-console.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dwall_2epath", 0, "systemd-ask-password-wall.path");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dwall_2eservice", 0, "systemd-ask-password-wall.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dbacklight_40backlight_3aacpi_5fvideo0_2eservice", 0, "systemd-backlight@backlight:acpi_video0.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dbacklight_40backlight_3aintel_5fbacklight_2eservice", 0, "systemd-backlight@backlight:intel_backlight.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dbinfmt_2eservice", 0, "systemd-binfmt.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dcoredump_2esocket", 0, "systemd-coredump.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dcoredump_400_2eservice", 0, "systemd-coredump@0.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dfirstboot_2eservice", 0, "systemd-firstboot.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dfsck_2droot_2eservice", 0, "systemd-fsck-root.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dhwdb_2dupdate_2eservice", 0, "systemd-hwdb-update.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dinitctl_2eservice", 0, "systemd-initctl.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dinitctl_2esocket", 0, "systemd-initctl.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournal_2dcatalog_2dupdate_2eservice", 0, "systemd-journal-catalog-update.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournal_2dflush_2eservice", 0, "systemd-journal-flush.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2daudit_2esocket", 0, "systemd-journald-audit.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2ddev_2dlog_2esocket", 0, "systemd-journald-dev-log.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2eservice", 0, "systemd-journald.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2esocket", 0, "systemd-journald.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dlogind_2eservice", 0, "systemd-logind.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dmachine_2did_2dcommit_2eservice", 0, "systemd-machine-id-commit.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dmodules_2dload_2eservice", 0, "systemd-modules-load.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dnetworkd_2eservice", 0, "systemd-networkd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dnetworkd_2esocket", 0, "systemd-networkd.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2drandom_2dseed_2eservice", 0, "systemd-random-seed.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dremount_2dfs_2eservice", 0, "systemd-remount-fs.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dresolved_2eservice", 0, "systemd-resolved.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2drfkill_2eservice", 0, "systemd-rfkill.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2drfkill_2esocket", 0, "systemd-rfkill.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dsysctl_2eservice", 0, "systemd-sysctl.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dsysusers_2eservice", 0, "systemd-sysusers.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtimesyncd_2eservice", 0, "systemd-timesyncd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2eservice", 0, "systemd-tmpfiles-clean.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer", 0, "systemd-tmpfiles-clean.timer");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dsetup_2ddev_2eservice", 0, "systemd-tmpfiles-setup-dev.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dsetup_2eservice", 0, "systemd-tmpfiles-setup.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudev_2dtrigger_2eservice", 0, "systemd-udev-trigger.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2dcontrol_2esocket", 0, "systemd-udevd-control.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2dkernel_2esocket", 0, "systemd-udevd-kernel.socket");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2eservice", 0, "systemd-udevd.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2ddone_2eservice", 0, "systemd-update-done.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2dutmp_2drunlevel_2eservice", 0, "systemd-update-utmp-runlevel.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2dutmp_2eservice", 0, "systemd-update-utmp.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2duser_2dsessions_2eservice", 0, "systemd-user-sessions.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dvconsole_2dsetup_2eservice", 0, "systemd-vconsole-setup.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/time_2dsync_2etarget", 0, "time-sync.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/timers_2etarget", 0, "timers.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/tmp_2emount", 0, "tmp.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/umount_2etarget", 0, "umount.target");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/unbound_2danchor_2eservice", 0, "unbound-anchor.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/unbound_2danchor_2etimer", 0, "unbound-anchor.timer");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/upower_2eservice", 0, "upower.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_2d1000_2eslice", 0, "user-1000.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_2druntime_2ddir_401000_2eservice", 0, "user-runtime-dir@1000.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_2eslice", 0, "user.slice");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_401000_2eservice", 0, "user@1000.service");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/usr_2dlocal_2dtexlive_2emount", 0, "usr-local-texlive.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/var_2dlib_2dmachines_2emount", 0, "var-lib-machines.mount");
+ test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/wpa_5fsupplicant_2eservice", 0, "wpa_supplicant.service");
+}
+
int main(int argc, char* argv[]) {
_cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
int r, rc = 0;
test_unit_name_template();
test_unit_name_path_unescape();
test_unit_name_to_prefix();
+ test_unit_name_from_dbus_path();
return rc;
}
#include "log.h"
#include "manager.h"
#include "rm-rf.h"
+#include "service.h"
#include "test-helper.h"
#include "tests.h"
<action id="org.freedesktop.timedate1.set-local-rtc">
<description gettext-domain="systemd">Set RTC to local timezone or UTC</description>
- <message gettext-domain="systemd">Authentication is required to control whether
- the RTC stores the local or UTC time.</message>
+ <message gettext-domain="systemd">Authentication is required to control whether the RTC stores the local or UTC time.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<action id="org.freedesktop.timedate1.set-ntp">
<description gettext-domain="systemd">Turn network time synchronization on or off</description>
- <message gettext-domain="systemd">Authentication is required to control whether
- network time synchronization shall be enabled.</message>
+ <message gettext-domain="systemd">Authentication is required to control whether network time synchronization shall be enabled.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
return 0;
}
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_time, "t", now(CLOCK_REALTIME));
+static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_ntp_sync, "b", ntp_synced());
+
static int property_get_rtc_time(
sd_bus *bus,
const char *path,
return sd_bus_message_append(reply, "t", t);
}
-static int property_get_time(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- return sd_bus_message_append(reply, "t", now(CLOCK_REALTIME));
-}
-
-static int property_get_ntp_sync(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- return sd_bus_message_append(reply, "b", ntp_synced());
-}
-
static int property_get_can_ntp(
sd_bus *bus,
const char *path,
static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *error) {
Context *c = userdata;
+ int interactive, r;
const char *z;
- int interactive;
- char *t;
- int r;
assert(m);
assert(c);
if (r < 0)
return r;
- if (!timezone_is_valid(z))
+ if (!timezone_is_valid(z, LOG_DEBUG))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid time zone '%s'", z);
if (streq_ptr(z, c->zone))
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
- t = strdup(z);
- if (!t)
- return -ENOMEM;
-
- free(c->zone);
- c->zone = t;
+ r = free_and_strdup(&c->zone, z);
+ if (r < 0)
+ return r;
/* 1. Write new configuration file */
r = context_write_data_timezone(c);
assert(bus);
assert(reply);
- return sd_bus_message_append(reply, "s", *s ? (*s)->string : "");
+ return sd_bus_message_append(reply, "s", *s ? (*s)->string : NULL);
}
static int property_get_current_server_address(
SD_BUS_VTABLE_END
};
-static int reload_dbus_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- const sd_bus_error *e;
- int r;
-
- assert(m);
-
- e = sd_bus_message_get_error(m);
- if (e) {
- log_error_errno(sd_bus_error_get_errno(e), "Failed to reload DBus configuration: %s", e->message);
- return 1;
- }
-
- /* Here, use the default request name handler to avoid an infinite loop of reloading and requesting. */
- r = sd_bus_request_name_async(sd_bus_message_get_bus(m), NULL, "org.freedesktop.timesync1", 0, NULL, NULL);
- if (r < 0)
- log_error_errno(r, "Failed to request name: %m");
-
- return 1;
-}
-
-static int request_name_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
- uint32_t ret;
- int r;
-
- assert(m);
-
- if (sd_bus_message_is_method_error(m, NULL)) {
- const sd_bus_error *e = sd_bus_message_get_error(m);
-
- if (!sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) {
- log_debug_errno(sd_bus_error_get_errno(e),
- "Unable to request name, failing connection: %s",
- e->message);
-
- bus_enter_closing(sd_bus_message_get_bus(m));
- return 1;
- }
-
- log_debug_errno(sd_bus_error_get_errno(e),
- "Unable to request name, retry after reloading DBus configuration: %s",
- e->message);
-
- /* If systemd-timesyncd.service enables DynamicUser= and dbus.service
- * started before the dynamic user is realized, then the DBus policy
- * about timesyncd has not been enabled yet. So, let's try to reload
- * DBus configuration, and after that request name again. Note that it
- * seems that no privileges are necessary to call the following method. */
-
- r = sd_bus_call_method_async(
- sd_bus_message_get_bus(m),
- NULL,
- "org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "ReloadConfig",
- reload_dbus_handler,
- NULL, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to reload DBus configuration: %m");
- bus_enter_closing(sd_bus_message_get_bus(m));
- }
-
- return 1;
- }
-
- r = sd_bus_message_read(m, "u", &ret);
- if (r < 0)
- return r;
-
- switch (ret) {
-
- case BUS_NAME_ALREADY_OWNER:
- log_debug("Already owner of requested service name, ignoring.");
- return 1;
-
- case BUS_NAME_IN_QUEUE:
- log_debug("In queue for requested service name.");
- return 1;
-
- case BUS_NAME_PRIMARY_OWNER:
- log_debug("Successfully acquired requested service name.");
- return 1;
-
- case BUS_NAME_EXISTS:
- log_debug("Requested service name already owned, failing connection.");
- bus_enter_closing(sd_bus_message_get_bus(m));
- return 1;
- }
-
- log_debug("Unexpected response from RequestName(), failing connection.");
- bus_enter_closing(sd_bus_message_get_bus(m));
- return 1;
-}
-
int manager_connect_bus(Manager *m) {
int r;
if (r < 0)
return log_error_errno(r, "Failed to add manager object vtable: %m");
- r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.timesync1", 0, request_name_handler, NULL);
+ r = bus_request_name_async_may_reload_dbus(m->bus, NULL, "org.freedesktop.timesync1", 0, NULL);
if (r < 0)
return log_error_errno(r, "Failed to request name: %m");
int manager_parse_server_string(Manager *m, ServerType type, const char *string);
-int config_parse_servers(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+CONFIG_PARSER_PROTOTYPE(config_parse_servers);
int manager_parse_config_file(Manager *m);
int manager_parse_fallback_string(Manager *m, const char *string);
manager_disconnect(m);
m->event_retry = sd_event_source_unref(m->event_retry);
- if (!ratelimit_test(&m->ratelimit)) {
+ if (!ratelimit_below(&m->ratelimit)) {
log_debug("Slowing down attempts to contact servers.");
r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + RETRY_USEC, 0, manager_retry_connect, m);
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
#include "umask-util.h"
#include "user-util.h"
#include "util.h"
_DIRECTORY_TYPE_MAX,
} DirectoryType;
+static bool arg_cat_config = false;
static bool arg_user = false;
static bool arg_create = false;
static bool arg_clean = false;
r = action(i, fd, st);
if (S_ISDIR(st->st_mode)) {
- char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
+ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
if (IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) {
- if (btrfs_is_subvol(isempty(arg_root) ? "/" : arg_root) <= 0)
+ if (btrfs_is_subvol(empty_to_root(arg_root)) <= 0)
/* Don't create a subvolume unless the
* root directory is one, too. We do
return 0;
}
+static int patch_var_run(const char *fname, unsigned line, char **path) {
+ const char *k;
+ char *n;
+
+ assert(path);
+ assert(*path);
+
+ /* Optionally rewrites lines referencing /var/run/, to use /run/ instead. Why bother? tmpfiles merges lines in
+ * some cases and detects conflicts in others. If files/directories are specified through two equivalent lines
+ * this is problematic as neither case will be detected. Ideally we'd detect these cases by resolving symlinks
+ * early, but that's precisely not what we can do here as this code very likely is running very early on, at a
+ * time where the paths in question are not available yet, or even more importantly, our own tmpfiles rules
+ * might create the paths that are intermediary to the listed paths. We can't really cover the generic case,
+ * but the least we can do is cover the specific case of /var/run vs. /run, as /var/run is a legacy name for
+ * /run only, and we explicitly document that and require that on systemd systems the former is a symlink to
+ * the latter. Moreover files below this path are by far the primary usecase for tmpfiles.d/. */
+
+ k = path_startswith(*path, "/var/run/");
+ if (isempty(k)) /* Don't complain about other paths than /var/run, and not about /var/run itself either. */
+ return 0;
+
+ n = strjoin("/run/", k);
+ if (!n)
+ return log_oom();
+
+ /* Also log about this briefly. We do so at LOG_NOTICE level, as we fixed up the situation automatically, hence
+ * there's no immediate need for action by the user. However, in the interest of making things less confusing
+ * to the user, let's still inform the user that these snippets should really be updated. */
+
+ log_notice("[%s:%u] Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.", fname, line, *path, n);
+
+ free(*path);
+ *path = n;
+
+ return 0;
+}
+
static int parse_line(const char *fname, unsigned line, const char *buffer, bool *invalid_config) {
_cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
/* invalid quoting and such or an unknown specifier */
*invalid_config = true;
return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
- }
-
- else if (r < 2) {
+ } else if (r < 2) {
*invalid_config = true;
log_error("[%s:%u] Syntax error.", fname, line);
return -EIO;
return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, path);
}
+ r = patch_var_run(fname, line, &i.path);
+ if (r < 0)
+ return r;
+
switch (i.type) {
case CREATE_DIRECTORY:
return 0;
}
+static int cat_config(char **config_dirs, char **args) {
+ _cleanup_strv_free_ char **files = NULL;
+ int r;
+
+ r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, NULL);
+ if (r < 0)
+ return r;
+
+ return cat_files(NULL, files, 0);
+}
+
static void help(void) {
printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
"Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
" -h --help Show this help\n"
" --user Execute user configuration\n"
" --version Show package version\n"
+ " --cat-config Show configuration files\n"
" --create Create marked files/directories\n"
" --clean Clean up marked directories\n"
" --remove Remove marked files/directories\n"
enum {
ARG_VERSION = 0x100,
+ ARG_CAT_CONFIG,
ARG_USER,
ARG_CREATE,
ARG_CLEAN,
{ "help", no_argument, NULL, 'h' },
{ "user", no_argument, NULL, ARG_USER },
{ "version", no_argument, NULL, ARG_VERSION },
+ { "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
{ "create", no_argument, NULL, ARG_CREATE },
{ "clean", no_argument, NULL, ARG_CLEAN },
{ "remove", no_argument, NULL, ARG_REMOVE },
case ARG_VERSION:
return version();
+ case ARG_CAT_CONFIG:
+ arg_cat_config = true;
+ break;
+
case ARG_USER:
arg_user = true;
break;
assert_not_reached("Unhandled option");
}
- if (!arg_clean && !arg_create && !arg_remove) {
+ if (!arg_clean && !arg_create && !arg_remove && !arg_cat_config) {
log_error("You need to specify at least one of --clean, --create or --remove.");
return -EINVAL;
}
+ if (arg_replace && arg_cat_config) {
+ log_error("Option --replace= is not supported with --cat-config");
+ return -EINVAL;
+ }
+
if (arg_replace && optind >= argc) {
log_error("When --replace= is given, some configuration items must be specified");
return -EINVAL;
char **f;
int r;
- r = conf_files_list_strv(&files, ".conf", arg_root, 0, (const char* const*) config_dirs);
+ r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, &p);
if (r < 0)
- return log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
-
- if (arg_replace) {
- r = conf_files_insert(&files, arg_root, config_dirs, arg_replace);
- if (r < 0)
- return log_error_errno(r, "Failed to extend tmpfiles.d file list: %m");
-
- p = path_join(arg_root, arg_replace, NULL);
- if (!p)
- return log_oom();
- }
+ return r;
STRV_FOREACH(f, files)
if (p && path_equal(*f, p)) {
log_parse_environment();
log_open();
- umask(0022);
-
- mac_selinux_init();
-
- items = ordered_hashmap_new(&string_hash_ops);
- globs = ordered_hashmap_new(&string_hash_ops);
-
- if (!items || !globs) {
- r = log_oom();
- goto finish;
- }
-
- r = 0;
-
if (arg_user) {
r = user_config_paths(&config_dirs);
if (r < 0) {
log_debug("Looking for configuration files in (higher priority first):\n\t%s", t);
}
+ if (arg_cat_config) {
+ r = cat_config(config_dirs, argv + optind);
+ goto finish;
+ }
+
+ umask(0022);
+
+ mac_selinux_init();
+
+ items = ordered_hashmap_new(&string_hash_ops);
+ globs = ordered_hashmap_new(&string_hash_ops);
+
+ if (!items || !globs) {
+ r = log_oom();
+ goto finish;
+ }
+
/* If command line arguments are specified along with --replace, read all
* configuration files and insert the positional arguments at the specified
* place. Otherwise, if command line arguments are specified, execute just
c_args : ['-fvisibility=default'])
libudev_static = static_library(
- 'udev',
+ 'udev_static',
'udev.h',
include_directories : includes,
link_with : udev_link_with,
link_whole : libudev_basic)
+static_libudev = get_option('static-libudev')
+static_libudev_pic = static_libudev == 'true' or static_libudev == 'pic'
+install_libudev_static = static_library(
+ 'udev',
+ basic_sources,
+ shared_sources,
+ libsystemd_sources,
+ libudev_sources,
+ include_directories : includes,
+ build_by_default : static_libudev != 'false',
+ install : static_libudev != 'false',
+ install_dir : rootlibdir,
+ link_depends : libudev_sym,
+ dependencies : libshared_deps + [libmount],
+ c_args : static_libudev_pic ? [] : ['-fno-PIC'],
+ pic : static_libudev_pic)
+
libudev = shared_library(
'udev',
'udev.h', # pick a header file at random to work around old meson bug
* Boston, MA 02110-1301 USA
*/
+#include <errno.h>
#include <fcntl.h>
#include <mtd/mtd-user.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
+#include "alloc-util.h"
+#include "fd-util.h"
#include "mtd_probe.h"
-int main(int argc, char** argv)
-{
- int mtd_fd;
- int error;
+int main(int argc, char** argv) {
+ _cleanup_close_ int mtd_fd = -1;
mtd_info_t mtd_info;
if (argc != 2) {
printf("usage: mtd_probe /dev/mtd[n]\n");
- return 1;
+ return EXIT_FAILURE;
}
mtd_fd = open(argv[1], O_RDONLY|O_CLOEXEC);
- if (mtd_fd == -1) {
- perror("open");
- exit(-1);
+ if (mtd_fd < 0) {
+ log_error_errno(errno, "Failed to open: %m");
+ return EXIT_FAILURE;
}
- error = ioctl(mtd_fd, MEMGETINFO, &mtd_info);
- if (error == -1) {
- perror("ioctl");
- exit(-1);
+ if (ioctl(mtd_fd, MEMGETINFO, &mtd_info) < 0) {
+ log_error_errno(errno, "Failed to issue MEMGETINFO ioctl: %m");
+ return EXIT_FAILURE;
}
- probe_smart_media(mtd_fd, &mtd_info);
- return -1;
+ if (probe_smart_media(mtd_fd, &mtd_info) < 0)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
}
#define SM_SMALL_PAGE 256
#define SM_SMALL_OOB_SIZE 8
-void probe_smart_media(int mtd_fd, mtd_info_t *info);
+int probe_smart_media(int mtd_fd, mtd_info_t *info);
* Boston, MA 02110-1301 USA
*/
+#include <errno.h>
#include <fcntl.h>
#include <mtd/mtd-user.h>
#include <stdint.h>
0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20
};
-void probe_smart_media(int mtd_fd, mtd_info_t* info) {
+int probe_smart_media(int mtd_fd, mtd_info_t* info) {
int sector_size;
int block_size;
int size_in_megs;
cis_buffer = malloc(SM_SECTOR_SIZE);
if (!cis_buffer)
- return;
+ return log_oom();
- if (info->type != MTD_NANDFLASH)
- goto exit;
+ if (info->type != MTD_NANDFLASH) {
+ log_debug("Not marked MTD_NANDFLASH.");
+ return -EINVAL;
+ }
sector_size = info->writesize;
block_size = info->erasesize;
size_in_megs = info->size / (1024 * 1024);
- if (!IN_SET(sector_size, SM_SECTOR_SIZE, SM_SMALL_PAGE))
- goto exit;
+ if (!IN_SET(sector_size, SM_SECTOR_SIZE, SM_SMALL_PAGE)) {
+ log_debug("Unexpected sector size: %i", sector_size);
+ return -EINVAL;
+ }
switch(size_in_megs) {
case 1:
break;
}
- for (offset = 0 ; offset < block_size * spare_count ;
- offset += sector_size) {
- lseek(mtd_fd, SEEK_SET, offset);
+ for (offset = 0; offset < block_size * spare_count; offset += sector_size) {
+ (void) lseek(mtd_fd, SEEK_SET, offset);
+
if (read(mtd_fd, cis_buffer, SM_SECTOR_SIZE) == SM_SECTOR_SIZE) {
cis_found = 1;
break;
}
}
- if (!cis_found)
- goto exit;
+ if (!cis_found) {
+ log_debug("CIS not found");
+ return -EINVAL;
+ }
if (memcmp(cis_buffer, cis_signature, sizeof(cis_signature)) != 0 &&
- (memcmp(cis_buffer + SM_SMALL_PAGE, cis_signature,
- sizeof(cis_signature)) != 0))
- goto exit;
+ memcmp(cis_buffer + SM_SMALL_PAGE, cis_signature, sizeof(cis_signature)) != 0) {
+ log_debug("CIS signature didn't match");
+ return -EINVAL;
+ }
printf("MTD_FTL=smartmedia\n");
- exit(EXIT_SUCCESS);
-
-exit:
- return;
+ return 0;
}
return r;
}
+
+int config_parse_channel(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ link_config *config = data;
+ uint32_t k;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou32(rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse channel value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (k < 1) {
+ log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid %s value, ignoring: %s", lvalue, rvalue);
+ return 0;
+ }
+
+ if (streq(lvalue, "RxChannels")) {
+ config->channels.rx_count = k;
+ config->channels.rx_count_set = true;
+ } else if (streq(lvalue, "TxChannels")) {
+ config->channels.tx_count = k;
+ config->channels.tx_count_set = true;
+ } else if (streq(lvalue, "OtherChannels")) {
+ config->channels.other_count = k;
+ config->channels.other_count_set = true;
+ } else if (streq(lvalue, "CombinedChannels")) {
+ config->channels.combined_count = k;
+ config->channels.combined_count_set = true;
+ }
+
+ return 0;
+}
+
+int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels) {
+ struct ethtool_channels ecmd = {
+ .cmd = ETHTOOL_GCHANNELS
+ };
+ struct ifreq ifr = {
+ .ifr_data = (void*) &ecmd
+ };
+
+ bool need_update = false;
+ int r;
+
+ if (*fd < 0) {
+ r = ethtool_connect(fd);
+ if (r < 0)
+ return log_warning_errno(r, "link_config: could not connect to ethtool: %m");
+ }
+
+ strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
+
+ r = ioctl(*fd, SIOCETHTOOL, &ifr);
+ if (r < 0)
+ return -errno;
+
+ if (channels->rx_count_set && ecmd.rx_count != channels->rx_count) {
+ ecmd.rx_count = channels->rx_count;
+ need_update = true;
+ }
+
+ if (channels->tx_count_set && ecmd.tx_count != channels->tx_count) {
+ ecmd.tx_count = channels->tx_count;
+ need_update = true;
+ }
+
+ if (channels->other_count_set && ecmd.other_count != channels->other_count) {
+ ecmd.other_count = channels->other_count;
+ need_update = true;
+ }
+
+ if (channels->combined_count_set && ecmd.combined_count != channels->combined_count) {
+ ecmd.combined_count = channels->combined_count;
+ need_update = true;
+ }
+
+ if (need_update) {
+ ecmd.cmd = ETHTOOL_SCHANNELS;
+
+ r = ioctl(*fd, SIOCETHTOOL, &ifr);
+ if (r < 0)
+ return -errno;
+ }
+
+ return 0;
+}
} link_modes;
};
+typedef struct netdev_channels {
+ uint32_t rx_count;
+ uint32_t tx_count;
+ uint32_t other_count;
+ uint32_t combined_count;
+
+ bool rx_count_set;
+ bool tx_count_set;
+ bool other_count_set;
+ bool combined_count_set;
+} netdev_channels;
+
int ethtool_connect(int *ret);
int ethtool_get_driver(int *fd, const char *ifname, char **ret);
int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol);
int ethtool_set_features(int *fd, const char *ifname, NetDevFeature *features);
int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *link);
+int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels);
const char *duplex_to_string(Duplex d) _const_;
Duplex duplex_from_string(const char *d) _pure_;
int config_parse_duplex(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_wol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_channel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
#endif
#include <stddef.h>
#include "conf-parser.h"
-#include "network-internal.h"
-#include "link-config.h"
#include "ethtool-util.h"
+#include "link-config.h"
+#include "network-internal.h"
%}
struct ConfigPerfItem;
%null_strings
%struct-type
%includes
%%
-Match.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, match_mac)
+Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac)
Match.OriginalName, config_parse_ifnames, 0, offsetof(link_config, match_name)
Match.Path, config_parse_strv, 0, offsetof(link_config, match_path)
Match.Driver, config_parse_strv, 0, offsetof(link_config, match_driver)
Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0
Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GRO])
Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_LRO])
+Link.RxChannels, config_parse_channel, 0, 0
+Link.TxChannels, config_parse_channel, 0, 0
+Link.OtherChannels, config_parse_channel, 0, 0
+Link.CombinedChannels, config_parse_channel, 0, 0
free(link->filename);
- free(link->match_mac);
+ set_free_free(link->match_mac);
strv_free(link->match_path);
strv_free(link->match_driver);
strv_free(link->match_type);
if (r < 0)
log_warning_errno(r, "Could not set offload features of %s: %m", old_name);
+ if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) {
+ r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels);
+ if (r < 0)
+ log_warning_errno(r, "Could not set channels of %s: %m", old_name);
+ }
+
ifindex = udev_device_get_ifindex(device);
if (ifindex <= 0) {
log_warning("Could not find ifindex");
#include "condition.h"
#include "ethtool-util.h"
#include "list.h"
+#include "set.h"
typedef struct link_config_ctx link_config_ctx;
typedef struct link_config link_config;
struct link_config {
char *filename;
- struct ether_addr *match_mac;
+ Set *match_mac;
char **match_path;
char **match_driver;
char **match_type;
WakeOnLan wol;
NetDevPort port;
NetDevFeature features[_NET_DEV_FEAT_MAX];
+ netdev_channels channels;
LIST_FIELDS(link_config, links);
};
if (trie) {
if (trie->root)
trie_node_cleanup(trie->root);
- strbuf_cleanup(trie->strings);
+ if (trie->strings)
+ strbuf_cleanup(trie->strings);
free(trie);
}
return rc;
'sysusers.d_' + file,
input : file + '.m4',
output: file,
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : enable_sysusers,
install_dir : sysusersdir)
# (at your option) any later version.
g systemd-journal - -
-m4_ifdef(`ENABLE_NETWORKD',
-u systemd-network - "systemd Network Management"
-)m4_dnl
-m4_ifdef(`ENABLE_RESOLVE',
-u systemd-resolve - "systemd Resolver"
-)m4_dnl
m4_ifdef(`ENABLE_COREDUMP',
u systemd-coredump - "systemd Core Dumper"
)m4_dnl
subprocess.check_call(['systemctl', 'restart', 'systemd-networkd'])
self.assertEqual(self.read_attr('port2', 'brport/priority'), '0')
+ def test_bridge_port_property(self):
+ """Test the "[Bridge]" section keys"""
+ self.assertEqual(self.read_attr('port2', 'brport/priority'), '32')
+ self.write_network_dropin('port2.network', 'property', '''\
+[Bridge]
+UnicastFlood=true
+HairPin=true
+UseBPDU=true
+FastLeave=true
+AllowPortToBeRoot=true
+Cost=555
+Priority=23
+''')
+ subprocess.check_call(['systemctl', 'restart', 'systemd-networkd'])
+
+ self.assertEqual(self.read_attr('port2', 'brport/priority'), '23')
+ self.assertEqual(self.read_attr('port2', 'brport/hairpin_mode'), '1')
+ self.assertEqual(self.read_attr('port2', 'brport/path_cost'), '555')
+ self.assertEqual(self.read_attr('port2', 'brport/multicast_fast_leave'), '1')
+ self.assertEqual(self.read_attr('port2', 'brport/unicast_flood'), '1')
+ self.assertEqual(self.read_attr('port2', 'brport/bpdu_guard'), '1')
+ self.assertEqual(self.read_attr('port2', 'brport/root_block'), '1')
+
class ClientTestBase(NetworkdTestingUtilities):
"""Provide common methods for testing networkd against servers."""
[Unit]
-Description=Test DynamicUser= migrate StateDirectory= (preparation)
+Description=Test DynamicUser= migrate StateDirectory=
[Service]
ExecStart=test -w /var/lib/test-dynamicuser-migrate
Description=Test for EnvironmentFile
[Service]
-ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline"'
+ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes'
Type=oneshot
EnvironmentFile=/tmp/test-exec_environmentfile.conf
Description=Test for PassEnvironment with variables absent from the execution environment
[Service]
-ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset"'
+ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset" && test "$${VAR5-unset}" = "unset"'
Type=oneshot
-PassEnvironment=VAR1 VAR2 VAR3 VAR4
+PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
Description=Test for PassEnvironment and erasing the variable list
[Service]
-ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset"'
+ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset" && test "$${VAR5-unset}" = "unset"'
Type=oneshot
-PassEnvironment=VAR1 VAR2 VAR3 VAR4
+PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
PassEnvironment=
Description=Test for PassEnvironment with a variable name repeated
[Service]
-ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline"'
+ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes'
Type=oneshot
PassEnvironment=VAR1 VAR2
PassEnvironment=VAR1 VAR3
PassEnvironment=VAR1 VAR4
+PassEnvironment=VAR1 VAR5
Description=Test for PassEnvironment
[Service]
-ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline"'
+ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes'
Type=oneshot
-PassEnvironment=VAR1 VAR2 VAR3 VAR4
+PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
'tmpfiles.d_' + pair[0],
input : pair[0] + '.m4',
output: pair[0],
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : true,
install_dir : tmpfilesdir)
d /run/systemd/machines 0755 root root -
d /run/systemd/shutdown 0755 root root -
m4_ifdef(`ENABLE_NETWORKD',
-d /run/systemd/netif 0755 systemd-network systemd-network -
-d /run/systemd/netif/links 0755 systemd-network systemd-network -
-d /run/systemd/netif/leases 0755 systemd-network systemd-network -
+d /run/systemd/netif 0755 root root -
+d /run/systemd/netif/links 0755 root root -
+d /run/systemd/netif/leases 0755 root root -
)m4_dnl
d /run/log 0755 root root -
d /var/lib/systemd 0755 root root -
d /var/lib/systemd/coredump 0755 root root 3d
+
+d /var/lib/private 0700 root root -
+d /var/log/private 0700 root root -
+d /var/cache/private 0700 root root -
DIR="$2"
fi
- find $DIR -type f \( -name '*.c' -o -name '*.xml' \) -exec $0 diff \{\} \;
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 diff \{\} \;
;;
recpatch)
DIR="$2"
fi
- find $DIR -type f \( -name '*.c' -o -name '*.xml' \) -exec $0 patch \{\} \;
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 patch \{\} \;
;;
diff)
--- /dev/null
+#!/bin/sh
+# SPDX-License-Identifier: LGPL-2.1+
+
+case "$1" in
+
+ recdiff)
+ if [ "$2" = "" ] ; then
+ DIR="$PWD/.."
+ else
+ DIR="$2"
+ fi
+
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 diff \{\} \;
+ ;;
+
+ recpatch)
+ if [ "$2" = "" ] ; then
+ DIR="$PWD/.."
+ else
+ DIR="$2"
+ fi
+
+ find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 patch \{\} \;
+ ;;
+
+ diff)
+ T=`mktemp`
+ sed 's/\t/ /g' < "$2" > "$T"
+ diff -u "$2" "$T"
+ rm -f "$T"
+ ;;
+
+ patch)
+ sed -i 's/\t/ /g' "$2"
+ ;;
+
+ *)
+ echo "Expected recdiff|recpatch|diff|patch as verb." >&2
+ ;;
+esac
--- /dev/null
+#!/bin/sh
+set -eu
+
+CONFIG=$1
+TARGET=$2
+
+if [ $# -ne 2 ]; then
+ echo 'Invalid number of arguments.'
+ exit 1
+fi
+
+if [ ! -f $CONFIG ]; then
+ echo "$CONFIG not found."
+ exit 2
+fi
+
+if [ ! -f $TARGET ]; then
+ echo "$TARGET not found."
+ exit 3
+fi
+
+DEFINES=$(awk '$1 == "#define" && $3 == "1" { printf "-D%s ", $2 }' $CONFIG)
+
+m4 -P $DEFINES $TARGET
git clone --depth 1 https://github.com/CZ-NIC/dns-fuzzing $df
zip -jqr $OUT/fuzz-dns-packet_seed_corpus.zip $df/packet
-mkdir -p $OUT/src/shared
-mv $build/src/shared/libsystemd-shared-*.so $OUT/src/shared
+# install the private shared library without executable permissions
+install -Dt $OUT/src/shared/ -m 0644 $build/src/shared/libsystemd-shared-*.so
find $build -maxdepth 1 -type f -executable -name "fuzz-*" -exec mv {} $OUT \;
cp src/fuzz/*.options $OUT
dnf-plugins-core
meson
ninja-build
+ccache
file,
input : input,
output: file,
- command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+ command : [meson_apply_m4, config_h, '@INPUT@'],
capture : true,
install : install,
install_dir : systemunitdir)
ConditionCapability=CAP_NET_ADMIN
DefaultDependencies=no
# systemd-udevd.service can be dropped once tuntap is moved to netlink
-After=systemd-udevd.service network-pre.target systemd-sysusers.service systemd-sysctl.service
+After=systemd-udevd.service network-pre.target systemd-sysctl.service
Before=network.target multi-user.target shutdown.target
Conflicts=shutdown.target
Wants=network.target
ExecStart=!!@rootlibexecdir@/systemd-networkd
WatchdogSec=3min
User=systemd-network
+DynamicUser=yes
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW
-ProtectSystem=strict
ProtectHome=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
+RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 AF_PACKET
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
SystemCallArchitectures=native
Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
DefaultDependencies=no
-After=systemd-sysusers.service systemd-networkd.service
+After=systemd-networkd.service
Before=network.target nss-lookup.target shutdown.target
Conflicts=shutdown.target
Wants=nss-lookup.target
ExecStart=!!@rootlibexecdir@/systemd-resolved
WatchdogSec=3min
User=systemd-resolve
+DynamicUser=yes
CapabilityBoundingSet=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE
-PrivateTmp=yes
PrivateDevices=yes
-ProtectSystem=strict
ProtectHome=yes
ProtectControlGroups=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
+RestrictNamespaces=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
SystemCallArchitectures=native
ConditionCapability=CAP_SYS_TIME
ConditionVirtualization=!container
DefaultDependencies=no
-After=systemd-remount-fs.service systemd-sysusers.service
+After=systemd-remount-fs.service
Before=time-sync.target sysinit.target shutdown.target
Conflicts=shutdown.target
Wants=time-sync.target