diff options
107 files changed, 890 insertions, 447 deletions
diff --git a/Makefile-man.am b/Makefile-man.am index a900b8d25a..013e0d7967 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -2272,19 +2272,25 @@ endif if HAVE_MICROHTTPD MANPAGES += \ man/journal-remote.conf.5 \ + man/journal-upload.conf.5 \ man/systemd-journal-gatewayd.service.8 \ man/systemd-journal-remote.8 \ man/systemd-journal-upload.8 MANPAGES_ALIAS += \ man/journal-remote.conf.d.5 \ + man/journal-upload.conf.d.5 \ man/systemd-journal-gatewayd.8 \ man/systemd-journal-gatewayd.socket.8 man/journal-remote.conf.d.5: man/journal-remote.conf.5 +man/journal-upload.conf.d.5: man/journal-upload.conf.5 man/systemd-journal-gatewayd.8: man/systemd-journal-gatewayd.service.8 man/systemd-journal-gatewayd.socket.8: man/systemd-journal-gatewayd.service.8 man/journal-remote.conf.d.html: man/journal-remote.conf.html $(html-alias) +man/journal-upload.conf.d.html: man/journal-upload.conf.html + $(html-alias) + man/systemd-journal-gatewayd.html: man/systemd-journal-gatewayd.service.html $(html-alias) @@ -2607,6 +2613,7 @@ EXTRA_DIST += \ man/hostnamectl.xml \ man/hwdb.xml \ man/journal-remote.conf.xml \ + man/journal-upload.conf.xml \ man/journalctl.xml \ man/journald.conf.xml \ man/kernel-command-line.xml \ diff --git a/coccinelle/free_and_replace.cocci b/coccinelle/free_and_replace.cocci new file mode 100644 index 0000000000..9dcdbf4d42 --- /dev/null +++ b/coccinelle/free_and_replace.cocci @@ -0,0 +1,15 @@ +@@ +expression p, q; +@@ +- free(p); +- p = q; +- q = NULL; +- return 0; ++ return free_and_replace(p, q); +@@ +expression p, q; +@@ +- free(p); +- p = q; +- q = NULL; ++ free_and_replace(p, q); diff --git a/coccinelle/mfree_return.cocci b/coccinelle/mfree_return.cocci new file mode 100644 index 0000000000..8119fe07f2 --- /dev/null +++ b/coccinelle/mfree_return.cocci @@ -0,0 +1,6 @@ +@@ +expression p; +@@ +- free(p); +- return NULL; ++ return mfree(p); diff --git a/hwdb/70-pointingstick.hwdb b/hwdb/70-pointingstick.hwdb index 2b30896dff..e18ef28290 100644 --- a/hwdb/70-pointingstick.hwdb +++ b/hwdb/70-pointingstick.hwdb @@ -87,6 +87,10 @@ evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*:pvr* evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:pvr* POINTINGSTICK_CONST_ACCEL=1.5 +# Latitude E7470 +evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*:pvr* + POINTINGSTICK_CONST_ACCEL=0.6 + ######################################### # Lenovo ######################################### diff --git a/man/journal-remote.conf.xml b/man/journal-remote.conf.xml index 2d345963d9..f7ac8c46e0 100644 --- a/man/journal-remote.conf.xml +++ b/man/journal-remote.conf.xml @@ -45,22 +45,21 @@ <refnamediv> <refname>journal-remote.conf</refname> <refname>journal-remote.conf.d</refname> - <refpurpose>Journal remote service configuration files</refpurpose> + <refpurpose>Configuration files for the service accepting remote journal uploads</refpurpose> </refnamediv> <refsynopsisdiv> <para><filename>/etc/systemd/journal-remote.conf</filename></para> - <para><filename>/etc/systemd/journald.conf.d/*.conf</filename></para> - <para><filename>/run/systemd/journald.conf.d/*.conf</filename></para> - <para><filename>/usr/lib/systemd/journald.conf.d/*.conf</filename></para> + <para><filename>/etc/systemd/journal-remote.conf.d/*.conf</filename></para> + <para><filename>/run/systemd/journal-remote.conf.d/*.conf</filename></para> + <para><filename>/usr/lib/systemd/journal-remote.conf.d/*.conf</filename></para> </refsynopsisdiv> <refsect1> <title>Description</title> - <para>These files configure various parameters of the systemd-remote-journal - application, - <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para> + <para>These files configure various parameters of + <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para> </refsect1> <xi:include href="standard-conf.xml" xpointer="main-conf" /> diff --git a/man/journal-upload.conf.xml b/man/journal-upload.conf.xml new file mode 100644 index 0000000000..e3be62dfd1 --- /dev/null +++ b/man/journal-upload.conf.xml @@ -0,0 +1,113 @@ +<?xml version='1.0'?> <!--*-nxml-*--> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> + +<!-- + This file is part of systemd. + + Copyright 2016 Zbigniew Jędrzejewski-Szmek + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +--> + +<refentry id="journal-upload.conf" conditional='HAVE_MICROHTTPD' + xmlns:xi="http://www.w3.org/2001/XInclude"> + <refentryinfo> + <title>journal-upload.conf</title> + <productname>systemd</productname> + + <authorgroup> + <author> + <contrib>Monkey with a keyboard</contrib> + <firstname>Zbigniew</firstname> + <surname>Jędrzejewski-Szmek</surname> + <email>zbyszek@in.waw.pl</email> + </author> + </authorgroup> + </refentryinfo> + + <refmeta> + <refentrytitle>journal-upload.conf</refentrytitle> + <manvolnum>5</manvolnum> + </refmeta> + + <refnamediv> + <refname>journal-upload.conf</refname> + <refname>journal-upload.conf.d</refname> + <refpurpose>Configuration files for the journal upload service</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <para><filename>/etc/systemd/journal-upload.conf</filename></para> + <para><filename>/etc/systemd/journal-upload.conf.d/*.conf</filename></para> + <para><filename>/run/systemd/journal-upload.conf.d/*.conf</filename></para> + <para><filename>/usr/lib/systemd/journal-upload.conf.d/*.conf</filename></para> + </refsynopsisdiv> + + <refsect1> + <title>Description</title> + + <para>These files configure various parameters of + <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para> + </refsect1> + + <xi:include href="standard-conf.xml" xpointer="main-conf" /> + + <refsect1> + <title>Options</title> + + <para>All options are configured in the <literal>[Upload]</literal> section:</para> + + <variablelist> + <varlistentry> + <term><varname>URL=</varname></term> + + <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> + </varlistentry> + + <varlistentry> + <term><varname>ServerKeyFile=</varname></term> + + <listitem><para>SSL key in PEM format.</para></listitem> + </varlistentry> + + <varlistentry> + <term><varname>ServerCertificateFile=</varname></term> + + <listitem><para>SSL CA certificate in PEM format.</para></listitem> + </varlistentry> + + <varlistentry> + <term><varname>TrustedCertificateFile=</varname></term> + + <listitem><para>SSL CA certificate.</para></listitem> + </varlistentry> + + </variablelist> + + </refsect1> + + <refsect1> + <title>See Also</title> + <para> + <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>, + <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, + <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> + </para> + </refsect1> + +</refentry> diff --git a/man/sd-journal.xml b/man/sd-journal.xml index 936a83acf7..0f4b3e8eea 100644 --- a/man/sd-journal.xml +++ b/man/sd-journal.xml @@ -98,6 +98,21 @@ tool.</para> </refsect1> + <refsect1> + <title>Thread safety</title> + + <para>Functions that operate on the <structname>sd_journal</structname> object are thread + agnostic — given <structname>sd_journal</structname> pointer may only be used from one thread at + a time, but multiple threads may use multiple such objects safely. Other functions — + those that are used to send entries to the journal, like + <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry> + and similar, or those that are used to retrieve global information like + <citerefentry><refentrytitle>sd_journal_stream_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry> + and + <citerefentry><refentrytitle>sd_journal_get_catalog_for_message_id</refentrytitle><manvolnum>3</manvolnum></citerefentry> + — are thread-safe and may be called from multiple threads in parallel.</para> + </refsect1> + <xi:include href="libsystemd-pkgconfig.xml" /> <refsect1> diff --git a/man/sd_bus_creds_get_pid.xml b/man/sd_bus_creds_get_pid.xml index 4c05835568..9e68d5e8c7 100644 --- a/man/sd_bus_creds_get_pid.xml +++ b/man/sd_bus_creds_get_pid.xml @@ -366,7 +366,7 @@ -ENXIO is returned.</para> <para><function>sd_bus_creds_get_cgroup()</function> will retrieve - the cgroup path. See <ulink + the control group path. See <ulink url="https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>. </para> diff --git a/man/sd_journal_add_match.xml b/man/sd_journal_add_match.xml index 98415d53fd..7c64329aed 100644 --- a/man/sd_journal_add_match.xml +++ b/man/sd_journal_add_match.xml @@ -168,6 +168,9 @@ <refsect1> <title>Notes</title> + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + <para>The <function>sd_journal_add_match()</function>, <function>sd_journal_add_disjunction()</function>, <function>sd_journal_add_conjunction()</function> and diff --git a/man/sd_journal_enumerate_fields.xml b/man/sd_journal_enumerate_fields.xml index fa5884106b..bc2c21ed4b 100644 --- a/man/sd_journal_enumerate_fields.xml +++ b/man/sd_journal_enumerate_fields.xml @@ -110,6 +110,9 @@ <refsect1> <title>Notes</title> + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + <para>The <function>sd_journal_enumerate_fields()</function> and <function>sd_journal_restart_fields()</function> interfaces are available as a shared library, which can be compiled and linked to with the <constant>libsystemd</constant> <citerefentry diff --git a/man/sd_journal_get_catalog.xml b/man/sd_journal_get_catalog.xml index c19eb11b20..35ec46f63e 100644 --- a/man/sd_journal_get_catalog.xml +++ b/man/sd_journal_get_catalog.xml @@ -112,6 +112,10 @@ <refsect1> <title>Notes</title> + <para>Function <function>sd_journal_get_catalog()</function> is thread-agnostic and only a + single thread may operate on a given <structname>sd_journal</structname> object. Function + <function>sd_journal_get_catalog_for_message_id() is thread-safe.</function></para> + <para>The <function>sd_journal_get_catalog()</function> and <function>sd_journal_get_catalog_for_message_id()</function> interfaces are available as a shared library, which can be diff --git a/man/sd_journal_get_cursor.xml b/man/sd_journal_get_cursor.xml index a400d8b1b5..b7aa05f8b2 100644 --- a/man/sd_journal_get_cursor.xml +++ b/man/sd_journal_get_cursor.xml @@ -122,6 +122,9 @@ <refsect1> <title>Notes</title> + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + <para>The <function>sd_journal_get_cursor()</function> and <function>sd_journal_test_cursor()</function> interfaces are available as a shared library, which can be compiled and linked to diff --git a/man/sd_journal_get_cutoff_realtime_usec.xml b/man/sd_journal_get_cutoff_realtime_usec.xml index 23e7cc65e8..0950e11b44 100644 --- a/man/sd_journal_get_cutoff_realtime_usec.xml +++ b/man/sd_journal_get_cutoff_realtime_usec.xml @@ -120,6 +120,9 @@ <refsect1> <title>Notes</title> + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + <para>The <function>sd_journal_get_cutoff_realtime_usec()</function> and <function>sd_journal_get_cutoff_monotonic_usec()</function> diff --git a/man/sd_journal_get_usage.xml b/man/sd_journal_get_usage.xml index 72c804d834..06b0ff534d 100644 --- a/man/sd_journal_get_usage.xml +++ b/man/sd_journal_get_usage.xml @@ -80,6 +80,9 @@ <refsect1> <title>Notes</title> + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + <para>The <function>sd_journal_get_usage()</function> interface is available as a shared library, which can be compiled and linked to with the diff --git a/man/sd_journal_has_runtime_files.xml b/man/sd_journal_has_runtime_files.xml index 237e649206..3f6d56ca77 100644 --- a/man/sd_journal_has_runtime_files.xml +++ b/man/sd_journal_has_runtime_files.xml @@ -86,6 +86,18 @@ </refsect1> <refsect1> + <title>Notes</title> + + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + + <para>Functions listed here are available as a shared library, which can be compiled and linked + to with the <constant>libsystemd</constant> <citerefentry + project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> + file.</para> + </refsect1> + + <refsect1> <title>See Also</title> <para> <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry> diff --git a/man/sd_journal_next.xml b/man/sd_journal_next.xml index 115fe26661..7c385de260 100644 --- a/man/sd_journal_next.xml +++ b/man/sd_journal_next.xml @@ -146,6 +146,9 @@ <refsect1> <title>Notes</title> + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + <para>The <function>sd_journal_next()</function>, <function>sd_journal_previous()</function>, <function>sd_journal_next_skip()</function> and diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml index 74e67023b5..25b3048f2e 100644 --- a/man/sd_journal_open.xml +++ b/man/sd_journal_open.xml @@ -208,6 +208,9 @@ <refsect1> <title>Notes</title> + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + <para>The <function>sd_journal_open()</function>, <function>sd_journal_open_directory()</function> and <function>sd_journal_close()</function> interfaces are available diff --git a/man/sd_journal_print.xml b/man/sd_journal_print.xml index 76542527fc..2d8dd635aa 100644 --- a/man/sd_journal_print.xml +++ b/man/sd_journal_print.xml @@ -201,9 +201,10 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid( </refsect1> <refsect1> - <title>Async signal safety</title> - <para><function>sd_journal_sendv()</function> is "async signal - safe" in the meaning of + <title>Thread safety</title> + <para>All functions listed here are thread-safe and may be called in parallel from multiple threads.</para> + + <para><function>sd_journal_sendv()</function> is "async signal safe" in the meaning of <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>. </para> diff --git a/man/sd_journal_query_unique.xml b/man/sd_journal_query_unique.xml index dbff55c105..d7a41a039c 100644 --- a/man/sd_journal_query_unique.xml +++ b/man/sd_journal_query_unique.xml @@ -150,6 +150,9 @@ <refsect1> <title>Notes</title> + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + <para>The <function>sd_journal_query_unique()</function>, <function>sd_journal_enumerate_unique()</function> and <function>sd_journal_restart_unique()</function> interfaces are diff --git a/man/sd_journal_seek_head.xml b/man/sd_journal_seek_head.xml index d74c2d5bbc..985073496c 100644 --- a/man/sd_journal_seek_head.xml +++ b/man/sd_journal_seek_head.xml @@ -144,6 +144,9 @@ <refsect1> <title>Notes</title> + <para>All functions listed here are thread-agnostic and only a single thread may operate + on a given <structname>sd_journal</structname> object.</para> + <para>The <function>sd_journal_seek_head()</function>, <function>sd_journal_seek_tail()</function>, <function>sd_journal_seek_monotonic_usec()</function>, diff --git a/man/sd_journal_stream_fd.xml b/man/sd_journal_stream_fd.xml index 2ea7731b48..226298ae1b 100644 --- a/man/sd_journal_stream_fd.xml +++ b/man/sd_journal_stream_fd.xml @@ -104,6 +104,10 @@ <refsect1> <title>Notes</title> + <para>Function <function>sd_journal_stream_fd()</function> is thread-safe and may be be called + from multiple threads. All calls will return the same file descriptor, although temporarily + multiple file descriptors may be open.</para> + <para>The <function>sd_journal_stream_fd()</function> interface is available as a shared library, which can be compiled and linked to with the diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 71dc86ec2f..7453aa7bee 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -74,6 +74,10 @@ execution specific configuration options are configured in the [Service], [Socket], [Mount], or [Swap] sections, depending on the unit type.</para> + + <para>In addition, options which control resources through Linux Control Groups (cgroups) are listed in + <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>. + Those options complement options listed here.</para> </refsect1> <refsect1> @@ -405,8 +409,9 @@ <option>null</option>, <option>tty</option>, <option>tty-force</option>, - <option>tty-fail</option> or - <option>socket</option>.</para> + <option>tty-fail</option>, + <option>socket</option> or + <option>fd</option>.</para> <para>If <option>null</option> is selected, standard input will be connected to <filename>/dev/null</filename>, i.e. all @@ -444,6 +449,20 @@ <citerefentry project='freebsd'><refentrytitle>inetd</refentrytitle><manvolnum>8</manvolnum></citerefentry> daemon.</para> + <para>The <option>fd</option> option connects + the input stream to a single file descriptor provided by a socket unit. + A custom named file descriptor can be specified as part of this option, + after a <literal>:</literal> (e.g. <literal>fd:<replaceable>foobar</replaceable></literal>). + If no name is specified, <literal>stdin</literal> is assumed + (i.e. <literal>fd</literal> is equivalent to <literal>fd:stdin</literal>). + At least one socket unit defining such name must be explicitly provided via the + <varname>Sockets=</varname> option, and file descriptor name may differ + from the name of its containing socket unit. + If multiple matches are found, the first one will be used. + See <varname>FileDescriptorName=</varname> in + <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> + for more details about named descriptors and ordering.</para> + <para>This setting defaults to <option>null</option>.</para></listitem> </varlistentry> @@ -460,8 +479,9 @@ <option>kmsg</option>, <option>journal+console</option>, <option>syslog+console</option>, - <option>kmsg+console</option> or - <option>socket</option>.</para> + <option>kmsg+console</option>, + <option>socket</option> or + <option>fd</option>.</para> <para><option>inherit</option> duplicates the file descriptor of standard input for standard output.</para> @@ -510,6 +530,20 @@ similar to the same option of <varname>StandardInput=</varname>.</para> + <para>The <option>fd</option> option connects + the output stream to a single file descriptor provided by a socket unit. + A custom named file descriptor can be specified as part of this option, + after a <literal>:</literal> (e.g. <literal>fd:<replaceable>foobar</replaceable></literal>). + If no name is specified, <literal>stdout</literal> is assumed + (i.e. <literal>fd</literal> is equivalent to <literal>fd:stdout</literal>). + At least one socket unit defining such name must be explicitly provided via the + <varname>Sockets=</varname> option, and file descriptor name may differ + from the name of its containing socket unit. + If multiple matches are found, the first one will be used. + See <varname>FileDescriptorName=</varname> in + <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> + for more details about named descriptors and ordering.</para> + <para>If the standard output (or error output, see below) of a unit is connected to the journal, syslog or the kernel log buffer, the unit will implicitly gain a dependency of type <varname>After=</varname> on <filename>systemd-journald.socket</filename> (also see the automatic dependencies section above).</para> @@ -527,9 +561,13 @@ <listitem><para>Controls where file descriptor 2 (STDERR) of the executed processes is connected to. The available options are identical to those of <varname>StandardOutput=</varname>, - with one exception: if set to <option>inherit</option> the + with some exceptions: if set to <option>inherit</option> the file descriptor used for standard output is duplicated for - standard error. This setting defaults to the value set with + standard error, while <option>fd</option> operates on the error + stream and will look by default for a descriptor named + <literal>stderr</literal>.</para> + + <para>This setting defaults to the value set with <option>DefaultStandardError=</option> in <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>, which defaults to <option>inherit</option>. Note that setting diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index 10aefbe0c5..02878b28a0 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -60,12 +60,10 @@ <refsect1> <title>Description</title> - <para>Unit configuration files for services, slices, scopes, - sockets, mount points, and swap devices share a subset of - configuration options for resource control of spawned - processes. Internally, this relies on the Control Groups - kernel concept for organizing processes in a hierarchical tree of - named groups for the purpose of resource management.</para> + <para>Unit configuration files for services, slices, scopes, sockets, mount points, and swap devices share a subset + of configuration options for resource control of spawned processes. Internally, this relies on the Linux Control + Groups (cgroups) kernel concept for organizing processes in a hierarchical tree of named groups for the purpose of + resource management.</para> <para>This man page lists the configuration options shared by those six unit types. See @@ -83,6 +81,11 @@ [Slice], [Scope], [Service], [Socket], [Mount], or [Swap] sections, depending on the unit type.</para> + <para>In addition, options which control resources available to programs + <emphasis>executed</emphasis> by systemd are listed in + <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>. + Those options complement options listed here.</para> + <para>See the <ulink url="http://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/">New Control Group Interfaces</ulink> for an introduction on how to make @@ -111,7 +114,7 @@ <term><option>CPU</option></term> <listitem> <para>Due to the lack of consensus in the kernel community, the CPU controller support on the unified - cgroup hierarchy requires out-of-tree kernel patches. See <ulink + control group hierarchy requires out-of-tree kernel patches. See <ulink url="https://git.kernel.org/cgit/linux/kernel/git/tj/cgroup.git/tree/Documentation/cgroup-v2-cpu.txt?h=cgroup-v2-cpu">cgroup-v2-cpu.txt</ulink>.</para> <para><varname>CPUWeight=</varname> and <varname>StartupCPUWeight=</varname> replace @@ -751,6 +754,7 @@ <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.swap</refentrytitle><manvolnum>5</manvolnum></citerefentry>, + <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>, The documentation for control groups and specific controllers in the Linux kernel: diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 79bdb2cd38..04efee2891 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -203,9 +203,7 @@ <filename>/run/systemd/system</filename> directories. Drop-in files in <filename>/etc</filename> take precedence over those in <filename>/run</filename> which in turn take precedence over those in <filename>/usr/lib</filename>. Drop-in files under any of these directories take precedence - over unit files wherever located. (Of course, since <filename>/run</filename> is temporary and - <filename>/usr/lib</filename> is for vendors, it is unlikely drop-ins should be used in either - of those places.)</para> + over unit files wherever located.</para> <!-- Note that we do not document .include here, as we consider it mostly obsolete, and want people to use .d/ drop-ins instead. --> @@ -1254,7 +1252,7 @@ <row> <entry><literal>%r</literal></entry> <entry>Control group path of the slice the unit is placed in</entry> - <entry>This usually maps to the parent cgroup path of <literal>%c</literal>.</entry> + <entry>This usually maps to the parent control group path of <literal>%c</literal>.</entry> </row> <row> <entry><literal>%R</literal></entry> diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in index b525286932..03a1c930b0 100644 --- a/shell-completion/zsh/_systemctl.in +++ b/shell-completion/zsh/_systemctl.in @@ -123,15 +123,11 @@ _systemctl_really_all_units() } _filter_units_by_property() { - local property=$1 value=$2 ; shift ; shift - local -a units ; units=($*) - local props - for props in ${(ps:\n\n:)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property="Id,$property" -- ${units} 2>/dev/null")"}; do - props=(${(f)props}) - if [[ "${props[2]}" = "$property=$value" ]]; then - echo -E - " ${props[1]#Id=}" - fi - done + local property=$1 value=$2; shift 2 + local -a units; units=("${(q-)@}") + local -A props + props=(${(f)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property=\"Id,$property\" -- ${units} 2>/dev/null")"}) + echo -E - "${(@g:o:)${(k@)props[(Re)$property=$value]}#Id=}" } _systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files)"}##*@.[^[:space:]]##}%%@.*}\@ } diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h index ceeee519b7..a44dd473c1 100644 --- a/src/basic/alloc-util.h +++ b/src/basic/alloc-util.h @@ -43,6 +43,14 @@ static inline void *mfree(void *memory) { return NULL; } +#define free_and_replace(a, b) \ + ({ \ + free(a); \ + (a) = (b); \ + (b) = NULL; \ + 0; \ + }) + void* memdup(const void *p, size_t l) _alloc_(2); static inline void freep(void *p) { diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c index f4b12fc261..f6212e6151 100644 --- a/src/basic/bitmap.c +++ b/src/basic/bitmap.c @@ -58,10 +58,8 @@ Bitmap *bitmap_copy(Bitmap *b) { return NULL; ret->bitmaps = newdup(uint64_t, b->bitmaps, b->n_bitmaps); - if (!ret->bitmaps) { - free(ret); - return NULL; - } + if (!ret->bitmaps) + return mfree(ret); ret->n_bitmaps = ret->bitmaps_allocated = b->n_bitmaps; return ret; diff --git a/src/basic/env-util.c b/src/basic/env-util.c index 7f5fddb700..b74290d6fd 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -544,8 +544,7 @@ char *replace_env(const char *format, char **env) { return k; fail: - free(r); - return NULL; + return mfree(r); } char **replace_env_argv(char **argv, char **env) { diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 86d9ad7e36..48952a1c26 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -678,9 +678,7 @@ int chase_symlinks(const char *path, const char *_root, char **ret) { !path_startswith(parent, root)) return -EINVAL; - free(done); - done = parent; - parent = NULL; + free_and_replace(done, parent); fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH); if (fd_parent < 0) @@ -724,9 +722,7 @@ int chase_symlinks(const char *path, const char *_root, char **ret) { if (fd < 0) return -errno; - free(buffer); - buffer = destination; - destination = NULL; + free_and_replace(buffer, destination); todo = buffer; free(done); diff --git a/src/basic/path-util.c b/src/basic/path-util.c index a76963aa9f..0f5b20cf05 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -288,9 +288,7 @@ char **path_strv_resolve(char **l, const char *prefix) { } else { /* canonicalized path goes outside of * prefix, keep the original path instead */ - free(u); - u = orig; - orig = NULL; + free_and_replace(u, orig); } } else free(t); diff --git a/src/basic/prioq.c b/src/basic/prioq.c index d2ec516d29..4570b8e4ba 100644 --- a/src/basic/prioq.c +++ b/src/basic/prioq.c @@ -62,9 +62,7 @@ Prioq* prioq_free(Prioq *q) { return NULL; free(q->items); - free(q); - - return NULL; + return mfree(q); } int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func) { diff --git a/src/basic/replace-var.c b/src/basic/replace-var.c index 6a204b9ec3..0d21423a9c 100644 --- a/src/basic/replace-var.c +++ b/src/basic/replace-var.c @@ -107,6 +107,5 @@ char *replace_var(const char *text, char *(*lookup)(const char *variable, void*u return r; oom: - free(r); - return NULL; + return mfree(r); } diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c index 4bef87d3c2..00aaf9e621 100644 --- a/src/basic/strbuf.c +++ b/src/basic/strbuf.c @@ -62,8 +62,7 @@ struct strbuf *strbuf_new(void) { err: free(str->buf); free(str->root); - free(str); - return NULL; + return mfree(str); } static void strbuf_node_cleanup(struct strbuf_node *node) { diff --git a/src/basic/string-util.c b/src/basic/string-util.c index dc7de5dab8..6b06e643c9 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -610,8 +610,7 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin return r; oom: - free(r); - return NULL; + return mfree(r); } char *strip_tab_ansi(char **ibuf, size_t *_isz) { @@ -682,8 +681,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) { if (ferror(f)) { fclose(f); - free(obuf); - return NULL; + return mfree(obuf); } fclose(f); diff --git a/src/basic/strv.c b/src/basic/strv.c index 34e464d253..0eec868eed 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -87,8 +87,7 @@ void strv_clear(char **l) { char **strv_free(char **l) { strv_clear(l); - free(l); - return NULL; + return mfree(l); } char **strv_free_erase(char **l) { @@ -426,8 +425,7 @@ char *strv_join_quoted(char **l) { return buf; oom: - free(buf); - return NULL; + return mfree(buf); } int strv_push(char ***l, char *value) { @@ -869,8 +867,7 @@ char ***strv_free_free(char ***l) { for (i = l; *i; i++) strv_free(*i); - free(l); - return NULL; + return mfree(l); } char **strv_skip(char **l, size_t n) { diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index 169ab772ff..b862bfaf05 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -36,6 +36,10 @@ #define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m" #define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m" #define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m" +#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m" +#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m" +#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;33m" +#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m" #define ANSI_NORMAL "\x1B[0m" #define ANSI_ERASE_TO_END_OF_LINE "\x1B[K" @@ -83,37 +87,24 @@ bool on_tty(void); bool terminal_is_dumb(void); bool colors_enabled(void); -static inline const char *ansi_underline(void) { - return colors_enabled() ? ANSI_UNDERLINE : ""; -} - -static inline const char *ansi_highlight(void) { - return colors_enabled() ? ANSI_HIGHLIGHT : ""; -} - -static inline const char *ansi_highlight_underline(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_UNDERLINE : ""; -} - -static inline const char *ansi_highlight_red(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_RED : ""; -} - -static inline const char *ansi_highlight_green(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_GREEN : ""; -} - -static inline const char *ansi_highlight_yellow(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_YELLOW : ""; -} - -static inline const char *ansi_highlight_blue(void) { - return colors_enabled() ? ANSI_HIGHLIGHT_BLUE : ""; -} - -static inline const char *ansi_normal(void) { - return colors_enabled() ? ANSI_NORMAL : ""; -} +#define DEFINE_ANSI_FUNC(name, NAME) \ + static inline const char *ansi_##name(void) { \ + return colors_enabled() ? ANSI_##NAME : ""; \ + } \ + struct __useless_struct_to_allow_trailing_semicolon__ + +DEFINE_ANSI_FUNC(underline, UNDERLINE); +DEFINE_ANSI_FUNC(highlight, HIGHLIGHT); +DEFINE_ANSI_FUNC(highlight_underline, HIGHLIGHT_UNDERLINE); +DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED); +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_red_underline, HIGHLIGHT_RED_UNDERLINE); +DEFINE_ANSI_FUNC(highlight_green_underline, HIGHLIGHT_GREEN_UNDERLINE); +DEFINE_ANSI_FUNC(highlight_yellow_underline, HIGHLIGHT_YELLOW_UNDERLINE); +DEFINE_ANSI_FUNC(highlight_blue_underline, HIGHLIGHT_BLUE_UNDERLINE); +DEFINE_ANSI_FUNC(normal, NORMAL); int get_ctty_devnr(pid_t pid, dev_t *d); int get_ctty(pid_t, dev_t *_devnr, char **r); diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c index ee6d7eb864..dc11b0d9db 100644 --- a/src/boot/bootctl.c +++ b/src/boot/bootctl.c @@ -621,7 +621,8 @@ static const char *efi_subdirs[] = { "EFI/systemd", "EFI/BOOT", "loader", - "loader/entries" + "loader/entries", + NULL }; static int create_dirs(const char *esp_path) { @@ -917,7 +918,7 @@ static int remove_binaries(const char *esp_path) { if (q < 0 && r == 0) r = q; - for (i = ELEMENTSOF(efi_subdirs); i > 0; i--) { + for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) { q = rmdir_one(esp_path, efi_subdirs[i-1]); if (q < 0 && r == 0) r = q; diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index b8720d7d3d..1a7f770db1 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -627,6 +627,53 @@ static int property_get_syslog_facility( return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority)); } +static int property_get_input_fdname( + 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; + const char *name; + + assert(bus); + assert(c); + assert(property); + assert(reply); + + name = exec_context_fdname(c, STDIN_FILENO); + + return sd_bus_message_append(reply, "s", name); +} + +static int property_get_output_fdname( + 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; + const char *name = NULL; + + assert(bus); + assert(c); + assert(property); + assert(reply); + + if (c->std_output == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardOutputFileDescriptorName")) + name = exec_context_fdname(c, STDOUT_FILENO); + else if (c->std_error == EXEC_OUTPUT_NAMED_FD && streq(property, "StandardErrorFileDescriptorName")) + name = exec_context_fdname(c, STDERR_FILENO); + + return sd_bus_message_append(reply, "s", name); +} + const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST), @@ -677,8 +724,11 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_input_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_output_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1030,7 +1080,6 @@ int bus_exec_context_set_transient_property( return 1; - } else if (streq(name, "StandardOutput")) { const char *s; ExecOutput p; @@ -1072,6 +1121,41 @@ int bus_exec_context_set_transient_property( return 1; } else if (STR_IN_SET(name, + "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) { + const char *s; + + r = sd_bus_message_read(message, "s", &s); + if (r < 0) + return r; + + if (!fdname_is_valid(s)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name"); + + if (mode != UNIT_CHECK) { + if (streq(name, "StandardInputFileDescriptorName")) { + c->std_input = EXEC_INPUT_NAMED_FD; + r = free_and_strdup(&c->stdio_fdname[STDIN_FILENO], s); + if (r < 0) + return r; + unit_write_drop_in_private_format(u, mode, name, "StandardInput=fd:%s", s); + } else if (streq(name, "StandardOutputFileDescriptorName")) { + c->std_output = EXEC_OUTPUT_NAMED_FD; + r = free_and_strdup(&c->stdio_fdname[STDOUT_FILENO], s); + if (r < 0) + return r; + unit_write_drop_in_private_format(u, mode, name, "StandardOutput=fd:%s", s); + } else if (streq(name, "StandardErrorFileDescriptorName")) { + c->std_error = EXEC_OUTPUT_NAMED_FD; + r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], s); + if (r < 0) + return r; + unit_write_drop_in_private_format(u, mode, name, "StandardError=fd:%s", s); + } + } + + return 1; + + } else if (STR_IN_SET(name, "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index 1043da3eb7..e1846e1adb 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -42,9 +42,7 @@ static DynamicUser* dynamic_user_free(DynamicUser *d) { (void) hashmap_remove(d->manager->dynamic_users, d->name); safe_close_pair(d->storage_socket); - free(d); - - return NULL; + return mfree(d); } static int dynamic_user_add(Manager *m, const char *name, int storage_socket[2], DynamicUser **ret) { diff --git a/src/core/execute.c b/src/core/execute.c index 869522704a..1b7b4a928d 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -411,7 +411,8 @@ static int fixup_output(ExecOutput std_output, int socket_fd) { static int setup_input( const ExecContext *context, const ExecParameters *params, - int socket_fd) { + int socket_fd, + int named_iofds[3]) { ExecInput i; @@ -461,6 +462,10 @@ static int setup_input( case EXEC_INPUT_SOCKET: return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO; + case EXEC_INPUT_NAMED_FD: + (void) fd_nonblock(named_iofds[STDIN_FILENO], false); + return dup2(named_iofds[STDIN_FILENO], STDIN_FILENO) < 0 ? -errno : STDIN_FILENO; + default: assert_not_reached("Unknown input type"); } @@ -472,6 +477,7 @@ static int setup_output( const ExecParameters *params, int fileno, int socket_fd, + int named_iofds[3], const char *ident, uid_t uid, gid_t gid, @@ -523,7 +529,7 @@ static int setup_output( return fileno; /* Duplicate from stdout if possible */ - if (e == o || e == EXEC_OUTPUT_INHERIT) + if ((e == o && e != EXEC_OUTPUT_NAMED_FD) || e == EXEC_OUTPUT_INHERIT) return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno; o = e; @@ -585,6 +591,10 @@ static int setup_output( assert(socket_fd >= 0); return dup2(socket_fd, fileno) < 0 ? -errno : fileno; + case EXEC_OUTPUT_NAMED_FD: + (void) fd_nonblock(named_iofds[fileno], false); + return dup2(named_iofds[fileno], fileno) < 0 ? -errno : fileno; + default: assert_not_reached("Unknown error type"); } @@ -2157,6 +2167,7 @@ static int exec_child( DynamicCreds *dcreds, char **argv, int socket_fd, + int named_iofds[3], int *fds, unsigned n_fds, char **files_env, int user_lookup_fd, @@ -2298,19 +2309,19 @@ static int exec_child( if (socket_fd >= 0) (void) fd_nonblock(socket_fd, false); - r = setup_input(context, params, socket_fd); + r = setup_input(context, params, socket_fd, named_iofds); if (r < 0) { *exit_status = EXIT_STDIN; return r; } - r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); + r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); if (r < 0) { *exit_status = EXIT_STDOUT; return r; } - r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); + r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); if (r < 0) { *exit_status = EXIT_STDERR; return r; @@ -2829,6 +2840,7 @@ int exec_spawn(Unit *unit, int *fds = NULL; unsigned n_fds = 0; _cleanup_free_ char *line = NULL; int socket_fd, r; + int named_iofds[3] = { -1, -1, -1 }; char **argv; pid_t pid; @@ -2855,6 +2867,10 @@ int exec_spawn(Unit *unit, n_fds = params->n_fds; } + r = exec_context_named_iofds(unit, context, params, named_iofds); + if (r < 0) + return log_unit_error_errno(unit, r, "Failed to load a named file descriptor: %m"); + r = exec_context_load_environment(unit, context, &files_env); if (r < 0) return log_unit_error_errno(unit, r, "Failed to load environment files: %m"); @@ -2884,6 +2900,7 @@ int exec_spawn(Unit *unit, dcreds, argv, socket_fd, + named_iofds, fds, n_fds, files_env, unit->manager->user_lookup_fds[1], @@ -2946,6 +2963,9 @@ void exec_context_done(ExecContext *c) { for (l = 0; l < ELEMENTSOF(c->rlimit); l++) c->rlimit[l] = mfree(c->rlimit[l]); + for (l = 0; l < 3; l++) + c->stdio_fdname[l] = mfree(c->stdio_fdname[l]); + c->working_directory = mfree(c->working_directory); c->root_directory = mfree(c->root_directory); c->tty_path = mfree(c->tty_path); @@ -3044,6 +3064,56 @@ static void invalid_env(const char *p, void *userdata) { log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path); } +const char* exec_context_fdname(const ExecContext *c, int fd_index) { + assert(c); + + switch (fd_index) { + case STDIN_FILENO: + if (c->std_input != EXEC_INPUT_NAMED_FD) + return NULL; + return c->stdio_fdname[STDIN_FILENO] ?: "stdin"; + case STDOUT_FILENO: + if (c->std_output != EXEC_OUTPUT_NAMED_FD) + return NULL; + return c->stdio_fdname[STDOUT_FILENO] ?: "stdout"; + case STDERR_FILENO: + if (c->std_error != EXEC_OUTPUT_NAMED_FD) + return NULL; + return c->stdio_fdname[STDERR_FILENO] ?: "stderr"; + default: + return NULL; + } +} + +int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]) { + unsigned i, targets; + const char *stdio_fdname[3]; + + assert(c); + assert(p); + + targets = (c->std_input == EXEC_INPUT_NAMED_FD) + + (c->std_output == EXEC_OUTPUT_NAMED_FD) + + (c->std_error == EXEC_OUTPUT_NAMED_FD); + + for (i = 0; i < 3; i++) + stdio_fdname[i] = exec_context_fdname(c, i); + + for (i = 0; i < p->n_fds && targets > 0; i++) + if (named_iofds[STDIN_FILENO] < 0 && c->std_input == EXEC_INPUT_NAMED_FD && stdio_fdname[STDIN_FILENO] && streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) { + named_iofds[STDIN_FILENO] = p->fds[i]; + targets--; + } else if (named_iofds[STDOUT_FILENO] < 0 && c->std_output == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDOUT_FILENO] && streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) { + named_iofds[STDOUT_FILENO] = p->fds[i]; + targets--; + } else if (named_iofds[STDERR_FILENO] < 0 && c->std_error == EXEC_OUTPUT_NAMED_FD && stdio_fdname[STDERR_FILENO] && streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) { + named_iofds[STDERR_FILENO] = p->fds[i]; + targets--; + } + + return (targets == 0 ? 0 : -ENOENT); +} + int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l) { char **i, **r = NULL; @@ -3740,9 +3810,7 @@ ExecRuntime *exec_runtime_unref(ExecRuntime *r) { free(r->tmp_dir); free(r->var_tmp_dir); safe_close_pair(r->netns_storage_socket); - free(r); - - return NULL; + return mfree(r); } int exec_runtime_serialize(Unit *u, ExecRuntime *rt, FILE *f, FDSet *fds) { @@ -3898,7 +3966,8 @@ static const char* const exec_input_table[_EXEC_INPUT_MAX] = { [EXEC_INPUT_TTY] = "tty", [EXEC_INPUT_TTY_FORCE] = "tty-force", [EXEC_INPUT_TTY_FAIL] = "tty-fail", - [EXEC_INPUT_SOCKET] = "socket" + [EXEC_INPUT_SOCKET] = "socket", + [EXEC_INPUT_NAMED_FD] = "fd", }; DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput); @@ -3913,7 +3982,8 @@ static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = { [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console", [EXEC_OUTPUT_JOURNAL] = "journal", [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console", - [EXEC_OUTPUT_SOCKET] = "socket" + [EXEC_OUTPUT_SOCKET] = "socket", + [EXEC_OUTPUT_NAMED_FD] = "fd", }; DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput); diff --git a/src/core/execute.h b/src/core/execute.h index 1de439c3ad..c7d0f7761e 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -50,6 +50,7 @@ typedef enum ExecInput { EXEC_INPUT_TTY_FORCE, EXEC_INPUT_TTY_FAIL, EXEC_INPUT_SOCKET, + EXEC_INPUT_NAMED_FD, _EXEC_INPUT_MAX, _EXEC_INPUT_INVALID = -1 } ExecInput; @@ -65,6 +66,7 @@ typedef enum ExecOutput { EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE, EXEC_OUTPUT_SOCKET, + EXEC_OUTPUT_NAMED_FD, _EXEC_OUTPUT_MAX, _EXEC_OUTPUT_INVALID = -1 } ExecOutput; @@ -120,6 +122,7 @@ struct ExecContext { ExecInput std_input; ExecOutput std_output; ExecOutput std_error; + char *stdio_fdname[3]; nsec_t timer_slack_nsec; @@ -284,6 +287,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix); int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_root); int exec_context_load_environment(Unit *unit, const ExecContext *c, char ***l); +int exec_context_named_iofds(Unit *unit, const ExecContext *c, const ExecParameters *p, int named_iofds[3]); +const char* exec_context_fdname(const ExecContext *c, int fd_index); bool exec_context_may_touch_console(ExecContext *c); bool exec_context_maintains_privileges(ExecContext *c); diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index a700d853cc..08c88b6b53 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -35,9 +35,9 @@ $1.Environment, config_parse_environ, 0, $1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files) $1.PassEnvironment, config_parse_pass_environ, 0, offsetof($1, exec_context.pass_environment) $1.DynamicUser, config_parse_bool, 0, offsetof($1, exec_context.dynamic_user) -$1.StandardInput, config_parse_input, 0, offsetof($1, exec_context.std_input) -$1.StandardOutput, config_parse_output, 0, offsetof($1, exec_context.std_output) -$1.StandardError, config_parse_output, 0, offsetof($1, exec_context.std_error) +$1.StandardInput, config_parse_exec_input, 0, offsetof($1, exec_context) +$1.StandardOutput, config_parse_exec_output, 0, offsetof($1, exec_context) +$1.StandardError, config_parse_exec_output, 0, offsetof($1, exec_context) $1.TTYPath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.tty_path) $1.TTYReset, config_parse_bool, 0, offsetof($1, exec_context.tty_reset) $1.TTYVHangup, config_parse_bool, 0, offsetof($1, exec_context.tty_vhangup) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 06c156a623..a69f60097d 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -776,8 +776,104 @@ int config_parse_socket_bindtodevice( return 0; } -DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier"); -DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input literal specifier"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output literal specifier"); + +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) { + ExecContext *c = data; + const char *name; + int r; + + assert(data); + assert(filename); + assert(line); + assert(rvalue); + + name = startswith(rvalue, "fd:"); + if (name) { + /* Strip prefix and validate fd name */ + if (!fdname_is_valid(name)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", name); + return 0; + } + c->std_input = EXEC_INPUT_NAMED_FD; + r = free_and_strdup(&c->stdio_fdname[STDIN_FILENO], name); + if (r < 0) + log_oom(); + return r; + } else { + ExecInput ei = exec_input_from_string(rvalue); + if (ei == _EXEC_INPUT_INVALID) + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse input specifier, ignoring: %s", rvalue); + else + c->std_input = ei; + return 0; + } +} + +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) { + ExecContext *c = data; + ExecOutput eo; + const char *name; + int r; + + assert(data); + assert(filename); + assert(line); + assert(lvalue); + assert(rvalue); + + name = startswith(rvalue, "fd:"); + if (name) { + /* Strip prefix and validate fd name */ + if (!fdname_is_valid(name)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", name); + return 0; + } + eo = EXEC_OUTPUT_NAMED_FD; + } else { + eo = exec_output_from_string(rvalue); + if (eo == _EXEC_OUTPUT_INVALID) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output specifier, ignoring: %s", rvalue); + return 0; + } + } + + if (streq(lvalue, "StandardOutput")) { + c->std_output = eo; + r = free_and_strdup(&c->stdio_fdname[STDOUT_FILENO], name); + if (r < 0) + log_oom(); + return r; + } else if (streq(lvalue, "StandardError")) { + c->std_error = eo; + r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], name); + if (r < 0) + log_oom(); + return r; + } else { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output property, ignoring: %s", lvalue); + return 0; + } +} int config_parse_exec_io_class(const char *unit, const char *filename, @@ -1591,11 +1687,7 @@ int config_parse_fdname( return 0; } - free(s->fdname); - s->fdname = p; - p = NULL; - - return 0; + return free_and_replace(s->fdname, p); } int config_parse_service_sockets( @@ -2052,9 +2144,7 @@ int config_parse_working_directory( return 0; } - free(c->working_directory); - c->working_directory = k; - k = NULL; + free_and_replace(c->working_directory, k); c->working_directory_home = false; } @@ -4189,8 +4279,8 @@ void unit_dump_config_items(FILE *f) { { config_parse_exec_cpu_affinity, "CPUAFFINITY" }, { config_parse_mode, "MODE" }, { config_parse_unit_env_file, "FILE" }, - { config_parse_output, "OUTPUT" }, - { config_parse_input, "INPUT" }, + { config_parse_exec_output, "OUTPUT" }, + { config_parse_exec_input, "INPUT" }, { config_parse_log_facility, "FACILITY" }, { config_parse_log_level, "LEVEL" }, { config_parse_exec_secure_bits, "SECUREBITS" }, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 8b688740cf..6d1fe55bcd 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -45,7 +45,9 @@ int config_parse_service_timeout(const char *unit, const char *filename, unsigne 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_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_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_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); diff --git a/src/core/manager.c b/src/core/manager.c index 3569249788..50aae0d1ba 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1119,8 +1119,7 @@ Manager* manager_free(Manager *m) { hashmap_free(m->uid_refs); hashmap_free(m->gid_refs); - free(m); - return NULL; + return mfree(m); } void manager_enumerate(Manager *m) { diff --git a/src/core/mount.c b/src/core/mount.c index 15619dffe3..da480001e1 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1484,17 +1484,9 @@ static int mount_setup_unit( MOUNT(u)->from_proc_self_mountinfo = true; - free(p->what); - p->what = w; - w = NULL; - - free(p->options); - p->options = o; - o = NULL; - - free(p->fstype); - p->fstype = f; - f = NULL; + free_and_replace(p->what, w); + free_and_replace(p->options, o); + free_and_replace(p->fstype, f); if (load_extras) { r = mount_add_extras(MOUNT(u)); diff --git a/src/core/service.c b/src/core/service.c index 63045ede55..c949de9cbe 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3088,9 +3088,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds) if (!streq_ptr(s->status_text, t)) { - free(s->status_text); - s->status_text = t; - t = NULL; + free_and_replace(s->status_text, t); notify_dbus = true; } diff --git a/src/core/timer.c b/src/core/timer.c index 9538059c13..2469a517ea 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -261,6 +261,8 @@ static void timer_set_state(Timer *t, TimerState state) { if (state != TIMER_WAITING) { t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source); t->realtime_event_source = sd_event_source_unref(t->realtime_event_source); + t->next_elapse_monotonic_or_boottime = USEC_INFINITY; + t->next_elapse_realtime = USEC_INFINITY; } if (state != old_state) diff --git a/src/core/transaction.c b/src/core/transaction.c index 8370b864fb..e22e3b30c2 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -1085,10 +1085,8 @@ Transaction *transaction_new(bool irreversible) { return NULL; tr->jobs = hashmap_new(NULL); - if (!tr->jobs) { - free(tr); - return NULL; - } + if (!tr->jobs) + return mfree(tr); tr->irreversible = irreversible; diff --git a/src/core/unit.c b/src/core/unit.c index 67668bdc48..2fa397bd41 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -88,10 +88,8 @@ Unit *unit_new(Manager *m, size_t size) { return NULL; u->names = set_new(&string_hash_ops); - if (!u->names) { - free(u); - return NULL; - } + if (!u->names) + return mfree(u); u->manager = m; u->type = _UNIT_TYPE_INVALID; @@ -860,18 +858,14 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { return r; } - if (c->std_output != EXEC_OUTPUT_KMSG && - c->std_output != EXEC_OUTPUT_SYSLOG && - c->std_output != EXEC_OUTPUT_JOURNAL && - c->std_output != EXEC_OUTPUT_KMSG_AND_CONSOLE && - c->std_output != EXEC_OUTPUT_SYSLOG_AND_CONSOLE && - c->std_output != EXEC_OUTPUT_JOURNAL_AND_CONSOLE && - c->std_error != EXEC_OUTPUT_KMSG && - c->std_error != EXEC_OUTPUT_SYSLOG && - c->std_error != EXEC_OUTPUT_JOURNAL && - c->std_error != EXEC_OUTPUT_KMSG_AND_CONSOLE && - c->std_error != EXEC_OUTPUT_JOURNAL_AND_CONSOLE && - c->std_error != EXEC_OUTPUT_SYSLOG_AND_CONSOLE) + if (!IN_SET(c->std_output, + EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE, + EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE) && + !IN_SET(c->std_error, + EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE, + EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE)) return 0; /* If syslog or kernel logging is requested, make sure our own @@ -3055,7 +3049,7 @@ int unit_coldplug(Unit *u) { return r; } -static bool fragment_mtime_newer(const char *path, usec_t mtime) { +static bool fragment_mtime_newer(const char *path, usec_t mtime, bool path_masked) { struct stat st; if (!path) @@ -3065,12 +3059,12 @@ static bool fragment_mtime_newer(const char *path, usec_t mtime) { /* What, cannot access this anymore? */ return true; - if (mtime > 0) + if (path_masked) + /* For masked files check if they are still so */ + return !null_or_empty(&st); + else /* For non-empty files check the mtime */ return timespec_load(&st.st_mtim) > mtime; - else if (!null_or_empty(&st)) - /* For masked files check if they are still so */ - return true; return false; } @@ -3081,18 +3075,22 @@ bool unit_need_daemon_reload(Unit *u) { assert(u); - if (fragment_mtime_newer(u->fragment_path, u->fragment_mtime)) + /* For unit files, we allow masking… */ + if (fragment_mtime_newer(u->fragment_path, u->fragment_mtime, + u->load_state == UNIT_MASKED)) return true; - if (fragment_mtime_newer(u->source_path, u->source_mtime)) + /* Source paths should not be masked… */ + if (fragment_mtime_newer(u->source_path, u->source_mtime, false)) return true; (void) unit_find_dropin_paths(u, &t); if (!strv_equal(u->dropin_paths, t)) return true; + /* … any drop-ins that are masked are simply omitted from the list. */ STRV_FOREACH(path, u->dropin_paths) - if (fragment_mtime_newer(*path, u->dropin_mtime)) + if (fragment_mtime_newer(*path, u->dropin_mtime, false)) return true; return false; diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 8ac5ab730a..de0a3b6f9c 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -264,16 +264,13 @@ static crypto_device *get_crypto_device(const char *uuid) { d->keyfile = d->options = d->name = NULL; d->uuid = strdup(uuid); - if (!d->uuid) { - free(d); - return NULL; - } + if (!d->uuid) + return mfree(d); r = hashmap_put(arg_disks, d->uuid, d); if (r < 0) { free(d->uuid); - free(d); - return NULL; + return mfree(d); } } diff --git a/src/import/curl-util.c b/src/import/curl-util.c index 6990c47f48..734e1560e6 100644 --- a/src/import/curl-util.c +++ b/src/import/curl-util.c @@ -235,9 +235,7 @@ CurlGlue *curl_glue_unref(CurlGlue *g) { sd_event_source_unref(g->timer); sd_event_unref(g->event); - free(g); - - return NULL; + return mfree(g); } int curl_glue_new(CurlGlue **glue, sd_event *event) { diff --git a/src/import/export-raw.c b/src/import/export-raw.c index 6136b677dd..a3dbce1954 100644 --- a/src/import/export-raw.c +++ b/src/import/export-raw.c @@ -87,9 +87,7 @@ RawExport *raw_export_unref(RawExport *e) { free(e->buffer); free(e->path); - free(e); - - return NULL; + return mfree(e); } int raw_export_new( diff --git a/src/import/export-tar.c b/src/import/export-tar.c index d79c27f2d0..3bb6027431 100644 --- a/src/import/export-tar.c +++ b/src/import/export-tar.c @@ -91,9 +91,7 @@ TarExport *tar_export_unref(TarExport *e) { free(e->buffer); free(e->path); - free(e); - - return NULL; + return mfree(e); } int tar_export_new( diff --git a/src/import/import-raw.c b/src/import/import-raw.c index fd6b9f7703..29f3f896e5 100644 --- a/src/import/import-raw.c +++ b/src/import/import-raw.c @@ -100,9 +100,7 @@ RawImport* raw_import_unref(RawImport *i) { free(i->final_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int raw_import_new( diff --git a/src/import/import-tar.c b/src/import/import-tar.c index 8b81324fde..22f9b8c5ea 100644 --- a/src/import/import-tar.c +++ b/src/import/import-tar.c @@ -107,9 +107,7 @@ TarImport* tar_import_unref(TarImport *i) { free(i->final_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int tar_import_new( diff --git a/src/import/importd.c b/src/import/importd.c index 28b4302cb3..9d31a956a5 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -141,8 +141,7 @@ static Transfer *transfer_unref(Transfer *t) { safe_close(t->stdin_fd); safe_close(t->stdout_fd); - free(t); - return NULL; + return mfree(t); } DEFINE_TRIVIAL_CLEANUP_FUNC(Transfer*, transfer_unref); @@ -548,8 +547,7 @@ static Manager *manager_unref(Manager *m) { m->bus = sd_bus_flush_close_unref(m->bus); sd_event_unref(m->event); - free(m); - return NULL; + return mfree(m); } DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); diff --git a/src/import/pull-job.c b/src/import/pull-job.c index 6bcf35ef4e..e550df2c57 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -50,9 +50,7 @@ PullJob* pull_job_unref(PullJob *j) { free(j->payload); free(j->checksum); - free(j); - - return NULL; + return mfree(j); } static void pull_job_finish(PullJob *j, int ret) { diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index 8993402821..0cf410a5d9 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -110,9 +110,7 @@ RawPull* raw_pull_unref(RawPull *i) { free(i->settings_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int raw_pull_new( diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c index 8c61c46f73..68e2397b02 100644 --- a/src/import/pull-tar.c +++ b/src/import/pull-tar.c @@ -114,9 +114,7 @@ TarPull* tar_pull_unref(TarPull *i) { free(i->settings_path); free(i->image_root); free(i->local); - free(i); - - return NULL; + return mfree(i); } int tar_pull_new( diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c index 7bba52566e..8729372aa3 100644 --- a/src/journal-remote/journal-remote-write.c +++ b/src/journal-remote/journal-remote-write.c @@ -75,10 +75,8 @@ Writer* writer_new(RemoteServer *server) { memset(&w->metrics, 0xFF, sizeof(w->metrics)); w->mmap = mmap_cache_new(); - if (!w->mmap) { - free(w); - return NULL; - } + if (!w->mmap) + return mfree(w); w->n_ref = 1; w->server = server; @@ -103,9 +101,7 @@ Writer* writer_free(Writer *w) { if (w->mmap) mmap_cache_unref(w->mmap); - free(w); - - return NULL; + return mfree(w); } Writer* writer_unref(Writer *w) { diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c index c0f967ab94..61190ff83c 100644 --- a/src/journal-remote/journal-upload.c +++ b/src/journal-remote/journal-upload.c @@ -527,9 +527,7 @@ static int perform_upload(Uploader *u) { log_debug("Upload finished successfully with code %ld: %s", status, strna(u->answer)); - free(u->last_cursor); - u->last_cursor = u->current_cursor; - u->current_cursor = NULL; + free_and_replace(u->last_cursor, u->current_cursor); return update_cursor_state(u); } diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 49199b269f..d3e0214731 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -394,8 +394,7 @@ JournalFile* journal_file_close(JournalFile *f) { gcry_md_close(f->hmac); #endif - free(f); - return NULL; + return mfree(f); } void journal_file_close_set(Set *s) { diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c index 293d27053a..d91247b524 100644 --- a/src/journal/mmap-cache.c +++ b/src/journal/mmap-cache.c @@ -325,10 +325,8 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) { f->fd = fd; r = hashmap_put(m->fds, FD_TO_PTR(fd), f); - if (r < 0) { - free(f); - return NULL; - } + if (r < 0) + return mfree(f); return f; } diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 98c8a47afe..f2f8546086 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -387,7 +387,7 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) { } static char *match_make_string(Match *m) { - char *p, *r; + char *p = NULL, *r; Match *i; bool enclose = false; @@ -397,15 +397,12 @@ static char *match_make_string(Match *m) { if (m->type == MATCH_DISCRETE) return strndup(m->data, m->size); - p = NULL; LIST_FOREACH(matches, i, m->matches) { char *t, *k; t = match_make_string(i); - if (!t) { - free(p); - return NULL; - } + if (!t) + return mfree(p); if (p) { k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL); diff --git a/src/libsystemd-network/ndisc-router.c b/src/libsystemd-network/ndisc-router.c index d9950b638c..41ff2b353a 100644 --- a/src/libsystemd-network/ndisc-router.c +++ b/src/libsystemd-network/ndisc-router.c @@ -49,8 +49,7 @@ _public_ sd_ndisc_router* sd_ndisc_router_unref(sd_ndisc_router *rt) { if (rt->n_ref > 0) return NULL; - free(rt); - return NULL; + return mfree(rt); } sd_ndisc_router *ndisc_router_new(size_t raw_size) { diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 179e5950bd..5ccb23922c 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -1873,9 +1873,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) { free(client->req_opts); free(client->hostname); free(client->vendor_class_identifier); - free(client); - - return NULL; + return mfree(client); } int sd_dhcp_client_new(sd_dhcp_client **ret) { diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index ef50ed17a1..8387b185c0 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -282,9 +282,7 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { free(lease->static_route); free(lease->client_id); free(lease->vendor_specific); - free(lease); - - return NULL; + return mfree(lease); } static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 11ee2e252e..f16314a37f 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -178,9 +178,7 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) { hashmap_free(server->leases_by_client_id); free(server->bound_leases); - free(server); - - return NULL; + return mfree(server); } int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) { diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 463fde401c..e81215f7d7 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -1300,9 +1300,7 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) { sd_dhcp6_client_detach_event(client); free(client->req_opts); - free(client); - - return NULL; + return mfree(client); } int sd_dhcp6_client_new(sd_dhcp6_client **ret) { diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index 5c10a6326a..ab59977a3f 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -389,9 +389,7 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) { free(lease->ntp); lease->ntp_fqdn = strv_free(lease->ntp_fqdn); - free(lease); - - return NULL; + return mfree(lease); } int dhcp6_lease_new(sd_dhcp6_lease **ret) { diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c index 662885840f..4dd343c101 100644 --- a/src/libsystemd-network/sd-ipv4acd.c +++ b/src/libsystemd-network/sd-ipv4acd.c @@ -135,9 +135,7 @@ sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) { ipv4acd_reset(acd); sd_ipv4acd_detach_event(acd); - free(acd); - - return NULL; + return mfree(acd); } int sd_ipv4acd_new(sd_ipv4acd **ret) { diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index 5603a533a5..13209261f9 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -90,9 +90,7 @@ sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) { return NULL; sd_ipv4acd_unref(ll->acd); - free(ll); - - return NULL; + return mfree(ll); } int sd_ipv4ll_new(sd_ipv4ll **ret) { diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c index 0bd1e66aa0..0702241506 100644 --- a/src/libsystemd-network/sd-lldp.c +++ b/src/libsystemd-network/sd-lldp.c @@ -374,9 +374,7 @@ _public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) { hashmap_free(lldp->neighbor_by_id); prioq_free(lldp->neighbor_by_expiry); - free(lldp); - - return NULL; + return mfree(lldp); } _public_ int sd_lldp_new(sd_lldp **ret) { diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c index 07b0d7f704..1d3be9b862 100644 --- a/src/libsystemd-network/sd-ndisc.c +++ b/src/libsystemd-network/sd-ndisc.c @@ -148,9 +148,7 @@ _public_ sd_ndisc *sd_ndisc_unref(sd_ndisc *nd) { ndisc_reset(nd); sd_ndisc_detach_event(nd); - free(nd); - - return NULL; + return mfree(nd); } _public_ int sd_ndisc_new(sd_ndisc **ret) { diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c index 8e9074c7df..33590c31ac 100644 --- a/src/libsystemd/sd-bus/bus-slot.c +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -212,9 +212,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) { bus_slot_disconnect(slot); free(slot->description); - free(slot); - - return NULL; + return mfree(slot); } _public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) { diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c index 00e93a215f..4acaf24793 100644 --- a/src/libsystemd/sd-bus/bus-track.c +++ b/src/libsystemd/sd-bus/bus-track.c @@ -74,9 +74,7 @@ static struct track_item* track_item_free(struct track_item *i) { sd_bus_slot_unref(i->slot); free(i->name); - free(i); - - return NULL; + return mfree(i); } DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free); @@ -206,9 +204,7 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { bus_track_remove_from_queue(track); hashmap_free(track->names); sd_bus_unref(track->bus); - free(track); - - return NULL; + return mfree(track); } static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c index da496ed456..0d51322a15 100644 --- a/src/libudev/libudev-list.c +++ b/src/libudev/libudev-list.c @@ -166,17 +166,16 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char * entry = new0(struct udev_list_entry, 1); if (entry == NULL) return NULL; + entry->name = strdup(name); - if (entry->name == NULL) { - free(entry); - return NULL; - } + if (entry->name == NULL) + return mfree(entry); + if (value != NULL) { entry->value = strdup(value); if (entry->value == NULL) { free(entry->name); - free(entry); - return NULL; + return mfree(entry); } } @@ -193,8 +192,7 @@ struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char * if (entries == NULL) { free(entry->name); free(entry->value); - free(entry); - return NULL; + return mfree(entry); } list->entries = entries; list->entries_max += add; diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c index 1f9d16c450..a1f2b33ad5 100644 --- a/src/libudev/libudev-monitor.c +++ b/src/libudev/libudev-monitor.c @@ -207,8 +207,7 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c udev_monitor->sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); if (udev_monitor->sock < 0) { log_debug_errno(errno, "error getting socket: %m"); - free(udev_monitor); - return NULL; + return mfree(udev_monitor); } } else { udev_monitor->bound = true; diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 0fc33cf541..4c618ed19e 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -83,6 +83,34 @@ static OutputFlags get_output_flags(void) { colors_enabled() * OUTPUT_COLOR; } +static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *error, char **path) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + char *ans; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "GetSession", + error, &reply, + "s", session_id); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "o", &ans); + if (r < 0) + return r; + + ans = strdup(ans); + if (!ans) + return -ENOMEM; + + *path = ans; + return 0; +} + static int list_sessions(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; @@ -115,10 +143,38 @@ static int list_sessions(int argc, char *argv[], void *userdata) { return bus_log_parse_error(r); if (arg_legend) - printf("%10s %10s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT"); + printf("%10s %10s %-16s %-16s %-16s\n", "SESSION", "UID", "USER", "SEAT", "TTY"); while ((r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object)) > 0) { - printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat); + _cleanup_(sd_bus_error_free) sd_bus_error error2 = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply2 = NULL; + _cleanup_free_ char *path = NULL; + const char *tty = NULL; + + r = get_session_path(bus, id, &error2, &path); + if (r < 0) + log_warning("Failed to get session path: %s", bus_error_message(&error, r)); + else { + r = sd_bus_get_property( + bus, + "org.freedesktop.login1", + path, + "org.freedesktop.login1.Session", + "TTY", + &error2, + &reply2, + "s"); + if (r < 0) + log_warning("Failed to get TTY for session %s: %s", + id, bus_error_message(&error2, r)); + else { + r = sd_bus_message_read(reply2, "s", &tty); + if (r < 0) + return bus_log_parse_error(r); + } + } + + printf("%10s %10"PRIu32" %-16s %-16s %-16s\n", id, uid, user, seat, strna(tty)); k++; } if (r < 0) @@ -165,7 +221,7 @@ static int list_users(int argc, char *argv[], void *userdata) { printf("%10s %-16s\n", "UID", "USER"); while ((r = sd_bus_message_read(reply, "(uso)", &uid, &user, &object)) > 0) { - printf("%10u %-16s\n", (unsigned) uid, user); + printf("%10"PRIu32" %-16s\n", uid, user); k++; } if (r < 0) @@ -462,9 +518,9 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li printf("%s - ", strna(i.id)); if (i.name) - printf("%s (%u)\n", i.name, (unsigned) i.uid); + printf("%s (%"PRIu32")\n", i.name, i.uid); else - printf("%u\n", (unsigned) i.uid); + printf("%"PRIu32"\n", i.uid); s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime); s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime); @@ -477,7 +533,7 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li if (i.leader > 0) { _cleanup_free_ char *t = NULL; - printf("\t Leader: %u", (unsigned) i.leader); + printf("\t Leader: %"PRIu32, i.leader); get_process_comm(i.leader, &t); if (t) @@ -589,9 +645,9 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) *new_line = true; if (i.name) - printf("%s (%u)\n", i.name, (unsigned) i.uid); + printf("%s (%"PRIu32")\n", i.name, i.uid); else - printf("%u\n", (unsigned) i.uid); + printf("%"PRIu32"\n", i.uid); s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime); s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime); @@ -887,26 +943,14 @@ static int show_session(int argc, char *argv[], void *userdata) { for (i = 1; i < argc; i++) { _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 *path = NULL; + _cleanup_free_ char *path = NULL; - r = sd_bus_call_method( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "GetSession", - &error, &reply, - "s", argv[i]); + r = get_session_path(bus, argv[1], &error, &path); if (r < 0) { - log_error("Failed to get session: %s", bus_error_message(&error, r)); + log_error("Failed to get session path: %s", bus_error_message(&error, r)); return r; } - r = sd_bus_message_read(reply, "o", &path); - if (r < 0) - return bus_log_parse_error(r); - if (properties) r = show_properties(bus, path, &new_line); else diff --git a/src/login/logind-button.c b/src/login/logind-button.c index baa6b7113c..90fb93bbaf 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -43,15 +43,12 @@ Button* button_new(Manager *m, const char *name) { return NULL; b->name = strdup(name); - if (!b->name) { - free(b); - return NULL; - } + if (!b->name) + return mfree(b); if (hashmap_put(m->buttons, b->name, b) < 0) { free(b->name); - free(b); - return NULL; + return mfree(b); } b->manager = m; diff --git a/src/login/logind-device.c b/src/login/logind-device.c index eb5edd1cd5..6537fa04bf 100644 --- a/src/login/logind-device.c +++ b/src/login/logind-device.c @@ -34,15 +34,12 @@ Device* device_new(Manager *m, const char *sysfs, bool master) { return NULL; d->sysfs = strdup(sysfs); - if (!d->sysfs) { - free(d); - return NULL; - } + if (!d->sysfs) + return mfree(d); if (hashmap_put(m->devices, d->sysfs, d) < 0) { free(d->sysfs); - free(d); - return NULL; + return mfree(d); } d->manager = m; diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index 6c78e0dddc..c93b24009b 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -45,17 +45,14 @@ Inhibitor* inhibitor_new(Manager *m, const char* id) { return NULL; i->state_file = strappend("/run/systemd/inhibit/", id); - if (!i->state_file) { - free(i); - return NULL; - } + if (!i->state_file) + return mfree(i); i->id = basename(i->state_file); if (hashmap_put(m->inhibitors, i->id, i) < 0) { free(i->state_file); - free(i); - return NULL; + return mfree(i); } i->manager = m; diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index b5192320e4..ecc7bd2e5b 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -48,18 +48,15 @@ Seat *seat_new(Manager *m, const char *id) { return NULL; s->state_file = strappend("/run/systemd/seats/", id); - if (!s->state_file) { - free(s); - return NULL; - } + if (!s->state_file) + return mfree(s); s->id = basename(s->state_file); s->manager = m; if (hashmap_put(m->seats, s->id, s) < 0) { free(s->state_file); - free(s); - return NULL; + return mfree(s); } return s; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index ba1bcc2630..cbf035f706 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -62,16 +62,13 @@ Session* session_new(Manager *m, const char *id) { return NULL; s->state_file = strappend("/run/systemd/sessions/", id); - if (!s->state_file) { - free(s); - return NULL; - } + if (!s->state_file) + return mfree(s); s->devices = hashmap_new(&devt_hash_ops); if (!s->devices) { free(s->state_file); - free(s); - return NULL; + return mfree(s); } s->id = basename(s->state_file); @@ -79,8 +76,7 @@ Session* session_new(Manager *m, const char *id) { if (hashmap_put(m->sessions, s->id, s) < 0) { hashmap_free(s->devices); free(s->state_file); - free(s); - return NULL; + return mfree(s); } s->manager = m; diff --git a/src/machine/machine.c b/src/machine/machine.c index dd046d6563..a02b9d7575 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -80,9 +80,7 @@ Machine* machine_new(Manager *manager, MachineClass class, const char *name) { fail: free(m->state_file); free(m->name); - free(m); - - return NULL; + return mfree(m); } void machine_free(Machine *m) { diff --git a/src/machine/operation.c b/src/machine/operation.c index 2bf93cb493..c966d0d21c 100644 --- a/src/machine/operation.c +++ b/src/machine/operation.c @@ -147,6 +147,5 @@ Operation *operation_free(Operation *o) { if (o->machine) LIST_REMOVE(operations_by_machine, o->machine->operations, o); - free(o); - return NULL; + return mfree(o); } diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c index 77a4734df8..9138ee4511 100644 --- a/src/network/networkd-netdev-tunnel.c +++ b/src/network/networkd-netdev-tunnel.c @@ -201,12 +201,18 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl } static int netdev_vti_fill_message_key(NetDev *netdev, Link *link, sd_netlink_message *m) { - Tunnel *t = VTI(netdev); uint32_t ikey, okey; + Tunnel *t; int r; assert(link); assert(m); + + if (netdev->kind == NETDEV_KIND_VTI) + t = VTI(netdev); + else + t = VTI6(netdev); + assert(t); if (t->key != 0) diff --git a/src/network/networkd-wait-online-link.c b/src/network/networkd-wait-online-link.c index 5727422e3d..e63ba07e90 100644 --- a/src/network/networkd-wait-online-link.c +++ b/src/network/networkd-wait-online-link.c @@ -77,8 +77,7 @@ Link *link_free(Link *l) { } free(l->ifname); - free(l); - return NULL; + return mfree(l); } int link_update_rtnl(Link *l, sd_netlink_message *m) { diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c index 5f1522cfb6..09c8f070ba 100644 --- a/src/nspawn/nspawn-settings.c +++ b/src/nspawn/nspawn-settings.c @@ -101,9 +101,7 @@ Settings* settings_free(Settings *s) { expose_port_free_all(s->expose_ports); custom_mount_free_all(s->custom_mounts, s->n_custom_mounts); - free(s); - - return NULL; + return mfree(s); } bool settings_private_network(Settings *s) { diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 53be18efc6..e03db4d003 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -83,9 +83,7 @@ DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) { if (c->scope) LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c); - free(c); - - return NULL; + return mfree(c); } static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) { @@ -421,9 +419,7 @@ DnsQuery *dns_query_free(DnsQuery *q) { q->manager->n_dns_queries--; } - free(q); - - return NULL; + return mfree(q); } int dns_query_new( diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 5687588a7d..87e4abec6e 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -73,10 +73,8 @@ DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const D return dns_resource_key_ref((DnsResourceKey*) key); k = dns_resource_key_new_consume(key->class, key->type, destination); - if (!k) { - free(destination); - return NULL; - } + if (!k) + return mfree(destination); return k; } @@ -513,9 +511,7 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) { } free(rr->to_string); - free(rr); - - return NULL; + return mfree(rr); } int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) { diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 03811ac8e7..8dbc7f623b 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -128,9 +128,7 @@ DnsScope* dns_scope_free(DnsScope *s) { dns_zone_flush(&s->zone); LIST_REMOVE(scopes, s->manager->dns_scopes, s); - free(s); - - return NULL; + return mfree(s); } DnsServer *dns_scope_get_dns_server(DnsScope *s) { diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c index 732471027b..1386e6a17b 100644 --- a/src/resolve/resolved-dns-search-domain.c +++ b/src/resolve/resolved-dns-search-domain.c @@ -104,9 +104,7 @@ DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d) { return NULL; free(d->name); - free(d); - - return NULL; + return mfree(d); } void dns_search_domain_unlink(DnsSearchDomain *d) { diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 97cc8c0e09..7282848e35 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -139,8 +139,7 @@ DnsServer* dns_server_unref(DnsServer *s) { return NULL; free(s->server_string); - free(s); - return NULL; + return mfree(s); } void dns_server_unlink(DnsServer *s) { diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index dd0e0b90e3..878bae47dc 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -343,9 +343,7 @@ DnsStream *dns_stream_unref(DnsStream *s) { dns_packet_unref(s->write_packet); dns_packet_unref(s->read_packet); - free(s); - - return NULL; + return mfree(s); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_unref); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index d455b6b1fa..2fce44ec8b 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -134,8 +134,7 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) { dns_answer_unref(t->validated_keys); dns_resource_key_unref(t->key); - free(t); - return NULL; + return mfree(t); } DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free); diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index ea4a007139..13e1f91192 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -101,8 +101,7 @@ Link *link_free(Link *l) { free(l->state_file); - free(l); - return NULL; + return mfree(l); } void link_allocate_scopes(Link *l) { @@ -698,8 +697,7 @@ LinkAddress *link_address_free(LinkAddress *a) { dns_resource_record_unref(a->llmnr_address_rr); dns_resource_record_unref(a->llmnr_ptr_rr); - free(a); - return NULL; + return mfree(a); } void link_address_add_rrs(LinkAddress *a, bool force_remove) { diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 40f08e8044..0954641c20 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -630,9 +630,7 @@ Manager *manager_free(Manager *m) { dns_trust_anchor_flush(&m->trust_anchor); manager_etc_hosts_flush(m); - free(m); - - return NULL; + return mfree(m); } int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { diff --git a/src/shared/install.c b/src/shared/install.c index f44f80560a..d33a658d0a 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -214,8 +214,8 @@ static int path_is_config(const LookupPaths *p, const char *path) { assert(p); assert(path); - /* Note that we do *not* have generic checks for /etc or /run in place, since with them we couldn't discern - * configuration from transient or generated units */ + /* Note that we do *not* have generic checks for /etc or /run in place, since with + * them we couldn't discern configuration from transient or generated units */ parent = dirname_malloc(path); if (!parent) @@ -232,8 +232,8 @@ static int path_is_runtime(const LookupPaths *p, const char *path) { assert(p); assert(path); - /* Everything in /run is considered runtime. On top of that we also add explicit checks for the various runtime - * directories, as safety net. */ + /* Everything in /run is considered runtime. On top of that we also add + * explicit checks for the various runtime directories, as safety net. */ rpath = skip_root(p, path); if (rpath && path_startswith(rpath, "/run")) @@ -1097,7 +1097,7 @@ static int config_parse_default_instance( UnitFileInstallInfo *i = data; const char *name; - char *printed; + _cleanup_free_ char *printed = NULL; int r; assert(filename); @@ -1117,15 +1117,10 @@ static int config_parse_default_instance( if (r < 0) return r; - if (!unit_instance_is_valid(printed)) { - free(printed); + if (!unit_instance_is_valid(printed)) return -EINVAL; - } - - free(i->default_instance); - i->default_instance = printed; - return 0; + return free_and_replace(i->default_instance, printed); } static int unit_file_load( @@ -1371,9 +1366,7 @@ static int install_info_follow( if (!streq(basename(i->symlink_target), i->name)) return -EXDEV; - free(i->path); - i->path = i->symlink_target; - i->symlink_target = NULL; + free_and_replace(i->path, i->symlink_target); i->type = _UNIT_FILE_TYPE_INVALID; return unit_file_load_or_readlink(c, i, i->path, root_dir, flags); diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 529d89ee2a..060f8d50c7 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -62,8 +62,7 @@ Image *image_unref(Image *i) { free(i->name); free(i->path); - free(i); - return NULL; + return mfree(i); } static char **image_settings_path(Image *image) { diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 24055e772b..293c6673fc 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -463,8 +463,7 @@ int pty_forward_new( PTYForward *pty_forward_free(PTYForward *f) { pty_forward_disconnect(f); - free(f); - return NULL; + return mfree(f); } int pty_forward_get_last_char(PTYForward *f, char *ch) { diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 7ed60dbe87..129706d15f 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -362,22 +362,24 @@ static int compare_unit_info(const void *a, const void *b) { return strcasecmp(u->id, v->id); } +static const char* unit_type_suffix(const char *name) { + const char *dot; + + dot = strrchr(name, '.'); + if (!dot) + return ""; + + return dot + 1; +} + static bool output_show_unit(const UnitInfo *u, char **patterns) { assert(u); if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE)) return false; - if (arg_types) { - const char *dot; - - dot = strrchr(u->id, '.'); - if (!dot) - return false; - - if (!strv_find(arg_types, dot+1)) - return false; - } + if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id))) + return false; if (arg_all) return true; @@ -403,10 +405,10 @@ static bool output_show_unit(const UnitInfo *u, char **patterns) { } static int output_units_list(const UnitInfo *unit_infos, unsigned c) { - unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len; + unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len; const UnitInfo *u; unsigned n_shown = 0; - int job_count = 0; + int job_count = 0, desc_len; max_id_len = strlen("UNIT"); load_len = strlen("LOAD"); @@ -464,18 +466,20 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { for (u = unit_infos; u < unit_infos + c; u++) { _cleanup_free_ char *e = NULL, *j = NULL; + const char *on_underline = "", *off_underline = ""; const char *on_loaded = "", *off_loaded = ""; const char *on_active = "", *off_active = ""; const char *on_circle = "", *off_circle = ""; const char *id; - bool circle = false; + bool circle = false, underline = false; if (!n_shown && !arg_no_legend) { if (circle_len > 0) fputs(" ", stdout); - printf("%-*s %-*s %-*s %-*s ", + printf("%s%-*s %-*s %-*s %-*s ", + ansi_underline(), id_len, "UNIT", load_len, "LOAD", active_len, "ACTIVE", @@ -484,23 +488,33 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { if (job_count) printf("%-*s ", job_len, "JOB"); - if (!arg_full && arg_no_pager) - printf("%.*s\n", desc_len, "DESCRIPTION"); - else - printf("%s\n", "DESCRIPTION"); + printf("%.*s%s\n", + !arg_full && arg_no_pager ? desc_len : -1, + "DESCRIPTION", + ansi_normal()); } n_shown++; + if (u + 1 < unit_infos + c && + !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) { + on_underline = ansi_underline(); + off_underline = ansi_normal(); + underline = true; + } + if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) { - on_loaded = ansi_highlight_red(); on_circle = ansi_highlight_yellow(); - off_loaded = off_circle = ansi_normal(); + off_circle = ansi_normal(); circle = true; + on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); + off_loaded = on_underline; } else if (streq(u->active_state, "failed") && !arg_plain) { - on_circle = on_active = ansi_highlight_red(); - off_circle = off_active = ansi_normal(); + on_circle = ansi_highlight_red(); + off_circle = ansi_normal(); circle = true; + on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); + off_active = on_underline; } if (u->machine) { @@ -523,17 +537,18 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { if (circle_len > 0) printf("%s%s%s ", on_circle, circle ? special_glyph(BLACK_CIRCLE) : " ", off_circle); - printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s", + printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s", + on_underline, on_active, id_len, id, off_active, on_loaded, load_len, u->load_state, off_loaded, on_active, active_len, u->active_state, sub_len, u->sub_state, off_active, job_count ? job_len + 1 : 0, u->job_id ? u->job_type : ""); - if (desc_len > 0) - printf("%.*s\n", desc_len, u->description); - else - printf("%s\n", u->description); + printf("%.*s%s\n", + desc_len > 0 ? desc_len : -1, + u->description, + off_underline); } if (!arg_no_legend) { @@ -1395,35 +1410,46 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) { id_cols = max_id_len; if (!arg_no_legend && c > 0) - printf("%-*s %-*s\n", + printf("%s%-*s %-*s%s\n", + ansi_underline(), id_cols, "UNIT FILE", - state_cols, "STATE"); + state_cols, "STATE", + ansi_normal()); for (u = units; u < units + c; u++) { _cleanup_free_ char *e = NULL; - const char *on, *off; + const char *on, *off, *on_underline = "", *off_underline = ""; const char *id; + bool underline = false; + + if (u + 1 < units + c && + !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path))) { + on_underline = ansi_underline(); + off_underline = ansi_normal(); + underline = true; + } if (IN_SET(u->state, UNIT_FILE_MASKED, UNIT_FILE_MASKED_RUNTIME, UNIT_FILE_DISABLED, - UNIT_FILE_BAD)) { - on = ansi_highlight_red(); - off = ansi_normal(); - } else if (u->state == UNIT_FILE_ENABLED) { - on = ansi_highlight_green(); - off = ansi_normal(); - } else - on = off = ""; + UNIT_FILE_BAD)) + on = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); + else if (u->state == UNIT_FILE_ENABLED) + on = underline ? ansi_highlight_green_underline() : ansi_highlight_green(); + else + on = on_underline; + off = off_underline; id = basename(u->path); e = arg_full ? NULL : ellipsize(id, id_cols, 33); - printf("%-*s %s%-*s%s\n", + printf("%s%-*s %s%-*s%s%s\n", + on_underline, id_cols, e ? e : id, - on, state_cols, unit_file_state_to_string(u->state), off); + on, state_cols, unit_file_state_to_string(u->state), off, + off_underline); } if (!arg_no_legend) diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index 57d9da4855..752ad0aca8 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -73,7 +73,7 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_ u = after; r = calendar_spec_next_usec(c, after, &u); - printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof(buf), u)); + printf("At: %s\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u)); if (expect != (usec_t)-1) assert_se(r >= 0 && u == expect); else @@ -109,6 +109,28 @@ static void test_timestamp(void) { assert_se(y == x); } +static void test_hourly_bug_4031(void) { + CalendarSpec *c; + usec_t n, u, w; + char buf[FORMAT_TIMESTAMP_MAX], zaf[FORMAT_TIMESTAMP_MAX]; + int r; + + assert_se(calendar_spec_from_string("hourly", &c) >= 0); + n = now(CLOCK_REALTIME); + assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0); + + printf("Now: %s (%"PRIu64")\n", format_timestamp_us(buf, sizeof buf, n), n); + printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(buf, sizeof buf, u), u); + + assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0); + printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror(-r) : format_timestamp_us(zaf, sizeof zaf, w), w); + + assert_se(n < u); + assert_se(u <= n + USEC_PER_HOUR); + assert_se(u < w); + assert_se(w <= u + USEC_PER_HOUR); +} + int main(int argc, char* argv[]) { CalendarSpec *c; @@ -177,6 +199,7 @@ int main(int argc, char* argv[]) { assert_se(calendar_spec_from_string("00:00:00.0..00.9", &c) < 0); test_timestamp(); + test_hourly_bug_4031(); return 0; } diff --git a/src/timesync/timesyncd-server.c b/src/timesync/timesyncd-server.c index 6bda86fe6e..57a7bf2c25 100644 --- a/src/timesync/timesyncd-server.c +++ b/src/timesync/timesyncd-server.c @@ -61,8 +61,7 @@ ServerAddress* server_address_free(ServerAddress *a) { manager_set_server_address(a->name->manager, NULL); } - free(a); - return NULL; + return mfree(a); } int server_name_new( @@ -137,9 +136,7 @@ ServerName *server_name_free(ServerName *n) { log_debug("Removed server %s.", n->string); free(n->string); - free(n); - - return NULL; + return mfree(n); } void server_name_flush_addresses(ServerName *n) { diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index f68a09d7a8..7717ac7924 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -211,8 +211,7 @@ struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) { err: if (conn->sock >= 0) close(conn->sock); - free(conn); - return NULL; + return mfree(conn); } struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn) { diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 26fa52cf6c..7619c8371b 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -1583,8 +1583,7 @@ struct udev_rules *udev_rules_unref(struct udev_rules *rules) { strbuf_cleanup(rules->strbuf); free(rules->uids); free(rules->gids); - free(rules); - return NULL; + return mfree(rules); } bool udev_rules_check_timestamp(struct udev_rules *rules) { |