mirror of
https://github.com/systemd/systemd.git
synced 2024-10-31 07:51:21 +03:00
Merge pull request #7714 from poettering/sd-bus-watch-connect
many sd-bus improvements
This commit is contained in:
commit
2df4611205
7
TODO
7
TODO
@ -35,6 +35,9 @@ Features:
|
||||
|
||||
* add bpf-based implementation of devices cgroup controller logic for compat with cgroupsv2 as supported by newest kernel
|
||||
|
||||
* sd-bus: add vtable flag, that may be used to request client creds implicitly
|
||||
and asynchronously before dispatching the operation
|
||||
|
||||
* implement transient socket unit.
|
||||
|
||||
* make systemd-run create transient path and socket unit.
|
||||
@ -56,8 +59,6 @@ Features:
|
||||
the runtime dir as we maintain for the fdstore: i.e. keep it around as long
|
||||
as the unit is running or has a job queued.
|
||||
|
||||
* add async version of sd_bus_add_match and make use of that
|
||||
|
||||
* support projid-based quota in machinectl for containers, and then drop
|
||||
implicit btrfs loopback magic in machined
|
||||
|
||||
@ -495,14 +496,12 @@ Features:
|
||||
- see if we can introduce a new sd_bus_get_owner_machine_id() call to retrieve the machine ID of the machine of the bus itself
|
||||
- see if we can drop more message validation on the sending side
|
||||
- add API to clone sd_bus_message objects
|
||||
- make AddMatch calls on dbus1 transports async?
|
||||
- longer term: priority inheritance
|
||||
- dbus spec updates:
|
||||
- NameLost/NameAcquired obsolete
|
||||
- GVariant
|
||||
- path escaping
|
||||
- update systemd.special(7) to mention that dbus.socket is only about the compatibility socket now
|
||||
- test bloom filter generation indexes
|
||||
|
||||
* sd-event
|
||||
- allow multiple signal handlers per signal?
|
||||
|
@ -241,6 +241,16 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--watch-bind=</option><replaceable>BOOL</replaceable></term>
|
||||
|
||||
<listitem>
|
||||
<para>Controls whether to wait for the specified <constant>AF_UNIX</constant> bus socket to appear in the
|
||||
file system before connecting to it. Defaults to off. When enabled, the tool will watch the file system until
|
||||
the socket is created and then connect to it.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="user-system-options.xml" xpointer="user" />
|
||||
<xi:include href="user-system-options.xml" xpointer="system" />
|
||||
<xi:include href="user-system-options.xml" xpointer="host" />
|
||||
|
@ -105,7 +105,12 @@ manpages = [
|
||||
['sd-journal', '3', [], ''],
|
||||
['sd-login', '3', [], 'HAVE_PAM'],
|
||||
['sd_booted', '3', [], ''],
|
||||
['sd_bus_add_match', '3', [], ''],
|
||||
['sd_bus_add_match',
|
||||
'3',
|
||||
['sd_bus_add_match_async',
|
||||
'sd_bus_match_signal',
|
||||
'sd_bus_match_signal_async'],
|
||||
''],
|
||||
['sd_bus_creds_get_pid',
|
||||
'3',
|
||||
['sd_bus_creds_get_audit_login_uid',
|
||||
@ -181,6 +186,7 @@ manpages = [
|
||||
['SD_BUS_ERROR_END', 'SD_BUS_ERROR_MAP', 'sd_bus_error_map'],
|
||||
''],
|
||||
['sd_bus_get_fd', '3', [], ''],
|
||||
['sd_bus_is_open', '3', ['sd_bus_is_ready'], ''],
|
||||
['sd_bus_message_append', '3', ['sd_bus_message_appendv'], ''],
|
||||
['sd_bus_message_append_array',
|
||||
'3',
|
||||
@ -200,6 +206,7 @@ manpages = [
|
||||
['sd_bus_message_get_realtime_usec', 'sd_bus_message_get_seqnum'],
|
||||
''],
|
||||
['sd_bus_message_read_basic', '3', [], ''],
|
||||
['sd_bus_message_set_destination', '3', ['sd_bus_message_set_sender'], ''],
|
||||
['sd_bus_negotiate_fds',
|
||||
'3',
|
||||
['sd_bus_negotiate_creds', 'sd_bus_negotiate_timestamp'],
|
||||
@ -210,7 +217,15 @@ manpages = [
|
||||
['sd_bus_path_decode', 'sd_bus_path_decode_many', 'sd_bus_path_encode_many'],
|
||||
''],
|
||||
['sd_bus_process', '3', [], ''],
|
||||
['sd_bus_request_name', '3', ['sd_bus_release_name'], ''],
|
||||
['sd_bus_request_name',
|
||||
'3',
|
||||
['sd_bus_release_name',
|
||||
'sd_bus_release_name_async',
|
||||
'sd_bus_request_name_async'],
|
||||
''],
|
||||
['sd_bus_set_connected_signal', '3', ['sd_bus_get_connected_signal'], ''],
|
||||
['sd_bus_set_sender', '3', ['sd_bus_get_sender'], ''],
|
||||
['sd_bus_set_watch_bind', '3', ['sd_bus_get_watch_bind'], ''],
|
||||
['sd_bus_track_add_name',
|
||||
'3',
|
||||
['sd_bus_track_add_sender',
|
||||
@ -655,6 +670,7 @@ manpages = [
|
||||
['systemd', '1', ['init'], ''],
|
||||
['systemd.automount', '5', [], ''],
|
||||
['systemd.device', '5', [], ''],
|
||||
['systemd.dnssd', '5', [], 'ENABLE_RESOLVE'],
|
||||
['systemd.environment-generator', '7', [], 'ENABLE_ENVIRONMENT_D'],
|
||||
['systemd.exec', '5', [], ''],
|
||||
['systemd.generator', '7', [], ''],
|
||||
@ -663,7 +679,6 @@ manpages = [
|
||||
['systemd.link', '5', [], ''],
|
||||
['systemd.mount', '5', [], ''],
|
||||
['systemd.netdev', '5', [], 'ENABLE_NETWORKD'],
|
||||
['systemd.dnssd', '5', [], 'ENABLE_RESOLVE'],
|
||||
['systemd.network', '5', [], 'ENABLE_NETWORKD'],
|
||||
['systemd.nspawn', '5', [], ''],
|
||||
['systemd.offline-updates', '7', [], ''],
|
||||
|
@ -173,10 +173,9 @@
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><filename>/var/run/utmp</filename></term>
|
||||
<term><filename>/run/utmp</filename></term>
|
||||
|
||||
<listitem><para>The utmp database <command>runlevel</command>
|
||||
reads the previous and current runlevel
|
||||
<listitem><para>The utmp database <command>runlevel</command> reads the previous and current runlevel
|
||||
from.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
@ -45,14 +45,24 @@
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_bus_add_match</refname>
|
||||
<refname>sd_bus_add_match_async</refname>
|
||||
<refname>sd_bus_match_signal</refname>
|
||||
<refname>sd_bus_match_signal_async</refname>
|
||||
|
||||
<refpurpose>Add a match rule for message dispatching</refpurpose>
|
||||
<refpurpose>Add a match rule for incoming message dispatching</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>typedef int (*<function>sd_bus_message_handler_t</function>)</funcdef>
|
||||
<paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
<paramdef>sd_bus_error *<parameter>ret_error</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_add_match</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
@ -63,65 +73,122 @@
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>typedef int (*<function>sd_bus_message_handler_t</function>)</funcdef>
|
||||
<paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
|
||||
<funcdef>int <function>sd_bus_add_match_async</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>match</parameter></paramdef>
|
||||
<paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
|
||||
<paramdef>sd_bus_message_handler_t <parameter>install_callback</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
<paramdef>sd_bus_error *<parameter>ret_error</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_match_signal</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>sender</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>path</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>interface</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>member</parameter></paramdef>
|
||||
<paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_match_signal_async</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>sender</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>path</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>interface</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>member</parameter></paramdef>
|
||||
<paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
|
||||
<paramdef>sd_bus_message_handler_t <parameter>install_callback</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>
|
||||
<function>sd_bus_add_match()</function> installs a match rule for incoming messages received on the specified bus
|
||||
connection object <parameter>bus</parameter>. The syntax of the match rule expression passed in
|
||||
<parameter>match</parameter> is described in the <ulink
|
||||
url="https://dbus.freedesktop.org/doc/dbus-specification.html">D-Bus Specification</ulink>. The specified handler
|
||||
function <parameter>callback</parameter> is called for eaching incoming message matching the specified
|
||||
expression, the <parameter>userdata</parameter> parameter is passed as-is to the callback function.
|
||||
<para><function>sd_bus_add_match()</function> installs a match rule for messages received on the specified bus
|
||||
connection object <parameter>bus</parameter>. The syntax of the match rule expression passed in
|
||||
<parameter>match</parameter> is described in the <ulink
|
||||
url="https://dbus.freedesktop.org/doc/dbus-specification.html">D-Bus Specification</ulink>. The specified handler
|
||||
function <parameter>callback</parameter> is called for eaching incoming message matching the specified expression,
|
||||
the <parameter>userdata</parameter> parameter is passed as-is to the callback function. The match is installed
|
||||
synchronously when connected to a bus broker, i.e. the call sends a control message requested the match to be added
|
||||
to the broker and waits until the broker confirms the match has been installed successfully.</para>
|
||||
|
||||
<para><function>sd_bus_add_match_async()</function> operates very similar to
|
||||
<function>sd_bus_match_signal()</function>, however it installs the match asynchronously, in a non-blocking
|
||||
fashion: a request is sent to the broker, but the call does not wait for a response. The
|
||||
<parameter>install_callback</parameter> function is called when the response is later received, with the response
|
||||
message from the broker as parameter. If this function is specified as <constant>NULL</constant> a default
|
||||
implementation is used that terminates the bus connection should installing the match fail.</para>
|
||||
|
||||
<para><function>sd_bus_match_signal()</function> is very similar to <function>sd_bus_add_match()</function>, but
|
||||
only matches signals, and instead of a match expression accepts four parameters: <parameter>sender</parameter> (the
|
||||
service name of the sender), <parameter>path</parameter> (the object path of the emitting object),
|
||||
<parameter>interface</parameter> (the interface the signal belongs to), <parameter>member</parameter> (the signal
|
||||
name), from which the match string is internally generated. Optionally, these parameters may be specified as
|
||||
<constant>NULL</constant> in which case the relevant field of incoming signals is not tested.</para>
|
||||
|
||||
<para><function>sd_bus_match_signal_async()</function> is combines the signal matching logic of
|
||||
<function>sd_bus_match_signal()</function> with the asynchronous behaviour of
|
||||
<function>sd_bus_add_match_async()</function>.</para>
|
||||
|
||||
<para>On success, and if non-<constant>NULL</constant>, the <parameter>slot</parameter> return parameter will be
|
||||
set to a slot object that may be used as a reference to the installed match, and may be utilized to remove it again
|
||||
at a later time with
|
||||
<citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If specified
|
||||
as <constant>NULL</constant> the lifetime of the match is bound to the lifetime of the bus object itself, and the
|
||||
match cannot be removed independently.</para>
|
||||
|
||||
<para>The message <parameter>m</parameter> passed to the callback is only borrowed, that is, the callback should
|
||||
not call <citerefentry><refentrytitle>sd_bus_message_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
on it. If the callback wants to hold on to the message beyond the lifetime of the callback, it needs to call
|
||||
<citerefentry><refentrytitle>sd_bus_message_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry> to create a
|
||||
new reference.</para>
|
||||
|
||||
<para>If an error occurs during the callback invocation, the callback should return a negative error number
|
||||
(optionally, a more precise error may be returned in <parameter>ret_error</parameter>, as well). If it wants other
|
||||
callbacks that match the same rule to be called, it should return 0. Otherwise it should return a positive integer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
On success, and if non-<constant>NULL</constant>, the <parameter>slot</parameter> return parameter will be set to
|
||||
a slot object that may be used as a reference to the installed match, and may be utilized to remove it again at a
|
||||
later time with
|
||||
<citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
|
||||
specified as <constant>NULL</constant> the lifetime of the match is bound to the lifetime of the bus object itself, and the match
|
||||
cannot be removed independently.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The message <parameter>m</parameter> passed to the callback is only borrowed, that is, the callback should not
|
||||
call <citerefentry><refentrytitle>sd_bus_message_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry> on
|
||||
it. If the callback wants to hold on to the message beyond the lifetime of the callback, it needs to call
|
||||
<citerefentry><refentrytitle>sd_bus_message_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry> to create
|
||||
a new reference.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If an error occurs during the callback invocation, the callback should return a negative error number. If it
|
||||
wants other callbacks that match the same rule to be called, it should return 0. Otherwise it should return a
|
||||
positive integer.
|
||||
</para>
|
||||
<para>If the <parameter>bus</parameter> refers to a direct connection (i.e. not a bus connection, as set with
|
||||
<citerefentry><refentrytitle>sd_bus_set_bus_client</refentrytitle><manvolnum>3</manvolnum></citerefentry>) the
|
||||
match is only installed on the client side, and the synchronous and asynchronous functions operate the same.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>
|
||||
On success, <function>sd_bus_add_match()</function> returns 0 or a positive integer. On failure, it returns a
|
||||
negative errno-style error code.
|
||||
On success, <function>sd_bus_add_match()</function> and the other calls return 0 or a positive integer. On
|
||||
failure, they return a negative errno-style error code.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para><function>sd_bus_add_match()</function> and the other functions described 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>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_message_ref</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_set_bus_client</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
137
man/sd_bus_is_open.xml
Normal file
137
man/sd_bus_is_open.xml
Normal file
@ -0,0 +1,137 @@
|
||||
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2017 Lennart Poettering
|
||||
|
||||
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="sd_bus_is_open">
|
||||
|
||||
<refentryinfo>
|
||||
<title>sd_bus_is_open</title>
|
||||
<productname>systemd</productname>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<contrib>Developer</contrib>
|
||||
<firstname>Lennart</firstname>
|
||||
<surname>Poettering</surname>
|
||||
<email>lennart@poettering.net</email>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>sd_bus_is_open</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_bus_is_open</refname>
|
||||
<refname>sd_bus_is_ready</refname>
|
||||
|
||||
<refpurpose>Check whether the a bus connection is open or ready.</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_is_open</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_is_ready</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_bus_is_open()</function> checks whether the specified bus connection is open, i.e. in the
|
||||
process of being established, already established or in the process of being torn down. It returns zero when the
|
||||
connection has not been started yet
|
||||
(i.e. <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry> or some
|
||||
equivalent call has not been invoked yet), or is fully terminated again (for example after
|
||||
<citerefentry><refentrytitle>sd_bus_close</refentrytitle><manvolnum>3</manvolnum></citerefentry>), it returns
|
||||
positive otherwise.</para>
|
||||
|
||||
<para><function>sd_bus_is_ready()</function> checks whether the specified connection is fully established,
|
||||
i.e. completed the connection and authentication phases of the protocol and received the
|
||||
<function>Hello()</function> method call response, and is not in the process of being torn down again. It returns
|
||||
zero outside of this state, and positive otherwise. Effectively, this function returns positive while regular
|
||||
messages can be sent or received on the connection.</para>
|
||||
|
||||
<para>To be notified when the connection is fully established, use
|
||||
<citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
|
||||
install a match for the <function>Connected()</function> signal on the
|
||||
<literal>org.freedesktop.DBus.Local</literal> interface. To be notified when the connection is torn down again,
|
||||
install a match for the <function>Disconnected()</function> signal on the
|
||||
<literal>org.freedesktop.DBus.Local</literal> interface.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
|
||||
error code.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Errors</title>
|
||||
|
||||
<para>Returned errors may indicate the following problems:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>-ECHILD</constant></term>
|
||||
|
||||
<listitem><para>The bus connection has been created in a different process.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para><function>sd_bus_is_open()</function> and <function>sd_bus_is_ready()</function> 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>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_close</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
137
man/sd_bus_message_set_destination.xml
Normal file
137
man/sd_bus_message_set_destination.xml
Normal file
@ -0,0 +1,137 @@
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2017 Lennart Poettering
|
||||
|
||||
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="sd_bus_message_set_destination">
|
||||
|
||||
<refentryinfo>
|
||||
<title>sd_bus_message_set_destination</title>
|
||||
<productname>systemd</productname>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<contrib>Developer</contrib>
|
||||
<firstname>Lennart</firstname>
|
||||
<surname>Poettering</surname>
|
||||
<email>lennart@poettering.net</email>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>sd_bus_message_set_destination</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_bus_message_set_destination</refname>
|
||||
<refname>sd_bus_message_set_sender</refname>
|
||||
<refpurpose>Set the destination or sender service name of a bus message</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_message_set_destination</function></funcdef>
|
||||
<paramdef>sd_bus_message *<parameter>message</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>destination</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_message_set_sender</function></funcdef>
|
||||
<paramdef>sd_bus_message *<parameter>message</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>sender</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_bus_message_set_destination()</function> sets the destination service name for the specified bus
|
||||
message object. The specified name must be a valid unique or well-known service name.</para>
|
||||
|
||||
<para><function>sd_bus_message_set_sender()</function> sets the sender service name for the specified bus message
|
||||
object. The specified name must be a valid unique or well-known service name. This function is useful only for
|
||||
messages to send on direct connections as for connections to bus brokers the broker will fill in the destination
|
||||
field anyway, and the sender field set by original sender is ignored.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style
|
||||
error code.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Errors</title>
|
||||
|
||||
<para>Returned errors may indicate the following problems:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>-EINVAL</constant></term>
|
||||
|
||||
<listitem><para>A specified parameter is invalid.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-EPERM</constant></term>
|
||||
|
||||
<listitem><para>The message is already sealed.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-EEXIST</constant></term>
|
||||
|
||||
<listitem><para>The message already has a destination or sender field set.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para>The <function>sd_bus_message_set_destination()</function> and
|
||||
<function>sd_bus_message_set_sender()</function> interfaces
|
||||
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>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_set_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
@ -46,7 +46,9 @@
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_bus_request_name</refname>
|
||||
<refname>sd_bus_request_name_async</refname>
|
||||
<refname>sd_bus_release_name</refname>
|
||||
<refname>sd_bus_release_name_async</refname>
|
||||
<refpurpose>Request or release a well-known service name on a bus</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
@ -61,71 +63,103 @@
|
||||
<paramdef>uint64_t <parameter>flags</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_request_name_async</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>name</parameter></paramdef>
|
||||
<paramdef>uint64_t <parameter>flags</parameter></paramdef>
|
||||
<paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_release_name</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>name</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_release_name_async</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>name</parameter></paramdef>
|
||||
<paramdef>sd_bus_message_handler_t <parameter>callback</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_bus_request_name()</function> requests a
|
||||
well-known service name on a bus. It takes a bus connection, a
|
||||
valid bus name and a flags parameter. The flags parameter is a
|
||||
combination of the following flags:</para>
|
||||
<para><function>sd_bus_request_name()</function> requests a well-known service name on a bus. It takes a bus
|
||||
connection, a valid bus name and a flags parameter. The flags parameter is a combination of the following
|
||||
flags:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname></term>
|
||||
|
||||
<listitem><para>After acquiring the name successfully, permit
|
||||
other peers to take over the name when they try to acquire it
|
||||
with the <varname>SD_BUS_NAME_REPLACE_EXISTING</varname> flag
|
||||
set. If <varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname> is
|
||||
not set on the original request, such a request by other peers
|
||||
will be denied.</para></listitem>
|
||||
<listitem><para>After acquiring the name successfully, permit other peers to take over the name when they try
|
||||
to acquire it with the <varname>SD_BUS_NAME_REPLACE_EXISTING</varname> flag set. If
|
||||
<varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname> is not set on the original request, such a request by other
|
||||
peers will be denied.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SD_BUS_NAME_REPLACE_EXISTING</varname></term>
|
||||
|
||||
<listitem><para>Take over the name if it is already acquired
|
||||
by another peer, and that other peer has permitted takeover by
|
||||
setting <varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname> while
|
||||
acquiring it.</para></listitem>
|
||||
<listitem><para>Take over the name if it is already acquired by another peer, and that other peer has permitted
|
||||
takeover by setting <varname>SD_BUS_NAME_ALLOW_REPLACEMENT</varname> while acquiring it.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SD_BUS_NAME_QUEUE</varname></term>
|
||||
|
||||
<listitem><para>Queue the acquisition of the name when the
|
||||
name is already taken.</para></listitem>
|
||||
<listitem><para>Queue the acquisition of the name when the name is already taken.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para><function>sd_bus_release_name()</function> releases an
|
||||
acquired well-known name. It takes a bus connection and a valid
|
||||
bus name as parameters.</para>
|
||||
<para><function>sd_bus_request_name()</function> operates in a synchronous fashion: a message requesting the name
|
||||
is sent to the bus broker, and the call waits until the broker responds.</para>
|
||||
|
||||
<para><function>sd_bus_request_name_async()</function> is an asynchronous version of of
|
||||
<function>sd_bus_release_name()</function>. Instead of waiting for the request to complete, the request message is
|
||||
enqueued. The specified <parameter>callback</parameter> will be called when the broker's response is received. If
|
||||
the parameter is specified as <constant>NULL</constant> a default implementation is used instead which will
|
||||
terminate the connection when the name cannot be acquired. The function returns a slot object in its
|
||||
<parameter>slot</parameter> parameter — if it is passed as non-<constant>NULL</constant> — which may be used as a
|
||||
reference to the name request operation. Use
|
||||
<citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry> to destroy
|
||||
this reference. Note that destroying the reference will not unregister the name, but simply ensure the specified
|
||||
callback is no longer called.</para>
|
||||
|
||||
<para><function>sd_bus_release_name()</function> releases an acquired well-known name. It takes a bus connection
|
||||
and a valid bus name as parameters. This function operates synchronously, sending a release request message to the
|
||||
bus broker and waiting for it to reply.</para>
|
||||
|
||||
<para><function>sd_bus_release_name_async()</function> is an asynchronous version of
|
||||
<function>sd_bus_release_name()</function>. The specified <parameter>callback</parameter> function is called when
|
||||
the name has been released successfully. If specified as <constant>NULL</constant> a generic implementation is used
|
||||
that ignores the result of the operation. As above, the <parameter>slot</parameter> (if
|
||||
non-<constant>NULL</constant>) is set to an object that may be used to reference the operation.</para>
|
||||
|
||||
<para>These functions are supported only on bus connections, i.e. connections to a bus broker and not on direct
|
||||
connections.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>On success, these calls return 0 or a positive integer. On
|
||||
failure, these calls return a negative errno-style error
|
||||
code.</para>
|
||||
<para>On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style
|
||||
error code.</para>
|
||||
|
||||
<para>If <varname>SD_BUS_NAME_QUEUE</varname> is specified,
|
||||
<function>sd_bus_request_name()</function> will return 0 when the
|
||||
name is already taken by another peer and the client has been
|
||||
added to the queue for the name. In that case, the caller can
|
||||
subscribe to <literal>NameOwnerChanged</literal> signals to be
|
||||
notified when the name is successfully acquired.
|
||||
<function>sd_bus_request_name()</function> returns > 0 when the
|
||||
name has immediately been acquired successfully.</para>
|
||||
<para>If <varname>SD_BUS_NAME_QUEUE</varname> is specified, <function>sd_bus_request_name()</function> will return
|
||||
0 when the name is already taken by another peer and the client has been added to the queue for the name. In that
|
||||
case, the caller can subscribe to <literal>NameOwnerChanged</literal> signals to be notified when the name is
|
||||
successfully acquired. <function>sd_bus_request_name()</function> returns > 0 when the name has immediately
|
||||
been acquired successfully.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -137,56 +171,50 @@
|
||||
<varlistentry>
|
||||
<term><constant>-EALREADY</constant></term>
|
||||
|
||||
<listitem><para>The caller already is the owner of the
|
||||
specified name.</para></listitem>
|
||||
<listitem><para>The caller already is the owner of the specified name.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-EEXIST</constant></term>
|
||||
|
||||
<listitem><para>The name has already been acquired by a
|
||||
different peer, and SD_BUS_NAME_REPLACE_EXISTING was not
|
||||
specified or the other peer did not specify
|
||||
SD_BUS_NAME_ALLOW_REPLACEMENT while acquiring the
|
||||
<listitem><para>The name has already been acquired by a different peer, and SD_BUS_NAME_REPLACE_EXISTING was
|
||||
not specified or the other peer did not specify SD_BUS_NAME_ALLOW_REPLACEMENT while acquiring the
|
||||
name.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-ESRCH</constant></term>
|
||||
|
||||
<listitem><para>It was attempted to release a name that is
|
||||
currently not registered on the bus.</para></listitem>
|
||||
<listitem><para>It was attempted to release a name that is currently not registered on the
|
||||
bus.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-EADDRINUSE</constant></term>
|
||||
|
||||
<listitem><para>It was attempted to release a name that is
|
||||
owned by a different peer on the bus.</para></listitem>
|
||||
<listitem><para>It was attempted to release a name that is owned by a different peer on the
|
||||
bus.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-EINVAL</constant></term>
|
||||
|
||||
<listitem><para>A specified parameter is invalid. This is also
|
||||
generated when the requested name is a special service name
|
||||
reserved by the D-Bus specification, or when the operation is
|
||||
requested on a connection that does not refer to a
|
||||
bus.</para></listitem>
|
||||
<listitem><para>A specified parameter is invalid. This is also generated when the requested name is a special
|
||||
service name reserved by the D-Bus specification, or when the operation is requested on a connection that does
|
||||
not refer to a bus.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-ENOTCONN</constant></term>
|
||||
|
||||
<listitem><para>The bus connection has been
|
||||
disconnected.</para></listitem>
|
||||
<listitem><para>The bus connection has been disconnected.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-ECHILD</constant></term>
|
||||
|
||||
<listitem><para>The bus connection has been created in a
|
||||
different process than the current one.</para></listitem>
|
||||
<listitem><para>The bus connection has been created in a different process than the current
|
||||
one.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
@ -194,12 +222,9 @@
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para>The <function>sd_bus_acquire_name()</function> and
|
||||
<function>sd_bus_release_name()</function> interfaces 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>
|
||||
<para>The <function>sd_bus_acquire_name()</function> and the other interfaces described 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>
|
||||
@ -208,7 +233,8 @@
|
||||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
<citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
143
man/sd_bus_set_connected_signal.xml
Normal file
143
man/sd_bus_set_connected_signal.xml
Normal file
@ -0,0 +1,143 @@
|
||||
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2017 Lennart Poettering
|
||||
|
||||
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="sd_bus_set_connected_signal">
|
||||
|
||||
<refentryinfo>
|
||||
<title>sd_bus_set_connected_signal</title>
|
||||
<productname>systemd</productname>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<contrib>Developer</contrib>
|
||||
<firstname>Lennart</firstname>
|
||||
<surname>Poettering</surname>
|
||||
<email>lennart@poettering.net</email>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>sd_bus_set_connected_signal</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_bus_set_connected_signal</refname>
|
||||
<refname>sd_bus_get_connected_signal</refname>
|
||||
|
||||
<refpurpose>Control emmission of local connection establishment signal on bus connections</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_set_connected_signal</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>int <parameter>b</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_get_connected_signal</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_bus_set_connected_signal()</function> may be used to control whether a local, synthetic
|
||||
<function>Connected()</function> signal message shall be generated and enqueued for dispatching when the connection
|
||||
is fully established. If the <parameter>b</parameter> parameter is zero the message is not generated (the default),
|
||||
otherwise it is generated.</para>
|
||||
|
||||
<para><function>sd_bus_get_connected_signal()</function> may be used to query whether this feature is enabled. It
|
||||
returns zero if not, positive otherwise.</para>
|
||||
|
||||
<para>The <function>Connected()</function> signal message is generated from the
|
||||
<literal>org.freedesktop.DBus.Local</literal> service and interface, and
|
||||
<literal>/org/freedesktop/DBus/Local</literal> object path. Use
|
||||
<citerefentry><refentrytitle>sd_bus_match_signal_async</refentrytitle><manvolnum>3</manvolnum></citerefentry> to
|
||||
match on this signal.</para>
|
||||
|
||||
<para>This message is particularly useful on slow transports where connections take a long time to be
|
||||
established. This is especially the case when
|
||||
<citerefentry><refentrytitle>sd_bus_set_watch_bind</refentrytitle><manvolnum>3</manvolnum></citerefentry> is
|
||||
used. The signal is generated when the
|
||||
<citerefentry><refentrytitle>sd_bus_is_ready</refentrytitle><manvolnum>3</manvolnum></citerefentry> returns
|
||||
positive for the first time.</para>
|
||||
|
||||
<para>The <function>Connected()</function> signal corresponds with the <function>Disconnected()</function> signal
|
||||
that is synthesized locally when the connection is terminated. The latter is generated unconditionally however,
|
||||
unlike the former which needs to be enabled explicitly before it is generated, with
|
||||
<function>sd_bus_set_connected_signal()</function>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
|
||||
error code.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Errors</title>
|
||||
|
||||
<para>Returned errors may indicate the following problems:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>-ECHILD</constant></term>
|
||||
|
||||
<listitem><para>The bus connection has been created in a different process.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para><function>sd_bus_set_connected_signal()</function> and <function>sd_bus_get_connected_signal()</function> 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>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_match_signal_async</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_set_watch_bind</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_is_ready</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
136
man/sd_bus_set_sender.xml
Normal file
136
man/sd_bus_set_sender.xml
Normal file
@ -0,0 +1,136 @@
|
||||
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2017 Lennart Poettering
|
||||
|
||||
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="sd_bus_set_sender">
|
||||
|
||||
<refentryinfo>
|
||||
<title>sd_bus_set_sender</title>
|
||||
<productname>systemd</productname>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<contrib>Developer</contrib>
|
||||
<firstname>Lennart</firstname>
|
||||
<surname>Poettering</surname>
|
||||
<email>lennart@poettering.net</email>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>sd_bus_set_sender</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_bus_set_sender</refname>
|
||||
<refname>sd_bus_get_sender</refname>
|
||||
|
||||
<refpurpose>Configure default sender for outgoing messages</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_set_sender</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>const char* <parameter>name</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_get_sender</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>const char** <parameter>name</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_bus_set_sender()</function> configures the default sender service name to use for outgoing
|
||||
messages. The service name specified in the <parameter>name</parameter> parameter is set on all outgoing messages
|
||||
that are sent on the connection and have no sender set yet, for example through
|
||||
<citerefentry><refentrytitle>sd_bus_message_set_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>. Note
|
||||
that this function is only supported on direct connections, i.e. not on connections to a bus broker as the broker
|
||||
will fill in the sender service name automatically anyway. By default no sender name is configured, and hence
|
||||
messages are sent without sender field set. If the <parameter>name</parameter> parameter is specified as
|
||||
<constant>NULL</constant> the default sender service name is cleared, returning to the default state if a default
|
||||
sender service name was set before. If passed as non-<constant>NULL</constant> the specified name must be a valid
|
||||
unique or well-known service name.</para>
|
||||
|
||||
<para><function>sd_bus_get_sender()</function> may be used to query the current default service name for outgoing
|
||||
messages.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
|
||||
error code.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Errors</title>
|
||||
|
||||
<para>Returned errors may indicate the following problems:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>-ECHILD</constant></term>
|
||||
|
||||
<listitem><para>The bus connection has been created in a different process.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-EPERM</constant></term>
|
||||
|
||||
<listitem><para>The specified bus connection object is a not a direct but a brokered connection.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para><function>sd_bus_set_sender()</function> and <function>sd_bus_get_sender()</function> 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>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_message_set_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
152
man/sd_bus_set_watch_bind.xml
Normal file
152
man/sd_bus_set_watch_bind.xml
Normal file
@ -0,0 +1,152 @@
|
||||
<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2017 Lennart Poettering
|
||||
|
||||
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="sd_bus_set_watch_bind">
|
||||
|
||||
<refentryinfo>
|
||||
<title>sd_bus_set_watch_bind</title>
|
||||
<productname>systemd</productname>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<contrib>Developer</contrib>
|
||||
<firstname>Lennart</firstname>
|
||||
<surname>Poettering</surname>
|
||||
<email>lennart@poettering.net</email>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>sd_bus_set_watch_bind</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_bus_set_watch_bind</refname>
|
||||
<refname>sd_bus_get_watch_bind</refname>
|
||||
|
||||
<refpurpose>Control socket binding watching on bus connections</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_set_watch_bind</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>int <parameter>b</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_get_watch_bind</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_bus_set_watch_bind()</function> may be used to enable or disable client-side watching of server
|
||||
socket binding for a bus connection object. If the <parameter>b</parameter> is true, the feature is enabled,
|
||||
otherwise disabled (which is the default). When enabled, and the selected bus address refers to an
|
||||
<filename>AF_UNIX</filename> socket in the file system which does not exist while the connection attempt is made an
|
||||
<citerefentry><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry> watch is installed on
|
||||
it, waiting for the socket to appear. As soon as the socket appears the connection is made. This functionality is
|
||||
useful in particular in early-boot programs that need to run before the system bus is available, but want to
|
||||
connect to it the instant it may be connected to.</para>
|
||||
|
||||
<para><function>sd_bus_get_watch_bind()</function> may be used to query the current setting of this feature. It
|
||||
returns zero when the feature is disabled, and positive if enabled.</para>
|
||||
|
||||
<para>Note that no timeout is applied while it is waited for the socket to appear. This means that any synchronous
|
||||
remote operation (such as
|
||||
<citerefentry><refentrytitle>sd_bus_call</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry> or
|
||||
<citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>), that is
|
||||
used on a connection with this feature enabled that is not established yet might block unbounded if the socket is
|
||||
never created. However, asynchronous remote operations (such as
|
||||
<citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_add_match_async</refentrytitle><manvolnum>3</manvolnum></citerefentry> or
|
||||
<citerefentry><refentrytitle>sd_bus_request_match_async</refentrytitle><manvolnum>3</manvolnum></citerefentry>) do
|
||||
not block in this case, and safely enqueue the requested operations to be dispatched the instant the connection is
|
||||
set up.</para>
|
||||
|
||||
<para>Use <citerefentry><refentrytitle>sd_bus_is_ready</refentrytitle><manvolnum>3</manvolnum></citerefentry> to
|
||||
determine whether the connection is fully established, i.e. whether the peer socket has been bound, connected to
|
||||
and authenticated. Use
|
||||
<citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry> to
|
||||
be notified when the connection is fully established.</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style
|
||||
error code.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Errors</title>
|
||||
|
||||
<para>Returned errors may indicate the following problems:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>-ECHILD</constant></term>
|
||||
|
||||
<listitem><para>The bus connection has been created in a different process.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para><function>sd_bus_set_watch_bind()</function> and <function>sd_bus_get_watch_bind()</function> 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>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>inotify</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_call</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_is_ready</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_set_connected_signal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
@ -2556,6 +2556,14 @@ endif
|
||||
|
||||
############################################################
|
||||
|
||||
meson_check_api_docs_sh = find_program('tools/meson-check-api-docs.sh')
|
||||
run_target(
|
||||
'check-api-docs',
|
||||
depends : [man, libsystemd, libudev],
|
||||
command : [meson_check_api_docs_sh, libsystemd.full_path(), libudev.full_path()])
|
||||
|
||||
############################################################
|
||||
|
||||
status = [
|
||||
'@0@ @1@'.format(meson.project_name(), meson.project_version()),
|
||||
|
||||
|
@ -53,9 +53,10 @@
|
||||
"/usr/lib/kbd/keymaps/\0"
|
||||
#endif
|
||||
|
||||
#define UNIX_SYSTEM_BUS_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
|
||||
#define DEFAULT_SYSTEM_BUS_ADDRESS UNIX_SYSTEM_BUS_ADDRESS
|
||||
#define UNIX_USER_BUS_ADDRESS_FMT "unix:path=%s/bus"
|
||||
/* Note that we use the new /run prefix here (instead of /var/run) since we require them to be aliases and that way we
|
||||
* become independent of /var being mounted */
|
||||
#define DEFAULT_SYSTEM_BUS_ADDRESS "unix:path=/run/dbus/system_bus_socket"
|
||||
#define DEFAULT_USER_BUS_ADDRESS_FMT "unix:path=%s/bus"
|
||||
|
||||
#define PLYMOUTH_SOCKET { \
|
||||
.un.sun_family = AF_UNIX, \
|
||||
|
@ -315,43 +315,60 @@ int fd_warn_permissions(const char *path, int fd) {
|
||||
}
|
||||
|
||||
int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
|
||||
_cleanup_close_ int fd;
|
||||
int r;
|
||||
char fdpath[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
|
||||
_cleanup_close_ int fd = -1;
|
||||
int r, ret = 0;
|
||||
|
||||
assert(path);
|
||||
|
||||
/* Note that touch_file() does not follow symlinks: if invoked on an existing symlink, then it is the symlink
|
||||
* itself which is updated, not its target
|
||||
*
|
||||
* Returns the first error we encounter, but tries to apply as much as possible. */
|
||||
|
||||
if (parents)
|
||||
mkdir_parents(path, 0755);
|
||||
(void) mkdir_parents(path, 0755);
|
||||
|
||||
fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
|
||||
IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
/* Initially, we try to open the node with O_PATH, so that we get a reference to the node. This is useful in
|
||||
* case the path refers to an existing device or socket node, as we can open it successfully in all cases, and
|
||||
* won't trigger any driver magic or so. */
|
||||
fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW);
|
||||
if (fd < 0) {
|
||||
if (errno != ENOENT)
|
||||
return -errno;
|
||||
|
||||
if (mode != MODE_INVALID) {
|
||||
r = fchmod(fd, mode);
|
||||
if (r < 0)
|
||||
/* if the node doesn't exist yet, we create it, but with O_EXCL, so that we only create a regular file
|
||||
* here, and nothing else */
|
||||
fd = open(path, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (uid != UID_INVALID || gid != GID_INVALID) {
|
||||
r = fchown(fd, uid, gid);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
}
|
||||
/* Let's make a path from the fd, and operate on that. With this logic, we can adjust the access mode,
|
||||
* ownership and time of the file node in all cases, even if the fd refers to an O_PATH object — which is
|
||||
* something fchown(), fchmod(), futimensat() don't allow. */
|
||||
xsprintf(fdpath, "/proc/self/fd/%i", fd);
|
||||
|
||||
if (mode != MODE_INVALID)
|
||||
if (chmod(fdpath, mode) < 0)
|
||||
ret = -errno;
|
||||
|
||||
if (uid_is_valid(uid) || gid_is_valid(gid))
|
||||
if (chown(fdpath, uid, gid) < 0 && ret >= 0)
|
||||
ret = -errno;
|
||||
|
||||
if (stamp != USEC_INFINITY) {
|
||||
struct timespec ts[2];
|
||||
|
||||
timespec_store(&ts[0], stamp);
|
||||
ts[1] = ts[0];
|
||||
r = futimens(fd, ts);
|
||||
r = utimensat(AT_FDCWD, fdpath, ts, 0);
|
||||
} else
|
||||
r = futimens(fd, NULL);
|
||||
if (r < 0)
|
||||
r = utimensat(AT_FDCWD, fdpath, NULL, 0);
|
||||
if (r < 0 && ret >= 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int touch(const char *path) {
|
||||
|
@ -33,6 +33,7 @@ int flush_fd(int fd) {
|
||||
.fd = fd,
|
||||
.events = POLLIN,
|
||||
};
|
||||
int count = 0;
|
||||
|
||||
/* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
|
||||
* read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
|
||||
@ -52,7 +53,7 @@ int flush_fd(int fd) {
|
||||
return -errno;
|
||||
|
||||
} else if (r == 0)
|
||||
return 0;
|
||||
return count;
|
||||
|
||||
l = read(fd, buf, sizeof(buf));
|
||||
if (l < 0) {
|
||||
@ -61,11 +62,13 @@ int flush_fd(int fd) {
|
||||
continue;
|
||||
|
||||
if (errno == EAGAIN)
|
||||
return 0;
|
||||
return count;
|
||||
|
||||
return -errno;
|
||||
} else if (l == 0)
|
||||
return 0;
|
||||
return count;
|
||||
|
||||
count += (int) l;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
@ -51,6 +52,7 @@ int socket_address_listen(
|
||||
const char *label) {
|
||||
|
||||
_cleanup_close_ int fd = -1;
|
||||
const char *p;
|
||||
int r, one;
|
||||
|
||||
assert(a);
|
||||
@ -112,19 +114,23 @@ int socket_address_listen(
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
|
||||
return -errno;
|
||||
|
||||
if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
|
||||
p = socket_address_get_path(a);
|
||||
if (p) {
|
||||
/* Create parents */
|
||||
(void) mkdir_parents_label(a->sockaddr.un.sun_path, directory_mode);
|
||||
(void) mkdir_parents_label(p, directory_mode);
|
||||
|
||||
/* Enforce the right access mode for the socket */
|
||||
RUN_WITH_UMASK(~socket_mode) {
|
||||
r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
|
||||
if (r == -EADDRINUSE) {
|
||||
/* Unlink and try again */
|
||||
unlink(a->sockaddr.un.sun_path);
|
||||
if (bind(fd, &a->sockaddr.sa, a->size) < 0)
|
||||
return -errno;
|
||||
} else if (r < 0)
|
||||
|
||||
if (unlink(p) < 0)
|
||||
return r; /* didn't work, return original error */
|
||||
|
||||
r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size);
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
@ -136,6 +142,11 @@ int socket_address_listen(
|
||||
if (listen(fd, backlog) < 0)
|
||||
return -errno;
|
||||
|
||||
/* Let's trigger an inotify event on the socket node, so that anyone waiting for this socket to be connectable
|
||||
* gets notified */
|
||||
if (p)
|
||||
(void) touch(p);
|
||||
|
||||
r = fd;
|
||||
fd = -1;
|
||||
|
||||
|
@ -68,7 +68,6 @@ DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
|
||||
|
||||
int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
char *e, *n;
|
||||
unsigned u;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
@ -78,6 +77,8 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
a->type = SOCK_STREAM;
|
||||
|
||||
if (*s == '[') {
|
||||
uint16_t port;
|
||||
|
||||
/* IPv6 in [x:.....:z]:p notation */
|
||||
|
||||
e = strchr(s+1, ']');
|
||||
@ -95,15 +96,12 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
return -EINVAL;
|
||||
|
||||
e++;
|
||||
r = safe_atou(e, &u);
|
||||
r = parse_ip_port(e, &port);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (u <= 0 || u > 0xFFFF)
|
||||
return -EINVAL;
|
||||
|
||||
a->sockaddr.in6.sin6_family = AF_INET6;
|
||||
a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
|
||||
a->sockaddr.in6.sin6_port = htobe16(port);
|
||||
a->size = sizeof(struct sockaddr_in6);
|
||||
|
||||
} else if (*s == '/') {
|
||||
@ -134,12 +132,13 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
} else if (startswith(s, "vsock:")) {
|
||||
/* AF_VSOCK socket in vsock:cid:port notation */
|
||||
const char *cid_start = s + STRLEN("vsock:");
|
||||
unsigned port;
|
||||
|
||||
e = strchr(cid_start, ':');
|
||||
if (!e)
|
||||
return -EINVAL;
|
||||
|
||||
r = safe_atou(e+1, &u);
|
||||
r = safe_atou(e+1, &port);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -152,19 +151,18 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
a->sockaddr.vm.svm_cid = VMADDR_CID_ANY;
|
||||
|
||||
a->sockaddr.vm.svm_family = AF_VSOCK;
|
||||
a->sockaddr.vm.svm_port = u;
|
||||
a->sockaddr.vm.svm_port = port;
|
||||
a->size = sizeof(struct sockaddr_vm);
|
||||
|
||||
} else {
|
||||
uint16_t port;
|
||||
|
||||
e = strchr(s, ':');
|
||||
if (e) {
|
||||
r = safe_atou(e+1, &u);
|
||||
r = parse_ip_port(e + 1, &port);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (u <= 0 || u > 0xFFFF)
|
||||
return -EINVAL;
|
||||
|
||||
n = strndupa(s, e-s);
|
||||
|
||||
/* IPv4 in w.x.y.z:p notation? */
|
||||
@ -175,7 +173,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
if (r > 0) {
|
||||
/* Gotcha, it's a traditional IPv4 address */
|
||||
a->sockaddr.in.sin_family = AF_INET;
|
||||
a->sockaddr.in.sin_port = htobe16((uint16_t)u);
|
||||
a->sockaddr.in.sin_port = htobe16(port);
|
||||
a->size = sizeof(struct sockaddr_in);
|
||||
} else {
|
||||
unsigned idx;
|
||||
@ -189,7 +187,7 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
return -EINVAL;
|
||||
|
||||
a->sockaddr.in6.sin6_family = AF_INET6;
|
||||
a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
|
||||
a->sockaddr.in6.sin6_port = htobe16(port);
|
||||
a->sockaddr.in6.sin6_scope_id = idx;
|
||||
a->sockaddr.in6.sin6_addr = in6addr_any;
|
||||
a->size = sizeof(struct sockaddr_in6);
|
||||
@ -197,21 +195,18 @@ int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
} else {
|
||||
|
||||
/* Just a port */
|
||||
r = safe_atou(s, &u);
|
||||
r = parse_ip_port(s, &port);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (u <= 0 || u > 0xFFFF)
|
||||
return -EINVAL;
|
||||
|
||||
if (socket_ipv6_is_supported()) {
|
||||
a->sockaddr.in6.sin6_family = AF_INET6;
|
||||
a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
|
||||
a->sockaddr.in6.sin6_port = htobe16(port);
|
||||
a->sockaddr.in6.sin6_addr = in6addr_any;
|
||||
a->size = sizeof(struct sockaddr_in6);
|
||||
} else {
|
||||
a->sockaddr.in.sin_family = AF_INET;
|
||||
a->sockaddr.in.sin_port = htobe16((uint16_t)u);
|
||||
a->sockaddr.in.sin_port = htobe16(port);
|
||||
a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
|
||||
a->size = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
@ -36,16 +36,26 @@
|
||||
#include "util.h"
|
||||
|
||||
union sockaddr_union {
|
||||
/* The minimal, abstract version */
|
||||
struct sockaddr sa;
|
||||
|
||||
/* The libc provided version that allocates "enough room" for every protocol */
|
||||
struct sockaddr_storage storage;
|
||||
|
||||
/* Protoctol-specific implementations */
|
||||
struct sockaddr_in in;
|
||||
struct sockaddr_in6 in6;
|
||||
struct sockaddr_un un;
|
||||
struct sockaddr_nl nl;
|
||||
struct sockaddr_storage storage;
|
||||
struct sockaddr_ll ll;
|
||||
struct sockaddr_vm vm;
|
||||
|
||||
/* Ensure there is enough space to store Infiniband addresses */
|
||||
uint8_t ll_buffer[offsetof(struct sockaddr_ll, sll_addr) + CONST_MAX(ETH_ALEN, INFINIBAND_ALEN)];
|
||||
|
||||
/* Ensure there is enough space after the AF_UNIX sun_path for one more NUL byte, just to be sure that the path
|
||||
* component is always followed by at least one NUL byte. */
|
||||
uint8_t un_buffer[sizeof(struct sockaddr_un) + 1];
|
||||
};
|
||||
|
||||
typedef struct SocketAddress {
|
||||
|
@ -30,45 +30,36 @@
|
||||
#include "verbs.h"
|
||||
#include "virt.h"
|
||||
|
||||
/* Wraps running_in_chroot() which is used in various places,
|
||||
* but also adds an environment variable check so external processes
|
||||
* can reliably force this on.
|
||||
/* Wraps running_in_chroot() which is used in various places, but also adds an environment variable check so external
|
||||
* processes can reliably force this on.
|
||||
*/
|
||||
bool running_in_chroot_or_offline(void) {
|
||||
int r;
|
||||
|
||||
/* Added to support use cases like rpm-ostree, where from %post
|
||||
* scripts we only want to execute "preset", but not "start"/"restart"
|
||||
* for example.
|
||||
/* Added to support use cases like rpm-ostree, where from %post scripts we only want to execute "preset", but
|
||||
* not "start"/"restart" for example.
|
||||
*
|
||||
* See ENVIRONMENT.md for docs.
|
||||
*/
|
||||
r = getenv_bool("SYSTEMD_OFFLINE");
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Parsing SYSTEMD_OFFLINE: %m");
|
||||
else if (r == 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
if (r < 0 && r != -ENXIO)
|
||||
log_debug_errno(r, "Failed to parse $SYSTEMD_OFFLINE: %m");
|
||||
else if (r >= 0)
|
||||
return r > 0;
|
||||
|
||||
/* We've had this condition check for a long time which basically
|
||||
* checks for legacy chroot case like Fedora's
|
||||
* "mock", which is used for package builds. We don't want
|
||||
* to try to start systemd services there, since without --new-chroot
|
||||
* we don't even have systemd running, and even if we did, adding
|
||||
* a concept of background daemons to builds would be an enormous change,
|
||||
* requiring considering things like how the journal output is handled, etc.
|
||||
* And there's really not a use case today for a build talking to a service.
|
||||
/* We've had this condition check for a long time which basically checks for legacy chroot case like Fedora's
|
||||
* "mock", which is used for package builds. We don't want to try to start systemd services there, since
|
||||
* without --new-chroot we don't even have systemd running, and even if we did, adding a concept of background
|
||||
* daemons to builds would be an enormous change, requiring considering things like how the journal output is
|
||||
* handled, etc. And there's really not a use case today for a build talking to a service.
|
||||
*
|
||||
* Note this call itself also looks for a different variable SYSTEMD_IGNORE_CHROOT=1.
|
||||
*/
|
||||
r = running_in_chroot();
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "running_in_chroot(): %m");
|
||||
else if (r > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return r > 0;
|
||||
}
|
||||
|
||||
int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
|
||||
|
@ -62,6 +62,7 @@ static bool arg_expect_reply = true;
|
||||
static bool arg_auto_start = true;
|
||||
static bool arg_allow_interactive_authorization = true;
|
||||
static bool arg_augment_creds = true;
|
||||
static bool arg_watch_bind = false;
|
||||
static usec_t arg_timeout = 0;
|
||||
|
||||
#define NAME_IS_ACQUIRED INT_TO_PTR(1)
|
||||
@ -1735,7 +1736,9 @@ static int help(void) {
|
||||
" --allow-interactive-authorization=BOOL\n"
|
||||
" Allow interactive authorization for operation\n"
|
||||
" --timeout=SECS Maximum time to wait for method call completion\n"
|
||||
" --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n\n"
|
||||
" --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n"
|
||||
" --watch-bind=BOOL Wait for bus AF_UNIX socket to be bound in the file\n"
|
||||
" system\n\n"
|
||||
"Commands:\n"
|
||||
" list List bus names\n"
|
||||
" status [SERVICE] Show bus service, process or bus owner credentials\n"
|
||||
@ -1777,6 +1780,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||
ARG_TIMEOUT,
|
||||
ARG_AUGMENT_CREDS,
|
||||
ARG_WATCH_BIND,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -1803,6 +1807,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION },
|
||||
{ "timeout", required_argument, NULL, ARG_TIMEOUT },
|
||||
{ "augment-creds",required_argument, NULL, ARG_AUGMENT_CREDS},
|
||||
{ "watch-bind", required_argument, NULL, ARG_WATCH_BIND },
|
||||
{},
|
||||
};
|
||||
|
||||
@ -1953,6 +1958,16 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_augment_creds = !!r;
|
||||
break;
|
||||
|
||||
case ARG_WATCH_BIND:
|
||||
r = parse_boolean(optarg);
|
||||
if (r < 0) {
|
||||
log_error("Failed to parse --watch-bind= parameter.");
|
||||
return r;
|
||||
}
|
||||
|
||||
arg_watch_bind = !!r;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@ -2051,6 +2066,12 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sd_bus_set_watch_bind(bus, arg_watch_bind);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to set watch-bind setting to '%s': %m", yes_no(arg_watch_bind));
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (arg_address)
|
||||
r = sd_bus_set_address(bus, arg_address);
|
||||
else {
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "dbus-unit.h"
|
||||
#include "dbus.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "log.h"
|
||||
#include "missing.h"
|
||||
#include "mkdir.h"
|
||||
@ -603,18 +604,16 @@ static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
|
||||
assert(m);
|
||||
assert(bus);
|
||||
|
||||
r = sd_bus_add_match(
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
NULL,
|
||||
"sender='org.freedesktop.DBus.Local',"
|
||||
"type='signal',"
|
||||
"path='/org/freedesktop/DBus/Local',"
|
||||
"interface='org.freedesktop.DBus.Local',"
|
||||
"member='Disconnected'",
|
||||
signal_disconnected, m);
|
||||
|
||||
"org.freedesktop.DBus.Local",
|
||||
"/org/freedesktop/DBus/Local",
|
||||
"org.freedesktop.DBus.Local",
|
||||
"Disconnected",
|
||||
signal_disconnected, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register match for Disconnected message: %m");
|
||||
return log_error_errno(r, "Failed to request match for Disconnected message: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -683,6 +682,12 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_bus_set_sender(bus, "org.freedesktop.systemd1");
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to set direct connection sender: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_bus_start(bus);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to start new connection bus: %m");
|
||||
@ -813,26 +818,23 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
|
||||
log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name);
|
||||
}
|
||||
|
||||
r = sd_bus_add_match(
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.DBus',"
|
||||
"path='/org/freedesktop/DBus',"
|
||||
"interface='org.freedesktop.systemd1.Activator',"
|
||||
"member='ActivationRequest'",
|
||||
signal_activation_request, m);
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.systemd1.Activator",
|
||||
"ActivationRequest",
|
||||
signal_activation_request, NULL, m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to subscribe to activation signal: %m");
|
||||
|
||||
/* Allow replacing of our name, to ease implementation of
|
||||
* reexecution, where we keep the old connection open until
|
||||
* after the new connection is set up and the name installed
|
||||
* to allow clients to synchronously wait for reexecution to
|
||||
* finish */
|
||||
r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT);
|
||||
/* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
|
||||
* until after the new connection is set up and the name installed to allow clients to synchronously wait for
|
||||
* reexecution to finish */
|
||||
r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register name: %m");
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = manager_sync_bus_names(m, bus);
|
||||
if (r < 0)
|
||||
@ -857,7 +859,6 @@ static int bus_init_api(Manager *m) {
|
||||
r = sd_bus_open_system(&bus);
|
||||
else
|
||||
r = sd_bus_open_user(&bus);
|
||||
|
||||
if (r < 0) {
|
||||
log_debug("Failed to connect to API bus, retrying later...");
|
||||
return 0;
|
||||
@ -894,16 +895,16 @@ static int bus_setup_system(Manager *m, sd_bus *bus) {
|
||||
|
||||
/* if we are a user instance we get the Released message via the system bus */
|
||||
if (MANAGER_IS_USER(m)) {
|
||||
r = sd_bus_add_match(
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"interface='org.freedesktop.systemd1.Agent',"
|
||||
"member='Released',"
|
||||
"path='/org/freedesktop/systemd1/agent'",
|
||||
signal_agent_released, m);
|
||||
NULL,
|
||||
"/org/freedesktop/systemd1/agent",
|
||||
"org.freedesktop.systemd1.Agent",
|
||||
"Released",
|
||||
signal_agent_released, NULL, m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to register Released match on system bus: %m");
|
||||
log_warning_errno(r, "Failed to request Released match on system bus: %m");
|
||||
}
|
||||
|
||||
log_debug("Successfully connected to system bus.");
|
||||
@ -1005,6 +1006,9 @@ static int bus_init_private(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "Failed to make private socket listening: %m");
|
||||
|
||||
/* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
|
||||
(void) touch(sa.un.sun_path);
|
||||
|
||||
r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate event source: %m");
|
||||
|
@ -263,7 +263,7 @@ static int manager_dispatch_ask_password_fd(sd_event_source *source,
|
||||
|
||||
assert(m);
|
||||
|
||||
flush_fd(fd);
|
||||
(void) flush_fd(fd);
|
||||
|
||||
m->have_ask_password = have_ask_password();
|
||||
if (m->have_ask_password < 0)
|
||||
|
@ -3042,7 +3042,7 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) {
|
||||
"member='NameOwnerChanged',"
|
||||
"arg0='", name, "'");
|
||||
|
||||
return sd_bus_add_match(bus, &u->match_bus_slot, match, signal_name_owner_changed, u);
|
||||
return sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u);
|
||||
}
|
||||
|
||||
int unit_watch_bus_name(Unit *u, const char *name) {
|
||||
|
@ -680,9 +680,9 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register object: %m");
|
||||
|
||||
r = sd_bus_request_name(bus, "org.freedesktop.hostname1", 0);
|
||||
r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.hostname1", 0, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register name: %m");
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = sd_bus_attach_event(bus, event, 0);
|
||||
if (r < 0)
|
||||
|
@ -1149,9 +1149,9 @@ static int manager_add_bus_objects(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add transfer enumerator: %m");
|
||||
|
||||
r = sd_bus_request_name(m->bus, "org.freedesktop.import1", 0);
|
||||
r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.import1", 0, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register name: %m");
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = sd_bus_attach_event(m->bus, m->event, 0);
|
||||
if (r < 0)
|
||||
|
@ -530,3 +530,20 @@ global:
|
||||
sd_bus_message_new;
|
||||
sd_bus_message_seal;
|
||||
} LIBSYSTEMD_234;
|
||||
|
||||
LIBSYSTEMD_237 {
|
||||
global:
|
||||
sd_bus_set_watch_bind;
|
||||
sd_bus_get_watch_bind;
|
||||
sd_bus_request_name_async;
|
||||
sd_bus_release_name_async;
|
||||
sd_bus_add_match_async;
|
||||
sd_bus_match_signal;
|
||||
sd_bus_match_signal_async;
|
||||
sd_bus_is_ready;
|
||||
sd_bus_set_connected_signal;
|
||||
sd_bus_get_connected_signal;
|
||||
sd_bus_set_sender;
|
||||
sd_bus_get_sender;
|
||||
sd_bus_message_set_sender;
|
||||
} LIBSYSTEMD_236;
|
||||
|
@ -57,13 +57,31 @@ _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
uint32_t ret, param = 0;
|
||||
int r;
|
||||
static int validate_request_name_parameters(
|
||||
sd_bus *bus,
|
||||
const char *name,
|
||||
uint64_t flags,
|
||||
uint32_t *ret_param) {
|
||||
|
||||
uint32_t param = 0;
|
||||
|
||||
assert(bus);
|
||||
assert(name);
|
||||
assert(ret_param);
|
||||
|
||||
assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
|
||||
assert_return(service_name_is_valid(name), -EINVAL);
|
||||
assert_return(name[0] != ':', -EINVAL);
|
||||
|
||||
if (!bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
/* Don't allow requesting the special driver and local names */
|
||||
if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
|
||||
return -EINVAL;
|
||||
|
||||
if (!BUS_IS_OPEN(bus->state))
|
||||
return -ENOTCONN;
|
||||
|
||||
if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
|
||||
param |= BUS_NAME_ALLOW_REPLACEMENT;
|
||||
@ -72,6 +90,28 @@ static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags)
|
||||
if (!(flags & SD_BUS_NAME_QUEUE))
|
||||
param |= BUS_NAME_DO_NOT_QUEUE;
|
||||
|
||||
*ret_param = param;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_request_name(
|
||||
sd_bus *bus,
|
||||
const char *name,
|
||||
uint64_t flags) {
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
uint32_t ret, param = 0;
|
||||
int r;
|
||||
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(name, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
|
||||
r = validate_request_name_parameters(bus, name, flags, ¶m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.DBus",
|
||||
@ -90,46 +130,143 @@ static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags)
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret == BUS_NAME_ALREADY_OWNER)
|
||||
switch (ret) {
|
||||
|
||||
case BUS_NAME_ALREADY_OWNER:
|
||||
return -EALREADY;
|
||||
else if (ret == BUS_NAME_EXISTS)
|
||||
|
||||
case BUS_NAME_EXISTS:
|
||||
return -EEXIST;
|
||||
else if (ret == BUS_NAME_IN_QUEUE)
|
||||
|
||||
case BUS_NAME_IN_QUEUE:
|
||||
return 0;
|
||||
else if (ret == BUS_NAME_PRIMARY_OWNER)
|
||||
|
||||
case BUS_NAME_PRIMARY_OWNER:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
|
||||
static int default_request_name_handler(
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *ret_error) {
|
||||
|
||||
uint32_t ret;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (sd_bus_message_is_method_error(m, NULL)) {
|
||||
log_debug_errno(sd_bus_message_get_errno(m),
|
||||
"Unable to request name, failing connection: %s",
|
||||
sd_bus_message_get_error(m)->message);
|
||||
|
||||
bus_enter_closing(sd_bus_message_get_bus(m));
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read(m, "u", &ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
switch (ret) {
|
||||
|
||||
case BUS_NAME_ALREADY_OWNER:
|
||||
log_debug("Already owner of requested service name, ignoring.");
|
||||
return 1;
|
||||
|
||||
case BUS_NAME_IN_QUEUE:
|
||||
log_debug("In queue for requested service name.");
|
||||
return 1;
|
||||
|
||||
case BUS_NAME_PRIMARY_OWNER:
|
||||
log_debug("Successfully acquired requested service name.");
|
||||
return 1;
|
||||
|
||||
case BUS_NAME_EXISTS:
|
||||
log_debug("Requested service name already owned, failing connection.");
|
||||
bus_enter_closing(sd_bus_message_get_bus(m));
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_debug("Unexpected response from RequestName(), failing connection.");
|
||||
bus_enter_closing(sd_bus_message_get_bus(m));
|
||||
return 1;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_request_name_async(
|
||||
sd_bus *bus,
|
||||
sd_bus_slot **ret_slot,
|
||||
const char *name,
|
||||
uint64_t flags,
|
||||
sd_bus_message_handler_t callback,
|
||||
void *userdata) {
|
||||
|
||||
uint32_t param = 0;
|
||||
int r;
|
||||
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(name, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
|
||||
|
||||
r = validate_request_name_parameters(bus, name, flags, ¶m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_call_method_async(
|
||||
bus,
|
||||
ret_slot,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus",
|
||||
"RequestName",
|
||||
callback ?: default_request_name_handler,
|
||||
userdata,
|
||||
"su",
|
||||
name,
|
||||
param);
|
||||
}
|
||||
|
||||
static int validate_release_name_parameters(
|
||||
sd_bus *bus,
|
||||
const char *name) {
|
||||
|
||||
assert(bus);
|
||||
assert(name);
|
||||
|
||||
assert_return(service_name_is_valid(name), -EINVAL);
|
||||
assert_return(name[0] != ':', -EINVAL);
|
||||
|
||||
if (!bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
/* Don't allow requesting the special driver and local names */
|
||||
/* Don't allow releasing the special driver and local names */
|
||||
if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
|
||||
return -EINVAL;
|
||||
|
||||
if (!BUS_IS_OPEN(bus->state))
|
||||
return -ENOTCONN;
|
||||
|
||||
return bus_request_name_dbus1(bus, name, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
|
||||
_public_ int sd_bus_release_name(
|
||||
sd_bus *bus,
|
||||
const char *name) {
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
uint32_t ret;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(name);
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(name, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
|
||||
r = validate_release_name_parameters(bus, name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
@ -147,41 +284,110 @@ static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
|
||||
r = sd_bus_message_read(reply, "u", &ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (ret == BUS_NAME_NON_EXISTENT)
|
||||
return -ESRCH;
|
||||
if (ret == BUS_NAME_NOT_OWNER)
|
||||
return -EADDRINUSE;
|
||||
if (ret == BUS_NAME_RELEASED)
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
switch (ret) {
|
||||
|
||||
case BUS_NAME_NON_EXISTENT:
|
||||
return -ESRCH;
|
||||
|
||||
case BUS_NAME_NOT_OWNER:
|
||||
return -EADDRINUSE;
|
||||
|
||||
case BUS_NAME_RELEASED:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
|
||||
static int default_release_name_handler(
|
||||
sd_bus_message *m,
|
||||
void *userdata,
|
||||
sd_bus_error *ret_error) {
|
||||
|
||||
uint32_t ret;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (sd_bus_message_is_method_error(m, NULL)) {
|
||||
log_debug_errno(sd_bus_message_get_errno(m),
|
||||
"Unable to release name, failing connection: %s",
|
||||
sd_bus_message_get_error(m)->message);
|
||||
|
||||
bus_enter_closing(sd_bus_message_get_bus(m));
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read(m, "u", &ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
switch (ret) {
|
||||
|
||||
case BUS_NAME_NON_EXISTENT:
|
||||
log_debug("Name asked to release is not taken currently, ignoring.");
|
||||
return 1;
|
||||
|
||||
case BUS_NAME_NOT_OWNER:
|
||||
log_debug("Name asked to release is owned by somebody else, ignoring.");
|
||||
return 1;
|
||||
|
||||
case BUS_NAME_RELEASED:
|
||||
log_debug("Name successfully released.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_debug("Unexpected response from ReleaseName(), failing connection.");
|
||||
bus_enter_closing(sd_bus_message_get_bus(m));
|
||||
return 1;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_release_name_async(
|
||||
sd_bus *bus,
|
||||
sd_bus_slot **ret_slot,
|
||||
const char *name,
|
||||
sd_bus_message_handler_t callback,
|
||||
void *userdata) {
|
||||
|
||||
int r;
|
||||
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(name, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
assert_return(service_name_is_valid(name), -EINVAL);
|
||||
assert_return(name[0] != ':', -EINVAL);
|
||||
|
||||
r = validate_release_name_parameters(bus, name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_call_method_async(
|
||||
bus,
|
||||
ret_slot,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus",
|
||||
"ReleaseName",
|
||||
callback ?: default_release_name_handler,
|
||||
userdata,
|
||||
"s",
|
||||
name);
|
||||
}
|
||||
|
||||
_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_strv_free_ char **x = NULL, **y = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(acquired || activatable, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
|
||||
if (!bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
/* Don't allow releasing the special driver and local names */
|
||||
if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
|
||||
return -EINVAL;
|
||||
|
||||
if (!BUS_IS_OPEN(bus->state))
|
||||
return -ENOTCONN;
|
||||
|
||||
return bus_release_name_dbus1(bus, name);
|
||||
}
|
||||
|
||||
static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_strv_free_ char **x = NULL, **y = NULL;
|
||||
int r;
|
||||
|
||||
if (acquired) {
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
@ -231,21 +437,7 @@ static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatab
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(acquired || activatable, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
|
||||
if (!bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
if (!BUS_IS_OPEN(bus->state))
|
||||
return -ENOTCONN;
|
||||
|
||||
return bus_list_names_dbus1(bus, acquired, activatable);
|
||||
}
|
||||
|
||||
static int bus_get_name_creds_dbus1(
|
||||
_public_ int sd_bus_get_name_creds(
|
||||
sd_bus *bus,
|
||||
const char *name,
|
||||
uint64_t mask,
|
||||
@ -257,6 +449,30 @@ static int bus_get_name_creds_dbus1(
|
||||
pid_t pid = 0;
|
||||
int r;
|
||||
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(name, -EINVAL);
|
||||
assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
|
||||
assert_return(mask == 0 || creds, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
assert_return(service_name_is_valid(name), -EINVAL);
|
||||
|
||||
if (!bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
/* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
|
||||
* going to match. */
|
||||
if (!bus->is_local)
|
||||
mask &= ~SD_BUS_CREDS_AUGMENT;
|
||||
|
||||
if (streq(name, "org.freedesktop.DBus.Local"))
|
||||
return -EINVAL;
|
||||
|
||||
if (streq(name, "org.freedesktop.DBus"))
|
||||
return sd_bus_get_owner_creds(bus, mask, creds);
|
||||
|
||||
if (!BUS_IS_OPEN(bus->state))
|
||||
return -ENOTCONN;
|
||||
|
||||
/* Only query the owner if the caller wants to know it or if
|
||||
* the caller just wants to check whether a name exists */
|
||||
if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
|
||||
@ -519,46 +735,22 @@ static int bus_get_name_creds_dbus1(
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_get_name_creds(
|
||||
sd_bus *bus,
|
||||
const char *name,
|
||||
uint64_t mask,
|
||||
sd_bus_creds **creds) {
|
||||
_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
|
||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
|
||||
bool do_label, do_groups;
|
||||
pid_t pid = 0;
|
||||
int r;
|
||||
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(name, -EINVAL);
|
||||
assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
|
||||
assert_return(mask == 0 || creds, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
assert_return(service_name_is_valid(name), -EINVAL);
|
||||
|
||||
if (!bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
/* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
|
||||
* going to match. */
|
||||
if (!bus->is_local)
|
||||
mask &= ~SD_BUS_CREDS_AUGMENT;
|
||||
|
||||
if (streq(name, "org.freedesktop.DBus.Local"))
|
||||
return -EINVAL;
|
||||
|
||||
if (streq(name, "org.freedesktop.DBus"))
|
||||
return sd_bus_get_owner_creds(bus, mask, creds);
|
||||
|
||||
if (!BUS_IS_OPEN(bus->state))
|
||||
return -ENOTCONN;
|
||||
|
||||
return bus_get_name_creds_dbus1(bus, name, mask, creds);
|
||||
}
|
||||
|
||||
static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
|
||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
|
||||
pid_t pid = 0;
|
||||
bool do_label, do_groups;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
if (!bus->is_local)
|
||||
mask &= ~SD_BUS_CREDS_AUGMENT;
|
||||
|
||||
do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
|
||||
do_groups = bus->n_groups != (size_t) -1 && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS);
|
||||
@ -615,36 +807,23 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
|
||||
if (!BUS_IS_OPEN(bus->state))
|
||||
return -ENOTCONN;
|
||||
|
||||
if (!bus->is_local)
|
||||
mask &= ~SD_BUS_CREDS_AUGMENT;
|
||||
|
||||
return bus_get_owner_creds_dbus1(bus, mask, ret);
|
||||
}
|
||||
|
||||
#define internal_match(bus, m) \
|
||||
((bus)->hello_flags & KDBUS_HELLO_MONITOR \
|
||||
#define append_eavesdrop(bus, m) \
|
||||
((bus)->is_monitor \
|
||||
? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
|
||||
: (m))
|
||||
|
||||
static int bus_add_match_internal_dbus1(
|
||||
int bus_add_match_internal(
|
||||
sd_bus *bus,
|
||||
const char *match) {
|
||||
|
||||
const char *e;
|
||||
|
||||
assert(bus);
|
||||
assert(match);
|
||||
|
||||
e = internal_match(bus, match);
|
||||
if (!bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
e = append_eavesdrop(bus, match);
|
||||
|
||||
return sd_bus_call_method(
|
||||
bus,
|
||||
@ -657,40 +836,31 @@ static int bus_add_match_internal_dbus1(
|
||||
"s",
|
||||
e);
|
||||
}
|
||||
|
||||
int bus_add_match_internal(
|
||||
int bus_add_match_internal_async(
|
||||
sd_bus *bus,
|
||||
sd_bus_slot **ret_slot,
|
||||
const char *match,
|
||||
struct bus_match_component *components,
|
||||
unsigned n_components) {
|
||||
sd_bus_message_handler_t callback,
|
||||
void *userdata) {
|
||||
|
||||
const char *e;
|
||||
|
||||
assert(bus);
|
||||
|
||||
if (!bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
return bus_add_match_internal_dbus1(bus, match);
|
||||
}
|
||||
e = append_eavesdrop(bus, match);
|
||||
|
||||
static int bus_remove_match_internal_dbus1(
|
||||
sd_bus *bus,
|
||||
const char *match) {
|
||||
|
||||
const char *e;
|
||||
|
||||
assert(bus);
|
||||
assert(match);
|
||||
|
||||
e = internal_match(bus, match);
|
||||
|
||||
return sd_bus_call_method(
|
||||
return sd_bus_call_method_async(
|
||||
bus,
|
||||
ret_slot,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus",
|
||||
"RemoveMatch",
|
||||
NULL,
|
||||
NULL,
|
||||
"AddMatch",
|
||||
callback,
|
||||
userdata,
|
||||
"s",
|
||||
e);
|
||||
}
|
||||
@ -699,12 +869,29 @@ int bus_remove_match_internal(
|
||||
sd_bus *bus,
|
||||
const char *match) {
|
||||
|
||||
const char *e;
|
||||
|
||||
assert(bus);
|
||||
assert(match);
|
||||
|
||||
if (!bus->bus_client)
|
||||
return -EINVAL;
|
||||
|
||||
return bus_remove_match_internal_dbus1(bus, match);
|
||||
e = append_eavesdrop(bus, match);
|
||||
|
||||
/* Fire and forget */
|
||||
|
||||
return sd_bus_call_method_async(
|
||||
bus,
|
||||
NULL,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus",
|
||||
"RemoveMatch",
|
||||
NULL,
|
||||
NULL,
|
||||
"s",
|
||||
e);
|
||||
}
|
||||
|
||||
_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "bus-match.h"
|
||||
int bus_add_match_internal(sd_bus *bus, const char *match);
|
||||
int bus_add_match_internal_async(sd_bus *bus, sd_bus_slot **ret, const char *match, sd_bus_message_handler_t callback, void *userdata);
|
||||
|
||||
int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components);
|
||||
int bus_remove_match_internal(sd_bus *bus, const char *match);
|
||||
|
@ -615,3 +615,69 @@ _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define make_expression(sender, path, interface, member) \
|
||||
strjoina( \
|
||||
"type='signal'", \
|
||||
sender ? ",sender='" : "", \
|
||||
sender ?: "", \
|
||||
sender ? "'" : "", \
|
||||
path ? ",path='" : "", \
|
||||
path ?: "", \
|
||||
path ? "'" : "", \
|
||||
interface ? ",interface='" : "", \
|
||||
interface ?: "", \
|
||||
interface ? "'" : "", \
|
||||
member ? ",member='" : "", \
|
||||
member ?: "", \
|
||||
member ? "'" : "" \
|
||||
)
|
||||
|
||||
_public_ int sd_bus_match_signal(
|
||||
sd_bus *bus,
|
||||
sd_bus_slot **ret,
|
||||
const char *sender,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *member,
|
||||
sd_bus_message_handler_t callback,
|
||||
void *userdata) {
|
||||
|
||||
const char *expression;
|
||||
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
assert_return(!sender || service_name_is_valid(sender), -EINVAL);
|
||||
assert_return(!path || object_path_is_valid(path), -EINVAL);
|
||||
assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
|
||||
assert_return(!member || member_name_is_valid(member), -EINVAL);
|
||||
|
||||
expression = make_expression(sender, path, interface, member);
|
||||
|
||||
return sd_bus_add_match(bus, ret, expression, callback, userdata);
|
||||
}
|
||||
|
||||
_public_ int sd_bus_match_signal_async(
|
||||
sd_bus *bus,
|
||||
sd_bus_slot **ret,
|
||||
const char *sender,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *member,
|
||||
sd_bus_message_handler_t callback,
|
||||
sd_bus_message_handler_t install_callback,
|
||||
void *userdata) {
|
||||
|
||||
const char *expression;
|
||||
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
assert_return(!sender || service_name_is_valid(sender), -EINVAL);
|
||||
assert_return(!path || object_path_is_valid(path), -EINVAL);
|
||||
assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
|
||||
assert_return(!member || member_name_is_valid(member), -EINVAL);
|
||||
|
||||
expression = make_expression(sender, path, interface, member);
|
||||
|
||||
return sd_bus_add_match_async(bus, ret, expression, callback, install_callback, userdata);
|
||||
}
|
||||
|
@ -362,13 +362,18 @@ int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
|
||||
} else
|
||||
return r;
|
||||
|
||||
log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
|
||||
log_debug("Failed to process message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s: %s",
|
||||
bus_message_type_to_string(m->header->type),
|
||||
strna(m->sender),
|
||||
strna(m->path),
|
||||
strna(m->interface),
|
||||
strna(m->member),
|
||||
strna(sd_bus_message_get_sender(m)),
|
||||
strna(sd_bus_message_get_destination(m)),
|
||||
strna(sd_bus_message_get_path(m)),
|
||||
strna(sd_bus_message_get_interface(m)),
|
||||
strna(sd_bus_message_get_member(m)),
|
||||
BUS_MESSAGE_COOKIE(m),
|
||||
m->reply_cookie,
|
||||
strna(m->root_container.signature),
|
||||
strna(m->error.name),
|
||||
strna(m->error.message),
|
||||
bus_error_message(error, r));
|
||||
|
||||
return 1;
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
struct reply_callback {
|
||||
sd_bus_message_handler_t callback;
|
||||
usec_t timeout;
|
||||
usec_t timeout_usec; /* this is a relative timeout until we reach the BUS_HELLO state, and an absolute one right after */
|
||||
uint64_t cookie;
|
||||
unsigned prioq_idx;
|
||||
};
|
||||
@ -53,6 +53,9 @@ struct filter_callback {
|
||||
|
||||
struct match_callback {
|
||||
sd_bus_message_handler_t callback;
|
||||
sd_bus_message_handler_t install_callback;
|
||||
|
||||
sd_bus_slot *install_slot; /* The AddMatch() call */
|
||||
|
||||
unsigned last_iteration;
|
||||
|
||||
@ -157,12 +160,14 @@ struct sd_bus_slot {
|
||||
|
||||
enum bus_state {
|
||||
BUS_UNSET,
|
||||
BUS_OPENING,
|
||||
BUS_AUTHENTICATING,
|
||||
BUS_HELLO,
|
||||
BUS_WATCH_BIND, /* waiting for the socket to appear via inotify */
|
||||
BUS_OPENING, /* the kernel's connect() is still not ready */
|
||||
BUS_AUTHENTICATING, /* we are currently in the "SASL" authorization phase of dbus */
|
||||
BUS_HELLO, /* we are waiting for the Hello() response */
|
||||
BUS_RUNNING,
|
||||
BUS_CLOSING,
|
||||
BUS_CLOSED
|
||||
BUS_CLOSED,
|
||||
_BUS_STATE_MAX,
|
||||
};
|
||||
|
||||
static inline bool BUS_IS_OPEN(enum bus_state state) {
|
||||
@ -188,6 +193,7 @@ struct sd_bus {
|
||||
|
||||
enum bus_state state;
|
||||
int input_fd, output_fd;
|
||||
int inotify_fd;
|
||||
int message_version;
|
||||
int message_endian;
|
||||
|
||||
@ -210,6 +216,11 @@ struct sd_bus {
|
||||
bool exited:1;
|
||||
bool exit_triggered:1;
|
||||
bool is_local:1;
|
||||
bool watch_bind:1;
|
||||
bool is_monitor:1;
|
||||
bool accept_fd:1;
|
||||
bool attach_timestamp:1;
|
||||
bool connected_signal:1;
|
||||
|
||||
int use_memfd;
|
||||
|
||||
@ -286,13 +297,11 @@ struct sd_bus {
|
||||
|
||||
pid_t original_pid;
|
||||
|
||||
uint64_t hello_flags;
|
||||
uint64_t attach_flags;
|
||||
|
||||
sd_event_source *input_io_event_source;
|
||||
sd_event_source *output_io_event_source;
|
||||
sd_event_source *time_event_source;
|
||||
sd_event_source *quit_event_source;
|
||||
sd_event_source *inotify_event_source;
|
||||
sd_event *event;
|
||||
int event_priority;
|
||||
|
||||
@ -307,11 +316,15 @@ struct sd_bus {
|
||||
char *cgroup_root;
|
||||
|
||||
char *description;
|
||||
char *patch_sender;
|
||||
|
||||
sd_bus_track *track_queue;
|
||||
|
||||
LIST_HEAD(sd_bus_slot, slots);
|
||||
LIST_HEAD(sd_bus_track, tracks);
|
||||
|
||||
int *inotify_watches;
|
||||
size_t n_inotify_watches;
|
||||
};
|
||||
|
||||
/* For method calls we time-out at 25s, like in the D-Bus reference implementation */
|
||||
@ -367,6 +380,12 @@ bool bus_pid_changed(sd_bus *bus);
|
||||
|
||||
char *bus_address_escape(const char *v);
|
||||
|
||||
int bus_attach_io_events(sd_bus *b);
|
||||
int bus_attach_inotify_event(sd_bus *b);
|
||||
|
||||
void bus_close_inotify_fd(sd_bus *b);
|
||||
void bus_close_io_fds(sd_bus *b);
|
||||
|
||||
#define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \
|
||||
for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \
|
||||
_slash && !(_slash[(_slash) == (prefix)] = 0); \
|
||||
@ -383,8 +402,6 @@ int bus_set_address_user(sd_bus *bus);
|
||||
int bus_set_address_system_remote(sd_bus *b, const char *host);
|
||||
int bus_set_address_system_machine(sd_bus *b, const char *machine);
|
||||
|
||||
int bus_remove_match_by_string(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
|
||||
|
||||
int bus_get_root_path(sd_bus *bus);
|
||||
|
||||
int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error);
|
||||
@ -395,64 +412,6 @@ int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error);
|
||||
return sd_bus_error_set_errno(error, r); \
|
||||
} while (false)
|
||||
|
||||
/**
|
||||
* enum kdbus_attach_flags - flags for metadata attachments
|
||||
* @KDBUS_ATTACH_TIMESTAMP: Timestamp
|
||||
* @KDBUS_ATTACH_CREDS: Credentials
|
||||
* @KDBUS_ATTACH_PIDS: PIDs
|
||||
* @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups
|
||||
* @KDBUS_ATTACH_NAMES: Well-known names
|
||||
* @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID
|
||||
* @KDBUS_ATTACH_PID_COMM: The "comm" process identifier of the PID
|
||||
* @KDBUS_ATTACH_EXE: The path of the executable
|
||||
* @KDBUS_ATTACH_CMDLINE: The process command line
|
||||
* @KDBUS_ATTACH_CGROUP: The croup membership
|
||||
* @KDBUS_ATTACH_CAPS: The process capabilities
|
||||
* @KDBUS_ATTACH_SECLABEL: The security label
|
||||
* @KDBUS_ATTACH_AUDIT: The audit IDs
|
||||
* @KDBUS_ATTACH_CONN_DESCRIPTION: The human-readable connection name
|
||||
* @_KDBUS_ATTACH_ALL: All of the above
|
||||
* @_KDBUS_ATTACH_ANY: Wildcard match to enable any kind of
|
||||
* metatdata.
|
||||
*/
|
||||
enum kdbus_attach_flags {
|
||||
KDBUS_ATTACH_TIMESTAMP = 1ULL << 0,
|
||||
KDBUS_ATTACH_CREDS = 1ULL << 1,
|
||||
KDBUS_ATTACH_PIDS = 1ULL << 2,
|
||||
KDBUS_ATTACH_AUXGROUPS = 1ULL << 3,
|
||||
KDBUS_ATTACH_NAMES = 1ULL << 4,
|
||||
KDBUS_ATTACH_TID_COMM = 1ULL << 5,
|
||||
KDBUS_ATTACH_PID_COMM = 1ULL << 6,
|
||||
KDBUS_ATTACH_EXE = 1ULL << 7,
|
||||
KDBUS_ATTACH_CMDLINE = 1ULL << 8,
|
||||
KDBUS_ATTACH_CGROUP = 1ULL << 9,
|
||||
KDBUS_ATTACH_CAPS = 1ULL << 10,
|
||||
KDBUS_ATTACH_SECLABEL = 1ULL << 11,
|
||||
KDBUS_ATTACH_AUDIT = 1ULL << 12,
|
||||
KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13,
|
||||
_KDBUS_ATTACH_ALL = (1ULL << 14) - 1,
|
||||
_KDBUS_ATTACH_ANY = ~0ULL
|
||||
};
|
||||
void bus_enter_closing(sd_bus *bus);
|
||||
|
||||
/**
|
||||
* enum kdbus_hello_flags - flags for struct kdbus_cmd_hello
|
||||
* @KDBUS_HELLO_ACCEPT_FD: The connection allows the reception of
|
||||
* any passed file descriptors
|
||||
* @KDBUS_HELLO_ACTIVATOR: Special-purpose connection which registers
|
||||
* a well-know name for a process to be started
|
||||
* when traffic arrives
|
||||
* @KDBUS_HELLO_POLICY_HOLDER: Special-purpose connection which registers
|
||||
* policy entries for a name. The provided name
|
||||
* is not activated and not registered with the
|
||||
* name database, it only allows unprivileged
|
||||
* connections to acquire a name, talk or discover
|
||||
* a service
|
||||
* @KDBUS_HELLO_MONITOR: Special-purpose connection to monitor
|
||||
* bus traffic
|
||||
*/
|
||||
enum kdbus_hello_flags {
|
||||
KDBUS_HELLO_ACCEPT_FD = 1ULL << 0,
|
||||
KDBUS_HELLO_ACTIVATOR = 1ULL << 1,
|
||||
KDBUS_HELLO_POLICY_HOLDER = 1ULL << 2,
|
||||
KDBUS_HELLO_MONITOR = 1ULL << 3,
|
||||
};
|
||||
void bus_set_state(sd_bus *bus, enum bus_state state);
|
||||
|
@ -66,49 +66,3 @@ void bus_flush_memfd(sd_bus *b) {
|
||||
for (i = 0; i < b->n_memfd_cache; i++)
|
||||
close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
|
||||
}
|
||||
|
||||
uint64_t attach_flags_to_kdbus(uint64_t mask) {
|
||||
uint64_t m = 0;
|
||||
|
||||
if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
|
||||
SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
|
||||
m |= KDBUS_ATTACH_CREDS;
|
||||
|
||||
if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID))
|
||||
m |= KDBUS_ATTACH_PIDS;
|
||||
|
||||
if (mask & SD_BUS_CREDS_COMM)
|
||||
m |= KDBUS_ATTACH_PID_COMM;
|
||||
|
||||
if (mask & SD_BUS_CREDS_TID_COMM)
|
||||
m |= KDBUS_ATTACH_TID_COMM;
|
||||
|
||||
if (mask & SD_BUS_CREDS_EXE)
|
||||
m |= KDBUS_ATTACH_EXE;
|
||||
|
||||
if (mask & SD_BUS_CREDS_CMDLINE)
|
||||
m |= KDBUS_ATTACH_CMDLINE;
|
||||
|
||||
if (mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID))
|
||||
m |= KDBUS_ATTACH_CGROUP;
|
||||
|
||||
if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
|
||||
m |= KDBUS_ATTACH_CAPS;
|
||||
|
||||
if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
|
||||
m |= KDBUS_ATTACH_SECLABEL;
|
||||
|
||||
if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
|
||||
m |= KDBUS_ATTACH_AUDIT;
|
||||
|
||||
if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
|
||||
m |= KDBUS_ATTACH_NAMES;
|
||||
|
||||
if (mask & SD_BUS_CREDS_DESCRIPTION)
|
||||
m |= KDBUS_ATTACH_CONN_DESCRIPTION;
|
||||
|
||||
if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
|
||||
m |= KDBUS_ATTACH_AUXGROUPS;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@ -41,5 +41,3 @@ struct memfd_cache {
|
||||
|
||||
void close_and_munmap(int fd, void *address, size_t size);
|
||||
void bus_flush_memfd(sd_bus *bus);
|
||||
|
||||
uint64_t attach_flags_to_kdbus(uint64_t sd_bus_flags);
|
||||
|
@ -127,7 +127,6 @@ static void message_free(sd_bus_message *m) {
|
||||
if (m->iovec != m->iovec_fixed)
|
||||
free(m->iovec);
|
||||
|
||||
m->destination_ptr = mfree(m->destination_ptr);
|
||||
message_reset_containers(m);
|
||||
free(m->root_container.signature);
|
||||
free(m->root_container.offsets);
|
||||
@ -5488,6 +5487,15 @@ _public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *desti
|
||||
return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
|
||||
}
|
||||
|
||||
_public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) {
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(sender, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
assert_return(!m->sender, -EEXIST);
|
||||
|
||||
return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);
|
||||
}
|
||||
|
||||
int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) {
|
||||
size_t total;
|
||||
void *p, *e;
|
||||
|
@ -136,10 +136,6 @@ struct sd_bus_message {
|
||||
|
||||
usec_t timeout;
|
||||
|
||||
char sender_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1];
|
||||
char destination_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1];
|
||||
char *destination_ptr;
|
||||
|
||||
size_t header_offsets[_BUS_MESSAGE_HEADER_MAX];
|
||||
unsigned n_header_offsets;
|
||||
};
|
||||
|
@ -1369,7 +1369,7 @@ int bus_process_object(sd_bus *bus, sd_bus_message *m) {
|
||||
assert(bus);
|
||||
assert(m);
|
||||
|
||||
if (bus->hello_flags & KDBUS_HELLO_MONITOR)
|
||||
if (bus->is_monitor)
|
||||
return 0;
|
||||
|
||||
if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
|
||||
|
@ -81,7 +81,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
|
||||
if (slot->reply_callback.cookie != 0)
|
||||
ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
|
||||
|
||||
if (slot->reply_callback.timeout != 0)
|
||||
if (slot->reply_callback.timeout_usec != 0)
|
||||
prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
|
||||
|
||||
break;
|
||||
@ -94,12 +94,17 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
|
||||
case BUS_MATCH_CALLBACK:
|
||||
|
||||
if (slot->match_added)
|
||||
bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
|
||||
(void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
|
||||
|
||||
if (slot->match_callback.install_slot) {
|
||||
bus_slot_disconnect(slot->match_callback.install_slot);
|
||||
slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot);
|
||||
}
|
||||
|
||||
slot->bus->match_callbacks_modified = true;
|
||||
bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
|
||||
|
||||
free(slot->match_callback.match_string);
|
||||
slot->match_callback.match_string = mfree(slot->match_callback.match_string);
|
||||
|
||||
break;
|
||||
|
||||
@ -174,7 +179,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
|
||||
}
|
||||
}
|
||||
|
||||
free(slot->node_vtable.interface);
|
||||
slot->node_vtable.interface = mfree(slot->node_vtable.interface);
|
||||
|
||||
if (slot->node_vtable.node) {
|
||||
LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
|
||||
|
@ -32,9 +32,12 @@
|
||||
#include "bus-socket.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "io-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "path-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "stdio-util.h"
|
||||
@ -188,7 +191,7 @@ static int bus_socket_auth_verify_client(sd_bus *b) {
|
||||
if (!e)
|
||||
return 0;
|
||||
|
||||
if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD) {
|
||||
if (b->accept_fd) {
|
||||
f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
|
||||
if (!f)
|
||||
return 0;
|
||||
@ -475,7 +478,7 @@ static int bus_socket_auth_verify_server(sd_bus *b) {
|
||||
r = bus_socket_auth_write_ok(b);
|
||||
}
|
||||
} else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
|
||||
if (b->auth == _BUS_AUTH_INVALID || !(b->hello_flags & KDBUS_HELLO_ACCEPT_FD))
|
||||
if (b->auth == _BUS_AUTH_INVALID || !b->accept_fd)
|
||||
r = bus_socket_auth_write(b, "ERROR\r\n");
|
||||
else {
|
||||
b->can_fds = true;
|
||||
@ -592,8 +595,8 @@ void bus_socket_setup(sd_bus *b) {
|
||||
assert(b);
|
||||
|
||||
/* Increase the buffers to 8 MB */
|
||||
fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
|
||||
fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
|
||||
(void) fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
|
||||
(void) fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
|
||||
|
||||
b->message_version = 1;
|
||||
b->message_endian = 0;
|
||||
@ -652,7 +655,7 @@ static int bus_socket_start_auth_client(sd_bus *b) {
|
||||
if (!b->auth_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD)
|
||||
if (b->accept_fd)
|
||||
auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
|
||||
else
|
||||
auth_suffix = "\r\nBEGIN\r\n";
|
||||
@ -672,15 +675,15 @@ int bus_socket_start_auth(sd_bus *b) {
|
||||
|
||||
bus_get_peercred(b);
|
||||
|
||||
b->state = BUS_AUTHENTICATING;
|
||||
bus_set_state(b, BUS_AUTHENTICATING);
|
||||
b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_AUTH_TIMEOUT;
|
||||
|
||||
if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
|
||||
b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
|
||||
b->accept_fd = false;
|
||||
|
||||
if (b->output_fd != b->input_fd)
|
||||
if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
|
||||
b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
|
||||
b->accept_fd = false;
|
||||
|
||||
if (b->is_server)
|
||||
return bus_socket_read_auth(b);
|
||||
@ -688,30 +691,249 @@ int bus_socket_start_auth(sd_bus *b) {
|
||||
return bus_socket_start_auth_client(b);
|
||||
}
|
||||
|
||||
static int bus_socket_inotify_setup(sd_bus *b) {
|
||||
_cleanup_free_ int *new_watches = NULL;
|
||||
_cleanup_free_ char *absolute = NULL;
|
||||
size_t n_allocated = 0, n = 0, done = 0, i;
|
||||
unsigned max_follow = 32;
|
||||
const char *p;
|
||||
int wd, r;
|
||||
|
||||
assert(b);
|
||||
assert(b->watch_bind);
|
||||
assert(b->sockaddr.sa.sa_family == AF_UNIX);
|
||||
assert(b->sockaddr.un.sun_path[0] != 0);
|
||||
|
||||
/* Sets up an inotify fd in case watch_bind is enabled: wait until the configured AF_UNIX file system socket
|
||||
* appears before connecting to it. The implemented is pretty simplistic: we just subscribe to relevant changes
|
||||
* to all prefix components of the path, and every time we get an event for that we try to reconnect again,
|
||||
* without actually caring what precisely the event we got told us. If we still can't connect we re-subscribe
|
||||
* to all relevant changes of anything in the path, so that our watches include any possibly newly created path
|
||||
* components. */
|
||||
|
||||
if (b->inotify_fd < 0) {
|
||||
b->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
|
||||
if (b->inotify_fd < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* Make sure the path is NUL terminated */
|
||||
p = strndupa(b->sockaddr.un.sun_path, sizeof(b->sockaddr.un.sun_path));
|
||||
|
||||
/* Make sure the path is absolute */
|
||||
r = path_make_absolute_cwd(p, &absolute);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
/* Watch all parent directories, and don't mind any prefix that doesn't exist yet. For the innermost directory
|
||||
* that exists we want to know when files are created or moved into it. For all parents of it we just care if
|
||||
* they are removed or renamed. */
|
||||
|
||||
if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Start with the top-level directory, which is a bit simpler than the rest, since it can't be a symlink, and
|
||||
* always exists */
|
||||
wd = inotify_add_watch(b->inotify_fd, "/", IN_CREATE|IN_MOVED_TO);
|
||||
if (wd < 0) {
|
||||
r = log_debug_errno(errno, "Failed to add inotify watch on /: %m");
|
||||
goto fail;
|
||||
} else
|
||||
new_watches[n++] = wd;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *component = NULL, *prefix = NULL, *destination = NULL;
|
||||
size_t n_slashes, n_component;
|
||||
char *c = NULL;
|
||||
|
||||
n_slashes = strspn(absolute + done, "/");
|
||||
n_component = n_slashes + strcspn(absolute + done + n_slashes, "/");
|
||||
|
||||
if (n_component == 0) /* The end */
|
||||
break;
|
||||
|
||||
component = strndup(absolute + done, n_component);
|
||||
if (!component) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* A trailing slash? That's a directory, and not a socket then */
|
||||
if (path_equal(component, "/")) {
|
||||
r = -EISDIR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* A single dot? Let's eat this up */
|
||||
if (path_equal(component, "/.")) {
|
||||
done += n_component;
|
||||
continue;
|
||||
}
|
||||
|
||||
prefix = strndup(absolute, done + n_component);
|
||||
if (!prefix) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wd = inotify_add_watch(b->inotify_fd, prefix, IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO|IN_DONT_FOLLOW);
|
||||
log_debug("Added inotify watch for %s on bus %s: %i", prefix, strna(b->description), wd);
|
||||
|
||||
if (wd < 0) {
|
||||
if (IN_SET(errno, ENOENT, ELOOP))
|
||||
break; /* This component doesn't exist yet, or the path contains a cyclic symlink right now */
|
||||
|
||||
r = log_debug_errno(errno, "Failed to add inotify watch on %s: %m", isempty(prefix) ? "/" : prefix);
|
||||
goto fail;
|
||||
} else
|
||||
new_watches[n++] = wd;
|
||||
|
||||
/* Check if this is possibly a symlink. If so, let's follow it and watch it too. */
|
||||
r = readlink_malloc(prefix, &destination);
|
||||
if (r == -EINVAL) { /* not a symlink */
|
||||
done += n_component;
|
||||
continue;
|
||||
}
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (isempty(destination)) { /* Empty symlink target? Yuck! */
|
||||
r = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (max_follow <= 0) { /* Let's make sure we don't follow symlinks forever */
|
||||
r = -ELOOP;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (path_is_absolute(destination)) {
|
||||
/* For absolute symlinks we build the new path and start anew */
|
||||
c = strjoin(destination, absolute + done + n_component);
|
||||
done = 0;
|
||||
} else {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
|
||||
/* For relative symlinks we replace the last component, and try again */
|
||||
t = strndup(absolute, done);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
c = strjoin(t, "/", destination, absolute + done + n_component);
|
||||
}
|
||||
if (!c) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
free(absolute);
|
||||
absolute = c;
|
||||
|
||||
max_follow--;
|
||||
}
|
||||
|
||||
/* And now, let's remove all watches from the previous iteration we don't need anymore */
|
||||
for (i = 0; i < b->n_inotify_watches; i++) {
|
||||
bool found = false;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < n; j++)
|
||||
if (new_watches[j] == b->inotify_watches[i]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
(void) inotify_rm_watch(b->inotify_fd, b->inotify_watches[i]);
|
||||
}
|
||||
|
||||
free_and_replace(b->inotify_watches, new_watches);
|
||||
b->n_inotify_watches = n;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
bus_close_inotify_fd(b);
|
||||
return r;
|
||||
}
|
||||
|
||||
int bus_socket_connect(sd_bus *b) {
|
||||
bool inotify_done = false;
|
||||
int r;
|
||||
|
||||
assert(b);
|
||||
assert(b->input_fd < 0);
|
||||
assert(b->output_fd < 0);
|
||||
assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
|
||||
|
||||
b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
if (b->input_fd < 0)
|
||||
return -errno;
|
||||
for (;;) {
|
||||
assert(b->input_fd < 0);
|
||||
assert(b->output_fd < 0);
|
||||
assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
|
||||
|
||||
b->output_fd = b->input_fd;
|
||||
b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
|
||||
if (b->input_fd < 0)
|
||||
return -errno;
|
||||
|
||||
bus_socket_setup(b);
|
||||
b->output_fd = b->input_fd;
|
||||
bus_socket_setup(b);
|
||||
|
||||
r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
|
||||
if (r < 0) {
|
||||
if (errno == EINPROGRESS)
|
||||
return 1;
|
||||
if (connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size) < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
|
||||
return -errno;
|
||||
/* If we have any inotify watches open, close them now, we don't need them anymore, as
|
||||
* we have successfully initiated a connection */
|
||||
bus_close_inotify_fd(b);
|
||||
|
||||
/* Note that very likely we are already in BUS_OPENING state here, as we enter it when
|
||||
* we start parsing the address string. The only reason we set the state explicitly
|
||||
* here, is to undo BUS_WATCH_BIND, in case we did the inotify magic. */
|
||||
bus_set_state(b, BUS_OPENING);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (IN_SET(errno, ENOENT, ECONNREFUSED) && /* ENOENT → unix socket doesn't exist at all; ECONNREFUSED → unix socket stale */
|
||||
b->watch_bind &&
|
||||
b->sockaddr.sa.sa_family == AF_UNIX &&
|
||||
b->sockaddr.un.sun_path[0] != 0) {
|
||||
|
||||
/* This connection attempt failed, let's release the socket for now, and start with a
|
||||
* fresh one when reconnecting. */
|
||||
bus_close_io_fds(b);
|
||||
|
||||
if (inotify_done) {
|
||||
/* inotify set up already, don't do it again, just return now, and remember
|
||||
* that we are waiting for inotify events now. */
|
||||
bus_set_state(b, BUS_WATCH_BIND);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This is a file system socket, and the inotify logic is enabled. Let's create the necessary inotify fd. */
|
||||
r = bus_socket_inotify_setup(b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Let's now try to connect a second time, because in theory there's otherwise a race
|
||||
* here: the socket might have been created in the time between our first connect() and
|
||||
* the time we set up the inotify logic. But let's remember that we set up inotify now,
|
||||
* so that we don't do the connect() more than twice. */
|
||||
inotify_done = true;
|
||||
|
||||
} else
|
||||
return -errno;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
/* Yay, established, we don't need no inotify anymore! */
|
||||
bus_close_inotify_fd(b);
|
||||
|
||||
return bus_socket_start_auth(b);
|
||||
}
|
||||
|
||||
@ -742,10 +964,10 @@ int bus_socket_exec(sd_bus *b) {
|
||||
if (!IN_SET(s[1], STDIN_FILENO, STDOUT_FILENO))
|
||||
safe_close(s[1]);
|
||||
|
||||
fd_cloexec(STDIN_FILENO, false);
|
||||
fd_cloexec(STDOUT_FILENO, false);
|
||||
fd_nonblock(STDIN_FILENO, false);
|
||||
fd_nonblock(STDOUT_FILENO, false);
|
||||
(void) fd_cloexec(STDIN_FILENO, false);
|
||||
(void) fd_cloexec(STDOUT_FILENO, false);
|
||||
(void) fd_nonblock(STDIN_FILENO, false);
|
||||
(void) fd_nonblock(STDOUT_FILENO, false);
|
||||
|
||||
if (b->exec_argv)
|
||||
execvp(b->exec_path, b->exec_argv);
|
||||
@ -1069,3 +1291,34 @@ int bus_socket_process_authenticating(sd_bus *b) {
|
||||
|
||||
return bus_socket_read_auth(b);
|
||||
}
|
||||
|
||||
int bus_socket_process_watch_bind(sd_bus *b) {
|
||||
int r, q;
|
||||
|
||||
assert(b);
|
||||
assert(b->state == BUS_WATCH_BIND);
|
||||
assert(b->inotify_fd >= 0);
|
||||
|
||||
r = flush_fd(b->inotify_fd);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
log_debug("Got inotify event on bus %s.", strna(b->description));
|
||||
|
||||
/* We flushed events out of the inotify fd. In that case, maybe the socket is valid now? Let's try to connect
|
||||
* to it again */
|
||||
|
||||
r = bus_socket_connect(b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
q = bus_attach_io_events(b);
|
||||
if (q < 0)
|
||||
return q;
|
||||
|
||||
q = bus_attach_inotify_event(b);
|
||||
if (q < 0)
|
||||
return q;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -34,5 +34,6 @@ int bus_socket_read_message(sd_bus *bus);
|
||||
|
||||
int bus_socket_process_opening(sd_bus *b);
|
||||
int bus_socket_process_authenticating(sd_bus *b);
|
||||
int bus_socket_process_watch_bind(sd_bus *b);
|
||||
|
||||
bool bus_socket_auth_needs_write(sd_bus *b);
|
||||
|
@ -48,25 +48,13 @@ struct sd_bus_track {
|
||||
LIST_FIELDS(sd_bus_track, tracks);
|
||||
};
|
||||
|
||||
#define MATCH_PREFIX \
|
||||
"type='signal'," \
|
||||
"sender='org.freedesktop.DBus'," \
|
||||
"path='/org/freedesktop/DBus'," \
|
||||
"interface='org.freedesktop.DBus'," \
|
||||
"member='NameOwnerChanged'," \
|
||||
"arg0='"
|
||||
|
||||
#define MATCH_SUFFIX \
|
||||
"'"
|
||||
|
||||
#define MATCH_FOR_NAME(name) \
|
||||
({ \
|
||||
char *_x; \
|
||||
size_t _l = strlen(name); \
|
||||
_x = alloca(STRLEN(MATCH_PREFIX)+_l+STRLEN(MATCH_SUFFIX)+1); \
|
||||
strcpy(stpcpy(stpcpy(_x, MATCH_PREFIX), name), MATCH_SUFFIX); \
|
||||
_x; \
|
||||
})
|
||||
#define MATCH_FOR_NAME(name) \
|
||||
strjoina("type='signal'," \
|
||||
"sender='org.freedesktop.DBus'," \
|
||||
"path='/org/freedesktop/DBus'," \
|
||||
"interface='org.freedesktop.DBus'," \
|
||||
"member='NameOwnerChanged'," \
|
||||
"arg0='", name, "'")
|
||||
|
||||
static struct track_item* track_item_free(struct track_item *i) {
|
||||
|
||||
@ -259,9 +247,7 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
|
||||
|
||||
bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */
|
||||
|
||||
track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */
|
||||
r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track);
|
||||
track->n_adding--;
|
||||
r = sd_bus_add_match_async(track->bus, &n->slot, match, on_name_owner_changed, NULL, track);
|
||||
if (r < 0) {
|
||||
bus_track_add_to_queue(track);
|
||||
return r;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -102,9 +102,9 @@ static int server_init(sd_bus **_bus) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
|
||||
r = sd_bus_match_signal(bus, NULL, NULL, NULL, "foo.bar", "Notify", match_callback, NULL);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to add match: %m");
|
||||
log_error_errno(r, "Failed to request match: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
239
src/libsystemd/sd-bus/test-bus-watch-bind.c
Normal file
239
src/libsystemd/sd-bus/test-bus-watch-bind.c
Normal file
@ -0,0 +1,239 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2017 Lennart Poettering
|
||||
|
||||
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/>.
|
||||
***/
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-event.h"
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "mkdir.h"
|
||||
#include "path-util.h"
|
||||
#include "random-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
static int method_foobar(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
log_info("Got Foobar() call.");
|
||||
|
||||
assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0) >= 0);
|
||||
return sd_bus_reply_method_return(m, NULL);
|
||||
}
|
||||
|
||||
static int method_exit(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
log_info("Got Exit() call");
|
||||
assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 1) >= 0);
|
||||
return sd_bus_reply_method_return(m, NULL);
|
||||
}
|
||||
|
||||
static const sd_bus_vtable vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD("Foobar", NULL, NULL, method_foobar, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("Exit", NULL, NULL, method_exit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
static void* thread_server(void *p) {
|
||||
_cleanup_free_ char *suffixed = NULL, *suffixed2 = NULL, *d = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
union sockaddr_union u = {
|
||||
.un.sun_family = AF_UNIX,
|
||||
};
|
||||
const char *path = p;
|
||||
|
||||
log_debug("Initializing server");
|
||||
|
||||
/* Let's play some games, by slowly creating the socket directory, and renaming it in the middle */
|
||||
(void) usleep(100 * USEC_PER_MSEC);
|
||||
|
||||
assert_se(mkdir_parents(path, 0755) >= 0);
|
||||
(void) usleep(100 * USEC_PER_MSEC);
|
||||
|
||||
d = dirname_malloc(path);
|
||||
assert_se(d);
|
||||
assert_se(asprintf(&suffixed, "%s.%" PRIx64, d, random_u64()) >= 0);
|
||||
assert_se(rename(d, suffixed) >= 0);
|
||||
(void) usleep(100 * USEC_PER_MSEC);
|
||||
|
||||
assert_se(asprintf(&suffixed2, "%s.%" PRIx64, d, random_u64()) >= 0);
|
||||
assert_se(symlink(suffixed2, d) >= 0);
|
||||
(void) usleep(100 * USEC_PER_MSEC);
|
||||
|
||||
assert_se(symlink(basename(suffixed), suffixed2) >= 0);
|
||||
(void) usleep(100 * USEC_PER_MSEC);
|
||||
|
||||
strncpy(u.un.sun_path, path, sizeof(u.un.sun_path));
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
|
||||
assert_se(fd >= 0);
|
||||
|
||||
assert_se(bind(fd, &u.sa, SOCKADDR_UN_LEN(u.un)) >= 0);
|
||||
usleep(100 * USEC_PER_MSEC);
|
||||
|
||||
assert_se(listen(fd, SOMAXCONN) >= 0);
|
||||
usleep(100 * USEC_PER_MSEC);
|
||||
|
||||
assert_se(touch(path) >= 0);
|
||||
usleep(100 * USEC_PER_MSEC);
|
||||
|
||||
log_debug("Initialized server");
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
sd_id128_t id;
|
||||
int bus_fd, code;
|
||||
|
||||
assert_se(sd_id128_randomize(&id) >= 0);
|
||||
|
||||
assert_se(sd_event_new(&event) >= 0);
|
||||
|
||||
bus_fd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
|
||||
assert_se(bus_fd >= 0);
|
||||
|
||||
log_debug("Accepted server connection");
|
||||
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_description(bus, "server") >= 0);
|
||||
assert_se(sd_bus_set_fd(bus, bus_fd, bus_fd) >= 0);
|
||||
assert_se(sd_bus_set_server(bus, true, id) >= 0);
|
||||
/* assert_se(sd_bus_set_anonymous(bus, true) >= 0); */
|
||||
|
||||
assert_se(sd_bus_attach_event(bus, event, 0) >= 0);
|
||||
|
||||
assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "foo.TestInterface", vtable, NULL) >= 0);
|
||||
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
assert_se(sd_event_loop(event) >= 0);
|
||||
|
||||
assert_se(sd_event_get_exit_code(event, &code) >= 0);
|
||||
|
||||
if (code > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
log_debug("Server done");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void* thread_client1(void *p) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
const char *path = p, *t;
|
||||
int r;
|
||||
|
||||
log_debug("Initializing client1");
|
||||
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_description(bus, "client1") >= 0);
|
||||
|
||||
t = strjoina("unix:path=", path);
|
||||
assert_se(sd_bus_set_address(bus, t) >= 0);
|
||||
assert_se(sd_bus_set_watch_bind(bus, true) >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
r = sd_bus_call_method(bus, "foo.bar", "/foo", "foo.TestInterface", "Foobar", &error, NULL, NULL);
|
||||
assert_se(r >= 0);
|
||||
|
||||
log_debug("Client1 done");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int client2_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
assert_se(sd_bus_message_is_method_error(m, NULL) == 0);
|
||||
assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0) >= 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* thread_client2(void *p) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
const char *path = p, *t;
|
||||
|
||||
log_debug("Initializing client2");
|
||||
|
||||
assert_se(sd_event_new(&event) >= 0);
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
assert_se(sd_bus_set_description(bus, "client2") >= 0);
|
||||
|
||||
t = strjoina("unix:path=", path);
|
||||
assert_se(sd_bus_set_address(bus, t) >= 0);
|
||||
assert_se(sd_bus_set_watch_bind(bus, true) >= 0);
|
||||
assert_se(sd_bus_attach_event(bus, event, 0) >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
assert_se(sd_bus_call_method_async(bus, NULL, "foo.bar", "/foo", "foo.TestInterface", "Foobar", client2_callback, NULL, NULL) >= 0);
|
||||
|
||||
assert_se(sd_event_loop(event) >= 0);
|
||||
|
||||
log_debug("Client2 done");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void request_exit(const char *path) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
const char *t;
|
||||
|
||||
assert_se(sd_bus_new(&bus) >= 0);
|
||||
|
||||
t = strjoina("unix:path=", path);
|
||||
assert_se(sd_bus_set_address(bus, t) >= 0);
|
||||
assert_se(sd_bus_set_watch_bind(bus, true) >= 0);
|
||||
assert_se(sd_bus_set_description(bus, "request-exit") >= 0);
|
||||
assert_se(sd_bus_start(bus) >= 0);
|
||||
|
||||
assert_se(sd_bus_call_method(bus, "foo.bar", "/foo", "foo.TestInterface", "Exit", NULL, NULL, NULL) >= 0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
_cleanup_(rm_rf_physical_and_freep) char *d = NULL;
|
||||
pthread_t server, client1, client2;
|
||||
char *path;
|
||||
|
||||
log_set_max_level(LOG_DEBUG);
|
||||
|
||||
/* We use /dev/shm here rather than /tmp, since some weird distros might set up /tmp as some weird fs that
|
||||
* doesn't support inotify properly. */
|
||||
assert_se(mkdtemp_malloc("/dev/shm/systemd-watch-bind-XXXXXX", &d) >= 0);
|
||||
|
||||
path = strjoina(d, "/this/is/a/socket");
|
||||
|
||||
assert_se(pthread_create(&server, NULL, thread_server, path) == 0);
|
||||
assert_se(pthread_create(&client1, NULL, thread_client1, path) == 0);
|
||||
assert_se(pthread_create(&client2, NULL, thread_client2, path) == 0);
|
||||
|
||||
assert_se(pthread_join(client1, NULL) == 0);
|
||||
assert_se(pthread_join(client2, NULL) == 0);
|
||||
|
||||
request_exit(path);
|
||||
|
||||
assert_se(pthread_join(server, NULL) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1061,10 +1061,15 @@ _public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) {
|
||||
}
|
||||
|
||||
_public_ int sd_login_monitor_flush(sd_login_monitor *m) {
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
|
||||
return flush_fd(MONITOR_TO_FD(m));
|
||||
r = flush_fd(MONITOR_TO_FD(m));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_login_monitor_get_fd(sd_login_monitor *m) {
|
||||
|
@ -268,8 +268,16 @@ _public_ int udev_queue_get_fd(struct udev_queue *udev_queue) {
|
||||
* Returns: the result of clearing the watch for queue changes.
|
||||
*/
|
||||
_public_ int udev_queue_flush(struct udev_queue *udev_queue) {
|
||||
int r;
|
||||
|
||||
assert(udev_queue);
|
||||
|
||||
if (udev_queue->fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return flush_fd(udev_queue->fd);
|
||||
r = flush_fd(udev_queue->fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -652,9 +652,9 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register object: %m");
|
||||
|
||||
r = sd_bus_request_name(bus, "org.freedesktop.locale1", 0);
|
||||
r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.locale1", 0, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register name: %m");
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = sd_bus_attach_event(bus, event, 0);
|
||||
if (r < 0)
|
||||
|
@ -288,13 +288,13 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
|
||||
return 0;
|
||||
|
||||
r = parse_uid(p, &uid);
|
||||
}
|
||||
if (r < 0)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
user = hashmap_get(m->users, UID_TO_PTR(uid));
|
||||
if (!user)
|
||||
return 0;
|
||||
user = hashmap_get(m->users, UID_TO_PTR(uid));
|
||||
if (!user)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*found = user;
|
||||
return 1;
|
||||
|
@ -658,7 +658,6 @@ static int manager_reserve_vt(Manager *m) {
|
||||
}
|
||||
|
||||
static int manager_connect_bus(Manager *m) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -696,65 +695,65 @@ static int manager_connect_bus(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add user enumerator: %m");
|
||||
|
||||
r = sd_bus_add_match(m->bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.systemd1.Manager',"
|
||||
"member='JobRemoved',"
|
||||
"path='/org/freedesktop/systemd1'",
|
||||
match_job_removed, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for JobRemoved: %m");
|
||||
|
||||
r = sd_bus_add_match(m->bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.systemd1.Manager',"
|
||||
"member='UnitRemoved',"
|
||||
"path='/org/freedesktop/systemd1'",
|
||||
match_unit_removed, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for UnitRemoved: %m");
|
||||
|
||||
r = sd_bus_add_match(m->bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.DBus.Properties',"
|
||||
"member='PropertiesChanged'",
|
||||
match_properties_changed, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for PropertiesChanged: %m");
|
||||
|
||||
r = sd_bus_add_match(m->bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.systemd1.Manager',"
|
||||
"member='Reloading',"
|
||||
"path='/org/freedesktop/systemd1'",
|
||||
match_reloading, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for Reloading: %m");
|
||||
|
||||
r = sd_bus_call_method(
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"JobRemoved",
|
||||
match_job_removed, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for JobRemoved: %m");
|
||||
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"UnitRemoved",
|
||||
match_unit_removed, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
|
||||
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
NULL,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged",
|
||||
match_properties_changed, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
|
||||
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"Reloading",
|
||||
match_reloading, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for Reloading: %m");
|
||||
|
||||
r = sd_bus_call_method_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"Subscribe",
|
||||
&error,
|
||||
NULL, NULL);
|
||||
if (r < 0) {
|
||||
log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_request_name(m->bus, "org.freedesktop.login1", 0);
|
||||
NULL, NULL,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register name: %m");
|
||||
return log_error_errno(r, "Failed to enable subscription: %m");
|
||||
|
||||
r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.login1", 0, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL);
|
||||
if (r < 0)
|
||||
|
@ -197,7 +197,7 @@ static int export_legacy_dbus_address(
|
||||
return PAM_SUCCESS;
|
||||
|
||||
s = mfree(s);
|
||||
if (asprintf(&s, UNIX_USER_BUS_ADDRESS_FMT, runtime) < 0)
|
||||
if (asprintf(&s, DEFAULT_USER_BUS_ADDRESS_FMT, runtime) < 0)
|
||||
goto error;
|
||||
|
||||
r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", s, 0);
|
||||
|
@ -1568,9 +1568,9 @@ static int login_machine(int argc, char *argv[], void *userdata) {
|
||||
"member='MachineRemoved',"
|
||||
"arg0='", machine, "'");
|
||||
|
||||
r = sd_bus_add_match(bus, &slot, match, on_machine_removed, &forward);
|
||||
r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, &forward);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add machine removal match: %m");
|
||||
return log_error_errno(r, "Failed to request machine removal match: %m");
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
@ -1643,9 +1643,9 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
|
||||
"member='MachineRemoved',"
|
||||
"arg0='", machine, "'");
|
||||
|
||||
r = sd_bus_add_match(bus, &slot, match, on_machine_removed, &forward);
|
||||
r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, &forward);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add machine removal match: %m");
|
||||
return log_error_errno(r, "Failed to request machine removal match: %m");
|
||||
|
||||
r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
@ -2087,28 +2087,27 @@ static int transfer_image_common(sd_bus *bus, sd_bus_message *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to attach bus to event loop: %m");
|
||||
|
||||
r = sd_bus_add_match(
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
&slot_job_removed,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.import1',"
|
||||
"interface='org.freedesktop.import1.Manager',"
|
||||
"member='TransferRemoved',"
|
||||
"path='/org/freedesktop/import1'",
|
||||
match_transfer_removed, &path);
|
||||
"org.freedesktop.import1",
|
||||
"/org/freedesktop/import1",
|
||||
"org.freedesktop.import1.Manager",
|
||||
"TransferRemoved",
|
||||
match_transfer_removed, NULL, &path);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to install match: %m");
|
||||
return log_error_errno(r, "Failed to request match: %m");
|
||||
|
||||
r = sd_bus_add_match(
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
&slot_log_message,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.import1',"
|
||||
"interface='org.freedesktop.import1.Transfer',"
|
||||
"member='LogMessage'",
|
||||
match_log_message, &path);
|
||||
"org.freedesktop.import1",
|
||||
NULL,
|
||||
"org.freedesktop.import1.Transfer",
|
||||
"LogMessage",
|
||||
match_log_message, NULL, &path);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to install match: %m");
|
||||
return log_error_errno(r, "Failed to request match: %m");
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, &reply);
|
||||
if (r < 0) {
|
||||
|
@ -186,7 +186,6 @@ int manager_enumerate_machines(Manager *m) {
|
||||
}
|
||||
|
||||
static int manager_connect_bus(Manager *m) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -216,70 +215,65 @@ static int manager_connect_bus(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add image enumerator: %m");
|
||||
|
||||
r = sd_bus_add_match(m->bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.systemd1.Manager',"
|
||||
"member='JobRemoved',"
|
||||
"path='/org/freedesktop/systemd1'",
|
||||
match_job_removed,
|
||||
m);
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"JobRemoved",
|
||||
match_job_removed, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for JobRemoved: %m");
|
||||
|
||||
r = sd_bus_add_match(m->bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.systemd1.Manager',"
|
||||
"member='UnitRemoved',"
|
||||
"path='/org/freedesktop/systemd1'",
|
||||
match_unit_removed,
|
||||
m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for UnitRemoved: %m");
|
||||
|
||||
r = sd_bus_add_match(m->bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.DBus.Properties',"
|
||||
"member='PropertiesChanged',"
|
||||
"arg0='org.freedesktop.systemd1.Unit'",
|
||||
match_properties_changed,
|
||||
m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for PropertiesChanged: %m");
|
||||
|
||||
r = sd_bus_add_match(m->bus,
|
||||
NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.systemd1.Manager',"
|
||||
"member='Reloading',"
|
||||
"path='/org/freedesktop/systemd1'",
|
||||
match_reloading,
|
||||
m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for Reloading: %m");
|
||||
|
||||
r = sd_bus_call_method(
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"UnitRemoved",
|
||||
match_unit_removed, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
|
||||
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
NULL,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged",
|
||||
match_properties_changed, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
|
||||
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"Reloading",
|
||||
match_reloading, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for Reloading: %m");
|
||||
|
||||
r = sd_bus_call_method_async(
|
||||
m->bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"Subscribe",
|
||||
&error,
|
||||
NULL, NULL);
|
||||
if (r < 0) {
|
||||
log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_request_name(m->bus, "org.freedesktop.machine1", 0);
|
||||
NULL, NULL,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register name: %m");
|
||||
return log_error_errno(r, "Failed to enable subscription: %m");
|
||||
|
||||
r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.machine1", 0, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = sd_bus_attach_event(m->bus, m->event, 0);
|
||||
if (r < 0)
|
||||
|
@ -153,7 +153,15 @@ static void netdev_free(NetDev *netdev) {
|
||||
condition_free_list(netdev->match_kernel_version);
|
||||
condition_free_list(netdev->match_arch);
|
||||
|
||||
if (NETDEV_VTABLE(netdev) &&
|
||||
/* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that
|
||||
* because we parse .netdev files twice: once to determine the kind (with a short, minimal NetDev structure
|
||||
* allocation, with no room for per-kind fields), and once to read the kind's properties (with a full,
|
||||
* comprehensive NetDev structure allocation with enough space for whatever the specific kind needs). Now, in
|
||||
* the first case we shouldn't try to destruct the per-kind NetDev fields on destruction, in the second case we
|
||||
* should. We use the state field to discern the two cases: it's _NETDEV_STATE_INVALID on the first "raw"
|
||||
* call. */
|
||||
if (netdev->state != _NETDEV_STATE_INVALID &&
|
||||
NETDEV_VTABLE(netdev) &&
|
||||
NETDEV_VTABLE(netdev)->done)
|
||||
NETDEV_VTABLE(netdev)->done(netdev);
|
||||
|
||||
@ -615,8 +623,8 @@ static int netdev_load_one(Manager *manager, const char *filename) {
|
||||
if (!file) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
else
|
||||
return -errno;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (null_or_empty_fd(fileno(file))) {
|
||||
@ -630,7 +638,7 @@ static int netdev_load_one(Manager *manager, const char *filename) {
|
||||
|
||||
netdev_raw->n_ref = 1;
|
||||
netdev_raw->kind = _NETDEV_KIND_INVALID;
|
||||
netdev_raw->state = _NETDEV_STATE_INVALID;
|
||||
netdev_raw->state = _NETDEV_STATE_INVALID; /* an invalid state means done() of the implementation won't be called on destruction */
|
||||
|
||||
dropin_dirname = strjoina(basename(filename), ".d");
|
||||
r = config_parse_many(filename, network_dirs, dropin_dirname,
|
||||
@ -669,7 +677,7 @@ static int netdev_load_one(Manager *manager, const char *filename) {
|
||||
netdev->n_ref = 1;
|
||||
netdev->manager = manager;
|
||||
netdev->kind = netdev_raw->kind;
|
||||
netdev->state = _NETDEV_STATE_INVALID;
|
||||
netdev->state = NETDEV_STATE_LOADING; /* we initialize the state here for the first time, so that done() will be called on destruction */
|
||||
|
||||
if (NETDEV_VTABLE(netdev)->init)
|
||||
NETDEV_VTABLE(netdev)->init(netdev);
|
||||
|
@ -65,6 +65,7 @@ typedef enum NetDevKind {
|
||||
} NetDevKind;
|
||||
|
||||
typedef enum NetDevState {
|
||||
NETDEV_STATE_LOADING,
|
||||
NETDEV_STATE_FAILED,
|
||||
NETDEV_STATE_CREATING,
|
||||
NETDEV_STATE_READY,
|
||||
@ -149,7 +150,9 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
|
||||
/* For casting a netdev into the various netdev kinds */
|
||||
#define DEFINE_NETDEV_CAST(UPPERCASE, MixedCase) \
|
||||
static inline MixedCase* UPPERCASE(NetDev *n) { \
|
||||
if (_unlikely_(!n || n->kind != NETDEV_KIND_##UPPERCASE)) \
|
||||
if (_unlikely_(!n || \
|
||||
n->kind != NETDEV_KIND_##UPPERCASE) || \
|
||||
n->state == _NETDEV_STATE_INVALID) \
|
||||
return NULL; \
|
||||
\
|
||||
return (MixedCase*) n; \
|
||||
|
@ -82,19 +82,6 @@ static int setup_default_address_pool(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
|
||||
assert(s);
|
||||
assert(m);
|
||||
|
||||
m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
|
||||
|
||||
manager_connect_bus(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_reset_all(Manager *m) {
|
||||
Link *link;
|
||||
Iterator i;
|
||||
@ -116,6 +103,7 @@ static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_b
|
||||
int b, r;
|
||||
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = sd_bus_message_read(message, "b", &b);
|
||||
if (r < 0) {
|
||||
@ -133,35 +121,32 @@ static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_b
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
|
||||
Manager *m = userdata;
|
||||
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
/* Did we get a timezone or transient hostname from DHCP while D-Bus wasn't up yet? */
|
||||
if (m->dynamic_hostname)
|
||||
(void) manager_set_hostname(m, m->dynamic_hostname);
|
||||
if (m->dynamic_timezone)
|
||||
(void) manager_set_timezone(m, m->dynamic_timezone);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_connect_bus(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = sd_bus_default_system(&m->bus);
|
||||
if (r < 0) {
|
||||
/* We failed to connect? Yuck, we must be in early
|
||||
* boot. Let's try in 5s again. */
|
||||
|
||||
log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
|
||||
|
||||
r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to install bus reconnect time event: %m");
|
||||
|
||||
if (m->bus)
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.login1',"
|
||||
"interface='org.freedesktop.login1.Manager',"
|
||||
"member='PrepareForSleep',"
|
||||
"path='/org/freedesktop/login1'",
|
||||
match_prepare_for_sleep,
|
||||
m);
|
||||
r = bus_open_system_watch_bind(&m->bus);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
|
||||
return log_error_errno(r, "Failed to connect to bus: %m");
|
||||
|
||||
r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m);
|
||||
if (r < 0)
|
||||
@ -183,25 +168,35 @@ int manager_connect_bus(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add network enumerator: %m");
|
||||
|
||||
r = sd_bus_request_name(m->bus, "org.freedesktop.network1", 0);
|
||||
r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.network1", 0, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register name: %m");
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = sd_bus_attach_event(m->bus, m->event, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to attach bus to event loop: %m");
|
||||
|
||||
/* Did we get a timezone or transient hostname from DHCP while D-Bus wasn't up yet? */
|
||||
if (m->dynamic_hostname) {
|
||||
r = manager_set_hostname(m, m->dynamic_hostname);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (m->dynamic_timezone) {
|
||||
r = manager_set_timezone(m, m->dynamic_timezone);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
&m->connected_slot,
|
||||
"org.freedesktop.DBus.Local",
|
||||
NULL,
|
||||
"org.freedesktop.DBus.Local",
|
||||
"Connected",
|
||||
on_connected, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match on Connected signal: %m");
|
||||
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
&m->prepare_for_sleep_slot,
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"PrepareForSleep",
|
||||
match_prepare_for_sleep, NULL, m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1321,6 +1316,7 @@ void manager_free(Manager *m) {
|
||||
|
||||
sd_bus_unref(m->bus);
|
||||
sd_bus_slot_unref(m->prepare_for_sleep_slot);
|
||||
sd_bus_slot_unref(m->connected_slot);
|
||||
sd_event_source_unref(m->bus_retry_event_source);
|
||||
|
||||
free(m->dynamic_timezone);
|
||||
@ -1595,12 +1591,12 @@ int manager_set_hostname(Manager *m, const char *hostname) {
|
||||
int r;
|
||||
|
||||
log_debug("Setting transient hostname: '%s'", strna(hostname));
|
||||
|
||||
if (free_and_strdup(&m->dynamic_hostname, hostname) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (!m->bus) {
|
||||
/* TODO: replace by assert when we can rely on kdbus */
|
||||
log_info("Not connected to system bus, ignoring transient hostname.");
|
||||
if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
|
||||
log_info("Not connected to system bus, not setting hostname.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1647,8 +1643,8 @@ int manager_set_timezone(Manager *m, const char *tz) {
|
||||
if (free_and_strdup(&m->dynamic_timezone, tz) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (!m->bus) {
|
||||
log_info("Not connected to system bus, ignoring timezone.");
|
||||
if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
|
||||
log_info("Not connected to system bus, not setting hostname.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ struct Manager {
|
||||
sd_event_source *bus_retry_event_source;
|
||||
sd_bus *bus;
|
||||
sd_bus_slot *prepare_for_sleep_slot;
|
||||
sd_bus_slot *connected_slot;
|
||||
struct udev *udev;
|
||||
struct udev_monitor *udev_monitor;
|
||||
sd_event_source *udev_event_source;
|
||||
|
@ -3622,14 +3622,16 @@ static int run(int master,
|
||||
* case PID 1 will send us a friendly RequestStop signal, when it is asked to terminate the
|
||||
* scope. Let's hook into that, and cleanly shut down the container, and print a friendly message. */
|
||||
|
||||
r = sd_bus_add_match(bus, NULL,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.systemd1.Scope',"
|
||||
"member='RequestStop'",
|
||||
on_request_stop, PID_TO_PTR(*pid));
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
NULL,
|
||||
"org.freedesktop.systemd1.Scope",
|
||||
"RequestStop",
|
||||
on_request_stop, NULL, PID_TO_PTR(*pid));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to install request stop match: %m");
|
||||
return log_error_errno(r, "Failed to request RequestStop match: %m");
|
||||
}
|
||||
|
||||
if (arg_register) {
|
||||
|
@ -1844,18 +1844,6 @@ static const sd_bus_vtable resolve_vtable[] = {
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
|
||||
Manager *m = userdata;
|
||||
|
||||
assert(s);
|
||||
assert(m);
|
||||
|
||||
m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
|
||||
|
||||
manager_connect_bus(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
|
||||
Manager *m = userdata;
|
||||
int b, r;
|
||||
@ -1886,20 +1874,9 @@ int manager_connect_bus(Manager *m) {
|
||||
if (m->bus)
|
||||
return 0;
|
||||
|
||||
r = sd_bus_default_system(&m->bus);
|
||||
if (r < 0) {
|
||||
/* We failed to connect? Yuck, we must be in early
|
||||
* boot. Let's try in 5s again. */
|
||||
|
||||
log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
|
||||
|
||||
r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to install bus reconnect time event: %m");
|
||||
|
||||
(void) sd_event_source_set_description(m->bus_retry_event_source, "bus-retry");
|
||||
return 0;
|
||||
}
|
||||
r = bus_open_system_watch_bind(&m->bus);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to connect to system bus: %m");
|
||||
|
||||
r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
|
||||
if (r < 0)
|
||||
@ -1921,24 +1898,26 @@ int manager_connect_bus(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register dnssd enumerator: %m");
|
||||
|
||||
r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
|
||||
r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register name: %m");
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = sd_bus_attach_event(m->bus, m->event, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to attach bus to event loop: %m");
|
||||
|
||||
r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.login1',"
|
||||
"interface='org.freedesktop.login1.Manager',"
|
||||
"member='PrepareForSleep',"
|
||||
"path='/org/freedesktop/login1'",
|
||||
match_prepare_for_sleep,
|
||||
m);
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
&m->prepare_for_sleep_slot,
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"PrepareForSleep",
|
||||
match_prepare_for_sleep,
|
||||
NULL,
|
||||
m);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
|
||||
log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1059,7 +1059,6 @@ static int start_transient_service(
|
||||
.inactive_enter_usec = USEC_INFINITY,
|
||||
};
|
||||
_cleanup_free_ char *path = NULL;
|
||||
const char *mt;
|
||||
|
||||
c.bus = sd_bus_ref(bus);
|
||||
|
||||
@ -1089,18 +1088,20 @@ static int start_transient_service(
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
mt = strjoina("type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"path='", path, "',"
|
||||
"interface='org.freedesktop.DBus.Properties',"
|
||||
"member='PropertiesChanged'");
|
||||
r = sd_bus_add_match(bus, &c.match, mt, on_properties_changed, &c);
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
&c.match,
|
||||
"org.freedesktop.systemd1",
|
||||
path,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged",
|
||||
on_properties_changed, NULL, &c);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add properties changed signal.");
|
||||
return log_error_errno(r, "Failed to request properties changed signal match: %m");
|
||||
|
||||
r = sd_bus_attach_event(bus, c.event, SD_EVENT_PRIORITY_NORMAL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to attach bus to event loop.");
|
||||
return log_error_errno(r, "Failed to attach bus to event loop: %m");
|
||||
|
||||
r = run_context_update(&c, path);
|
||||
if (r < 0)
|
||||
|
@ -316,7 +316,7 @@ int ask_password_tty(
|
||||
}
|
||||
|
||||
if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0)
|
||||
flush_fd(notify);
|
||||
(void) flush_fd(notify);
|
||||
|
||||
if (pollfd[POLL_TTY].revents == 0)
|
||||
continue;
|
||||
|
@ -1730,31 +1730,25 @@ int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
|
||||
/* When we are a bus client we match by sender. Direct
|
||||
* connections OTOH have no initialized sender field, and
|
||||
* hence we ignore the sender then */
|
||||
r = sd_bus_add_match(
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
&d->slot_job_removed,
|
||||
bus->bus_client ?
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.systemd1',"
|
||||
"interface='org.freedesktop.systemd1.Manager',"
|
||||
"member='JobRemoved',"
|
||||
"path='/org/freedesktop/systemd1'" :
|
||||
"type='signal',"
|
||||
"interface='org.freedesktop.systemd1.Manager',"
|
||||
"member='JobRemoved',"
|
||||
"path='/org/freedesktop/systemd1'",
|
||||
match_job_removed, d);
|
||||
bus->bus_client ? "org.freedesktop.systemd1" : NULL,
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"JobRemoved",
|
||||
match_job_removed, NULL, d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_add_match(
|
||||
r = sd_bus_match_signal_async(
|
||||
bus,
|
||||
&d->slot_disconnected,
|
||||
"type='signal',"
|
||||
"sender='org.freedesktop.DBus.Local',"
|
||||
"interface='org.freedesktop.DBus.Local',"
|
||||
"member='Disconnected'",
|
||||
match_disconnected, d);
|
||||
"org.freedesktop.DBus.Local",
|
||||
NULL,
|
||||
"org.freedesktop.DBus.Local",
|
||||
"Disconnected",
|
||||
match_disconnected, NULL, d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -68,7 +68,7 @@ static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_
|
||||
}
|
||||
|
||||
int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
|
||||
_cleanup_free_ char *match = NULL;
|
||||
const char *match;
|
||||
const char *unique;
|
||||
int r;
|
||||
|
||||
@ -85,23 +85,21 @@ int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = asprintf(&match,
|
||||
"sender='org.freedesktop.DBus',"
|
||||
"type='signal',"
|
||||
"interface='org.freedesktop.DBus',"
|
||||
"member='NameOwnerChanged',"
|
||||
"path='/org/freedesktop/DBus',"
|
||||
"arg0='%s',"
|
||||
"arg1='%s',"
|
||||
"arg2=''", name, unique);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
match = strjoina(
|
||||
"sender='org.freedesktop.DBus',"
|
||||
"type='signal',"
|
||||
"interface='org.freedesktop.DBus',"
|
||||
"member='NameOwnerChanged',"
|
||||
"path='/org/freedesktop/DBus',"
|
||||
"arg0='", name, "',",
|
||||
"arg1='", unique, "',",
|
||||
"arg2=''");
|
||||
|
||||
r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
|
||||
r = sd_bus_add_match_async(bus, NULL, match, name_owner_change_callback, NULL, e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_release_name(bus, name);
|
||||
r = sd_bus_release_name_async(bus, NULL, name, NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1600,3 +1598,54 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int bus_open_system_watch_bind(sd_bus **ret) {
|
||||
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
|
||||
|
||||
r = sd_bus_new(&bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
|
||||
if (!e)
|
||||
e = DEFAULT_SYSTEM_BUS_ADDRESS;
|
||||
|
||||
r = sd_bus_set_address(bus, e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_set_bus_client(bus, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_set_trusted(bus, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_set_watch_bind(bus, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_set_connected_signal(bus, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_start(bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = bus;
|
||||
bus = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -162,3 +162,5 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send
|
||||
int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
|
||||
|
||||
int bus_track_add_name_many(sd_bus_track *t, char **l);
|
||||
|
||||
int bus_open_system_watch_bind(sd_bus **ret);
|
||||
|
@ -2905,7 +2905,6 @@ static int start_unit_one(
|
||||
|
||||
if (wait_context) {
|
||||
_cleanup_free_ char *unit_path = NULL;
|
||||
const char* mt;
|
||||
|
||||
log_debug("Watching for property changes of %s", name);
|
||||
r = sd_bus_call_method(
|
||||
@ -2928,13 +2927,15 @@ static int start_unit_one(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add unit path %s to set: %m", unit_path);
|
||||
|
||||
mt = strjoina("type='signal',"
|
||||
"interface='org.freedesktop.DBus.Properties',"
|
||||
"path='", unit_path, "',"
|
||||
"member='PropertiesChanged'");
|
||||
r = sd_bus_add_match(bus, &wait_context->match, mt, on_properties_changed, wait_context);
|
||||
r = sd_bus_match_signal_async(bus,
|
||||
&wait_context->match,
|
||||
NULL,
|
||||
unit_path,
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged",
|
||||
on_properties_changed, NULL, wait_context);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for PropertiesChanged signal: %m");
|
||||
return log_error_errno(r, "Failed to request match for PropertiesChanged signal: %m");
|
||||
}
|
||||
|
||||
log_debug("%s manager for %s on %s, %s",
|
||||
@ -3150,22 +3151,21 @@ static int start_unit(int argc, char *argv[], void *userdata) {
|
||||
}
|
||||
|
||||
if (arg_wait) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
|
||||
wait_context.unit_paths = set_new(&string_hash_ops);
|
||||
if (!wait_context.unit_paths)
|
||||
return log_oom();
|
||||
|
||||
r = sd_bus_call_method(
|
||||
r = sd_bus_call_method_async(
|
||||
bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"Subscribe",
|
||||
&error,
|
||||
NULL, NULL);
|
||||
NULL, NULL,
|
||||
NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enable subscription: %s", bus_error_message(&error, r));
|
||||
return log_error_errno(r, "Failed to enable subscription: %m");
|
||||
r = sd_event_default(&wait_context.event);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate event loop: %m");
|
||||
|
@ -150,8 +150,14 @@ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b);
|
||||
int sd_bus_get_allow_interactive_authorization(sd_bus *bus);
|
||||
int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b);
|
||||
int sd_bus_get_exit_on_disconnect(sd_bus *bus);
|
||||
int sd_bus_set_watch_bind(sd_bus *bus, int b);
|
||||
int sd_bus_get_watch_bind(sd_bus *bus);
|
||||
int sd_bus_set_connected_signal(sd_bus *bus, int b);
|
||||
int sd_bus_get_connected_signal(sd_bus *bus);
|
||||
int sd_bus_set_sender(sd_bus *bus, const char *sender);
|
||||
int sd_bus_get_sender(sd_bus *bus, const char **ret);
|
||||
|
||||
int sd_bus_start(sd_bus *ret);
|
||||
int sd_bus_start(sd_bus *bus);
|
||||
|
||||
int sd_bus_try_close(sd_bus *bus);
|
||||
void sd_bus_close(sd_bus *bus);
|
||||
@ -163,6 +169,7 @@ sd_bus *sd_bus_flush_close_unref(sd_bus *bus);
|
||||
void sd_bus_default_flush_close(void);
|
||||
|
||||
int sd_bus_is_open(sd_bus *bus);
|
||||
int sd_bus_is_ready(sd_bus *bus);
|
||||
|
||||
int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id);
|
||||
int sd_bus_get_scope(sd_bus *bus, const char **scope);
|
||||
@ -193,6 +200,7 @@ sd_event *sd_bus_get_event(sd_bus *bus);
|
||||
|
||||
int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata);
|
||||
int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata);
|
||||
int sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata);
|
||||
int sd_bus_add_object(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_message_handler_t callback, void *userdata);
|
||||
int sd_bus_add_fallback(sd_bus *bus, sd_bus_slot **slot, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
|
||||
int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
|
||||
@ -267,6 +275,7 @@ int sd_bus_message_set_auto_start(sd_bus_message *m, int b);
|
||||
int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b);
|
||||
|
||||
int sd_bus_message_set_destination(sd_bus_message *m, const char *destination);
|
||||
int sd_bus_message_set_sender(sd_bus_message *m, const char *sender);
|
||||
int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority);
|
||||
|
||||
int sd_bus_message_append(sd_bus_message *m, const char *types, ...);
|
||||
@ -300,7 +309,9 @@ int sd_bus_message_rewind(sd_bus_message *m, int complete);
|
||||
|
||||
int sd_bus_get_unique_name(sd_bus *bus, const char **unique);
|
||||
int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags);
|
||||
int sd_bus_request_name_async(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, sd_bus_message_handler_t callback, void *userdata);
|
||||
int sd_bus_release_name(sd_bus *bus, const char *name);
|
||||
int sd_bus_release_name_async(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, sd_bus_message_handler_t callback, void *userdata);
|
||||
int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable); /* free the results */
|
||||
int sd_bus_get_name_creds(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds); /* unref the result! */
|
||||
int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine);
|
||||
@ -336,6 +347,9 @@ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *in
|
||||
int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds);
|
||||
int sd_bus_query_sender_privilege(sd_bus_message *call, int capability);
|
||||
|
||||
int sd_bus_match_signal(sd_bus *bus, sd_bus_slot **ret, const char *sender, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata);
|
||||
int sd_bus_match_signal_async(sd_bus *bus, sd_bus_slot **ret, const char *sender, const char *path, const char *interface, const char *member, sd_bus_message_handler_t match_callback, sd_bus_message_handler_t add_callback, void *userdata);
|
||||
|
||||
/* Credential handling */
|
||||
|
||||
int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t creds_mask);
|
||||
|
@ -762,6 +762,10 @@ tests += [
|
||||
[],
|
||||
[threads]],
|
||||
|
||||
[['src/libsystemd/sd-bus/test-bus-watch-bind.c'],
|
||||
[],
|
||||
[threads], '', 'timeout=120'],
|
||||
|
||||
[['src/libsystemd/sd-bus/test-bus-chat.c'],
|
||||
[],
|
||||
[threads]],
|
||||
|
@ -29,8 +29,8 @@
|
||||
#include "apparmor-util.h"
|
||||
#include "architecture.h"
|
||||
#include "audit-util.h"
|
||||
#include "condition.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "condition.h"
|
||||
#include "hostname-util.h"
|
||||
#include "id128-util.h"
|
||||
#include "ima-util.h"
|
||||
@ -187,12 +187,12 @@ static int test_condition_test_control_group_controller(void) {
|
||||
/* Multiple valid controllers at the same time */
|
||||
assert_se(cg_mask_to_string(system_mask, &controller_name) >= 0);
|
||||
|
||||
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, controller_name, false, false);
|
||||
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, false);
|
||||
assert_se(condition);
|
||||
assert_se(condition_test(condition));
|
||||
condition_free(condition);
|
||||
|
||||
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, controller_name, false, true);
|
||||
condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, true);
|
||||
assert_se(condition);
|
||||
assert_se(!condition_test(condition));
|
||||
condition_free(condition);
|
||||
|
@ -388,6 +388,92 @@ static void test_access_fd(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void test_touch_file(void) {
|
||||
uid_t test_uid, test_gid;
|
||||
_cleanup_(rm_rf_physical_and_freep) char *p = NULL;
|
||||
struct stat st;
|
||||
const char *a;
|
||||
usec_t test_mtime;
|
||||
|
||||
test_uid = geteuid() == 0 ? 65534 : getuid();
|
||||
test_gid = geteuid() == 0 ? 65534 : getgid();
|
||||
|
||||
test_mtime = usec_sub_unsigned(now(CLOCK_REALTIME), USEC_PER_WEEK);
|
||||
|
||||
assert_se(mkdtemp_malloc("/dev/shm/touch-file-XXXXXX", &p) >= 0);
|
||||
|
||||
a = strjoina(p, "/regular");
|
||||
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
|
||||
assert_se(lstat(a, &st) >= 0);
|
||||
assert_se(st.st_uid == test_uid);
|
||||
assert_se(st.st_gid == test_gid);
|
||||
assert_se(S_ISREG(st.st_mode));
|
||||
assert_se((st.st_mode & 0777) == 0640);
|
||||
assert_se(timespec_load(&st.st_mtim) == test_mtime);
|
||||
|
||||
a = strjoina(p, "/dir");
|
||||
assert_se(mkdir(a, 0775) >= 0);
|
||||
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
|
||||
assert_se(lstat(a, &st) >= 0);
|
||||
assert_se(st.st_uid == test_uid);
|
||||
assert_se(st.st_gid == test_gid);
|
||||
assert_se(S_ISDIR(st.st_mode));
|
||||
assert_se((st.st_mode & 0777) == 0640);
|
||||
assert_se(timespec_load(&st.st_mtim) == test_mtime);
|
||||
|
||||
a = strjoina(p, "/fifo");
|
||||
assert_se(mkfifo(a, 0775) >= 0);
|
||||
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
|
||||
assert_se(lstat(a, &st) >= 0);
|
||||
assert_se(st.st_uid == test_uid);
|
||||
assert_se(st.st_gid == test_gid);
|
||||
assert_se(S_ISFIFO(st.st_mode));
|
||||
assert_se((st.st_mode & 0777) == 0640);
|
||||
assert_se(timespec_load(&st.st_mtim) == test_mtime);
|
||||
|
||||
a = strjoina(p, "/sock");
|
||||
assert_se(mknod(a, 0775 | S_IFSOCK, 0) >= 0);
|
||||
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
|
||||
assert_se(lstat(a, &st) >= 0);
|
||||
assert_se(st.st_uid == test_uid);
|
||||
assert_se(st.st_gid == test_gid);
|
||||
assert_se(S_ISSOCK(st.st_mode));
|
||||
assert_se((st.st_mode & 0777) == 0640);
|
||||
assert_se(timespec_load(&st.st_mtim) == test_mtime);
|
||||
|
||||
if (geteuid() == 0) {
|
||||
a = strjoina(p, "/cdev");
|
||||
assert_se(mknod(a, 0775 | S_IFCHR, makedev(0, 0)) >= 0);
|
||||
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
|
||||
assert_se(lstat(a, &st) >= 0);
|
||||
assert_se(st.st_uid == test_uid);
|
||||
assert_se(st.st_gid == test_gid);
|
||||
assert_se(S_ISCHR(st.st_mode));
|
||||
assert_se((st.st_mode & 0777) == 0640);
|
||||
assert_se(timespec_load(&st.st_mtim) == test_mtime);
|
||||
|
||||
a = strjoina(p, "/bdev");
|
||||
assert_se(mknod(a, 0775 | S_IFBLK, makedev(0, 0)) >= 0);
|
||||
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
|
||||
assert_se(lstat(a, &st) >= 0);
|
||||
assert_se(st.st_uid == test_uid);
|
||||
assert_se(st.st_gid == test_gid);
|
||||
assert_se(S_ISBLK(st.st_mode));
|
||||
assert_se((st.st_mode & 0777) == 0640);
|
||||
assert_se(timespec_load(&st.st_mtim) == test_mtime);
|
||||
}
|
||||
|
||||
a = strjoina(p, "/lnk");
|
||||
assert_se(symlink("target", a) >= 0);
|
||||
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
|
||||
assert_se(lstat(a, &st) >= 0);
|
||||
assert_se(st.st_uid == test_uid);
|
||||
assert_se(st.st_gid == test_gid);
|
||||
assert_se(S_ISLNK(st.st_mode));
|
||||
assert_se((st.st_mode & 0777) == 0640);
|
||||
assert_se(timespec_load(&st.st_mtim) == test_mtime);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
test_unlink_noerrno();
|
||||
test_get_files_in_directory();
|
||||
@ -396,6 +482,7 @@ int main(int argc, char *argv[]) {
|
||||
test_chase_symlinks();
|
||||
test_dot_or_dot_dot();
|
||||
test_access_fd();
|
||||
test_touch_file();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -675,9 +675,9 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register object: %m");
|
||||
|
||||
r = sd_bus_request_name(bus, "org.freedesktop.timedate1", 0);
|
||||
r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.timedate1", 0, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register name: %m");
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = sd_bus_attach_event(bus, event, 0);
|
||||
if (r < 0)
|
||||
|
@ -159,7 +159,7 @@ static int ask_password_plymouth(
|
||||
}
|
||||
|
||||
if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0)
|
||||
flush_fd(notify);
|
||||
(void) flush_fd(notify);
|
||||
|
||||
if (pollfd[POLL_SOCKET].revents == 0)
|
||||
continue;
|
||||
|
11
tools/meson-check-api-docs.sh
Normal file
11
tools/meson-check-api-docs.sh
Normal file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
for symbol in `nm -g --defined-only "$@" | grep " T " | cut -d" " -f3 | sort -u` ; do
|
||||
if test -f ${MESON_BUILD_ROOT}/man/$symbol.3 ; then
|
||||
echo "✓ Symbol $symbol() is documented."
|
||||
else
|
||||
printf " \x1b[1;31mSymbol $symbol() lacks documentation.\x1b[0m\n"
|
||||
fi
|
||||
done
|
Loading…
Reference in New Issue
Block a user