mirror of
https://github.com/systemd/systemd.git
synced 2025-03-14 04:58:28 +03:00
Merge pull request #12351 from keszybz/sd-bus-add-symbol
Add symbol to tell the linker that new libsystemd version is needed
This commit is contained in:
commit
aba5472979
@ -140,6 +140,16 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--xml-interface</option></term>
|
||||
|
||||
<listitem>
|
||||
<para>When used with the <command>introspect</command> call, dump the XML description received from
|
||||
the D-Bus <constant>org.freedesktop.DBus.Introspectable.Introspect</constant> call instead of the
|
||||
normal output.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--json=</option><replaceable>MODE</replaceable></term>
|
||||
|
||||
|
@ -115,6 +115,21 @@ manpages = [
|
||||
'sd_bus_match_signal',
|
||||
'sd_bus_match_signal_async'],
|
||||
''],
|
||||
['sd_bus_add_object_vtable',
|
||||
'3',
|
||||
['SD_BUS_METHOD',
|
||||
'SD_BUS_METHOD_WITH_NAMES',
|
||||
'SD_BUS_METHOD_WITH_NAMES_OFFSET',
|
||||
'SD_BUS_METHOD_WITH_OFFSET',
|
||||
'SD_BUS_PARAM',
|
||||
'SD_BUS_PROPERTY',
|
||||
'SD_BUS_SIGNAL',
|
||||
'SD_BUS_SIGNAL_WITH_NAMES',
|
||||
'SD_BUS_VTABLE_END',
|
||||
'SD_BUS_VTABLE_START',
|
||||
'SD_BUS_WRITABLE_PROPERTY',
|
||||
'sd_bus_add_fallback_vtable'],
|
||||
''],
|
||||
['sd_bus_attach_event', '3', ['sd_bus_detach_event', 'sd_bus_get_event'], ''],
|
||||
['sd_bus_close', '3', ['sd_bus_flush'], ''],
|
||||
['sd_bus_creds_get_pid',
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
<para>See
|
||||
<literallayout><citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_add_object_vtable</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_attach_event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_creds_get_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_creds_new_from_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
|
473
man/sd_bus_add_object_vtable.xml
Normal file
473
man/sd_bus_add_object_vtable.xml
Normal file
@ -0,0 +1,473 @@
|
||||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
|
||||
|
||||
<refentry id="sd_bus_add_object_vtable"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
<title>sd_bus_add_object_vtable</title>
|
||||
<productname>systemd</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>sd_bus_add_object_vtable</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_bus_add_object_vtable</refname>
|
||||
<refname>sd_bus_add_fallback_vtable</refname>
|
||||
<refname>SD_BUS_VTABLE_START</refname>
|
||||
<refname>SD_BUS_VTABLE_END</refname>
|
||||
<refname>SD_BUS_METHOD_WITH_NAMES_OFFSET</refname>
|
||||
<refname>SD_BUS_METHOD_WITH_NAMES</refname>
|
||||
<refname>SD_BUS_METHOD_WITH_OFFSET</refname>
|
||||
<refname>SD_BUS_METHOD</refname>
|
||||
<refname>SD_BUS_SIGNAL_WITH_NAMES</refname>
|
||||
<refname>SD_BUS_SIGNAL</refname>
|
||||
<refname>SD_BUS_WRITABLE_PROPERTY</refname>
|
||||
<refname>SD_BUS_PROPERTY</refname>
|
||||
<refname>SD_BUS_PARAM</refname>
|
||||
|
||||
<refpurpose>Declare properties and methods for a D-Bus path</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus-vtable.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>typedef int (*<function>sd_bus_property_get_t</function>)</funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>path</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>interface</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>property</parameter></paramdef>
|
||||
<paramdef>sd_bus_message *<parameter>reply</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
<paramdef>sd_bus_error *<parameter>ret_error</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>typedef int (*<function>sd_bus_property_set_t</function>)</funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>path</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>interface</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>property</parameter></paramdef>
|
||||
<paramdef>sd_bus_message *<parameter>value</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
<paramdef>sd_bus_error *<parameter>ret_error</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>typedef int (*<function>sd_bus_object_find_t</function>)</funcdef>
|
||||
<paramdef>const char *<parameter>path</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>interface</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
<paramdef>void **<parameter>ret_found</parameter></paramdef>
|
||||
<paramdef>sd_bus_error *<parameter>ret_error</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_add_object_vtable</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>path</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>interface</parameter></paramdef>
|
||||
<paramdef>const sd_bus_vtable *<parameter>vtable</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_add_fallback_vtable</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>sd_bus_slot **<parameter>slot</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>prefix</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>interface</parameter></paramdef>
|
||||
<paramdef>const sd_bus_vtable *<parameter>vtable</parameter></paramdef>
|
||||
<paramdef>sd_bus_object_find_t <parameter>find</parameter></paramdef>
|
||||
<paramdef>void *<parameter>userdata</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<para>
|
||||
<constant>SD_BUS_VTABLE_START(<replaceable>flags</replaceable>)</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_VTABLE_END</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_METHOD_WITH_NAMES_OFFSET(
|
||||
<replaceable>member</replaceable>,
|
||||
<replaceable>signature</replaceable>,
|
||||
<replaceable>in_names</replaceable>,
|
||||
<replaceable>result</replaceable>,
|
||||
<replaceable>out_names</replaceable>,
|
||||
<replaceable>handler</replaceable>,
|
||||
<replaceable>offset</replaceable>,
|
||||
<replaceable>flags</replaceable>)
|
||||
</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_METHOD_WITH_NAMES(
|
||||
<replaceable>member</replaceable>,
|
||||
<replaceable>signature</replaceable>,
|
||||
<replaceable>in_names</replaceable>,
|
||||
<replaceable>result</replaceable>,
|
||||
<replaceable>out_names</replaceable>,
|
||||
<replaceable>handler</replaceable>,
|
||||
<replaceable>flags</replaceable>)
|
||||
</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_METHOD_WITH_OFFSET(
|
||||
<replaceable>member</replaceable>,
|
||||
<replaceable>signature</replaceable>,
|
||||
<replaceable>result</replaceable>,
|
||||
<replaceable>handler</replaceable>,
|
||||
<replaceable>offset</replaceable>,
|
||||
<replaceable>flags</replaceable>)
|
||||
</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_METHOD(
|
||||
<replaceable>member</replaceable>,
|
||||
<replaceable>signature</replaceable>,
|
||||
<replaceable>result</replaceable>,
|
||||
<replaceable>handler</replaceable>,
|
||||
<replaceable>flags</replaceable>)
|
||||
</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_SIGNAL_WITH_NAMES(
|
||||
<replaceable>member</replaceable>,
|
||||
<replaceable>signature</replaceable>,
|
||||
<replaceable>names</replaceable>,
|
||||
<replaceable>flags</replaceable>)
|
||||
</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_SIGNAL(
|
||||
<replaceable>member</replaceable>,
|
||||
<replaceable>signature</replaceable>,
|
||||
<replaceable>flags</replaceable>)
|
||||
</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_WRITABLE_PROPERTY(
|
||||
<replaceable>member</replaceable>,
|
||||
<replaceable>signature</replaceable>,
|
||||
<replaceable>get</replaceable>,
|
||||
<replaceable>set</replaceable>,
|
||||
<replaceable>offset</replaceable>,
|
||||
<replaceable>flags</replaceable>)
|
||||
</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_PROPERTY(
|
||||
<replaceable>member</replaceable>,
|
||||
<replaceable>signature</replaceable>,
|
||||
<replaceable>get</replaceable>,
|
||||
<replaceable>offset</replaceable>,
|
||||
<replaceable>flags</replaceable>)
|
||||
</constant>
|
||||
</para>
|
||||
<para>
|
||||
<constant>SD_BUS_PARAM(<replaceable>name</replaceable>)</constant>
|
||||
</para>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_bus_add_object_vtable()</function> is used to declare attributes for the path object
|
||||
path <parameter>path</parameter> connected to the bus connection <parameter>bus</parameter> under the
|
||||
interface <parameter>interface</parameter>. The table <parameter>vtable</parameter> may contain property
|
||||
declarations using <constant>SD_BUS_PROPERTY()</constant> or
|
||||
<constant>SD_BUS_WRITABLE_PROPERTY()</constant>, method declarations using
|
||||
<constant>SD_BUS_METHOD()</constant>, <constant>SD_BUS_METHOD_WITH_NAMES()</constant>,
|
||||
<constant>SD_BUS_METHOD_WITH_OFFSET()</constant>, or
|
||||
<constant>SD_BUS_METHOD_WITH_NAMES_OFFSET()</constant>, and signal declarations using
|
||||
<constant>SD_BUS_SIGNAL_WITH_NAMES()</constant> or <constant>SD_BUS_SIGNAL()</constant>, see below. The
|
||||
<replaceable>userdata</replaceable> parameter contains a pointer that will be passed to various callback
|
||||
functions. It may be specified as <constant>NULL</constant> if no value is necessary.</para>
|
||||
|
||||
<para><function>sd_bus_add_object_vtable()</function> is similar to
|
||||
<function>sd_bus_add_object_vtable()</function>, but is used to register "fallback" attributes. When
|
||||
looking for an attribute declaration, bus object paths registered with
|
||||
<function>sd_bus_add_object_vtable()</function> are checked first. If no match is found, the fallback
|
||||
vtables are checked for each prefix of the bus object path, i.e. with the last slash-separated components
|
||||
successively removed. This allows the vtable to be used for an arbitrary number of dynamically created
|
||||
objects.</para>
|
||||
|
||||
<para>Parameter <replaceable>find</replaceable> is a function which is used to locate the target object
|
||||
based on the bus object path <replaceable>path</replaceable>. It must return <constant>1</constant> and
|
||||
set the <parameter>ret_found</parameter> output parameter if the object is found, return
|
||||
<constant>0</constant> if the object was not found, and return a negative errno-style error code or
|
||||
initialize the error structure <replaceable>ret_error</replaceable> on error. The pointer passed in
|
||||
<parameter>ret_found</parameter> will be used as the <parameter>userdata</parameter> parameter for the
|
||||
callback functions (offset by the <parameter>offset</parameter> offsets as specified in the vtable
|
||||
entries).</para>
|
||||
|
||||
<para>For both functions, a match slot is created internally. If the output parameter
|
||||
<replaceable>slot</replaceable> is <constant>NULL</constant>, a "floating" slot object is created, see
|
||||
<citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
Otherwise, a pointer to the slot object is returned. In that case, the reference to the slot object
|
||||
should be dropped when the vtable is not needed anymore, see
|
||||
<citerefentry><refentrytitle>sd_bus_slot_unref</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
<refsect2>
|
||||
<title>The <structname>sd_bus_vtable</structname> array</title>
|
||||
|
||||
<para>The array consists of the structures of type <structname>sd_bus_vtable</structname>, but it
|
||||
should never be filled in manually, but through one of the following macros:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_VTABLE_START()</constant></term>
|
||||
<term><constant>SD_BUS_VTABLE_END</constant></term>
|
||||
|
||||
<listitem><para>Those must always be the first and last element.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_METHOD_WITH_NAMES_OFFSET()</constant></term>
|
||||
<term><constant>SD_BUS_METHOD_WITH_NAMES()</constant></term>
|
||||
<term><constant>SD_BUS_METHOD_WITH_OFFSET()</constant></term>
|
||||
<term><constant>SD_BUS_METHOD()</constant></term>
|
||||
|
||||
<listitem><para>Declare a D-Bus method with the name <replaceable>member</replaceable>, parameter
|
||||
signature <replaceable>signature</replaceable>, result signature <replaceable>result</replaceable>.
|
||||
Parameters <replaceable>in_names</replaceable> and <replaceable>out_names</replaceable> specify the
|
||||
argument names of the input and output arguments in the function signature. The handler function
|
||||
<replaceable>handler</replaceable> must be of type <function>sd_bus_message_handler_t</function>.
|
||||
It will be called to handle the incoming messages that call this method. It receives a pointer that
|
||||
is the <replaceable>userdata</replaceable> parameter passed to the registration function offset by
|
||||
<replaceable>offset</replaceable> bytes. This may be used to pass pointers to different fields in
|
||||
the same data structure to different methods in the same
|
||||
vtable. <replaceable>in_names</replaceable> and <replaceable>out_names</replaceable> should be
|
||||
created using the <constant>SD_BUS_PARAM()</constant> macro, see below. Parameter
|
||||
<replaceable>flags</replaceable> is a combination of flags, see below.</para>
|
||||
|
||||
<para><constant>SD_BUS_METHOD_WITH_NAMES()</constant>,
|
||||
<constant>SD_BUS_METHOD_WITH_OFFSET()</constant>, and <constant>SD_BUS_METHOD()</constant> are
|
||||
variants which specify zero offset (<replaceable>userdata</replaceable> parameter is passed with
|
||||
no change), leave the names unset (i.e. no parameter names), or both.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_SIGNAL_WITH_NAMES()</constant></term>
|
||||
<term><constant>SD_BUS_SIGNAL()</constant></term>
|
||||
|
||||
<listitem><para>Declare a D-Bus signal with the name <replaceable>member</replaceable>,
|
||||
parameter signature <replaceable>signature</replaceable>, and argument names
|
||||
<replaceable>names</replaceable>. <replaceable>names</replaceable> should be
|
||||
created using the <constant>SD_BUS_PARAM()</constant> macro, see below.
|
||||
Parameter <replaceable>flags</replaceable> is a combination of flags, see below.
|
||||
</para>
|
||||
|
||||
<para>Equivalent to <constant>SD_BUS_SIGNAL_WITH_NAMES()</constant> with the
|
||||
<replaceable>names</replaceable> paramater unset (i.e. no parameter names).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_WRITABLE_PROPERTY()</constant></term>
|
||||
<term><constant>SD_BUS_PROPERTY()</constant></term>
|
||||
|
||||
<listitem><para>Declare a D-Bus property with the name <replaceable>member</replaceable> and value
|
||||
signature <replaceable>signature</replaceable>. Parameters <replaceable>get</replaceable> and
|
||||
<replaceable>set</replaceable> are the getter and setter methods. They are called with a pointer
|
||||
that is the <replaceable>userdata</replaceable> parameter passed to the registration function
|
||||
offset by <replaceable>offset</replaceable> bytes. This may be used pass pointers to different
|
||||
fields in the same data structure to different setters and getters in the same vtable. Parameter
|
||||
<replaceable>flags</replaceable> is a combination of flags, see below.</para>
|
||||
|
||||
<para>The setter and getter methods may be omitted (specified as <constant>NULL</constant>), if the
|
||||
property has one of the basic types or <literal>as</literal> in case of read-only properties. In
|
||||
those cases, the <replaceable>userdata</replaceable> and <replaceable>offset</replaceable>
|
||||
parameters must together point to valid variable of the corresponding type. A default setter and
|
||||
getters will be provided, which simply copy the argument between this variable and the message.
|
||||
</para>
|
||||
|
||||
<para><constant>SD_BUS_PROPERTY()</constant> is used to define a read-only property.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_PARAM()</constant></term>
|
||||
<listitem><para>Parameter names should be wrapped in this macro, see the example below.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Flags</title>
|
||||
|
||||
<para>The <replaceable>flags</replaceable> parameter is used to specify a combination of
|
||||
<ulink url="https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format">D-Bus annotations</ulink>.
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_VTABLE_DEPRECATED</constant></term>
|
||||
|
||||
<listitem><para>Mark this vtable entry as deprecated using the
|
||||
<constant>org.freedesktop.DBus.Deprecated</constant> annotation in introspection data. If
|
||||
specified for <constant>SD_BUS_VTABLE_START()</constant>, the annotation is applied to the
|
||||
enclosing interface.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_VTABLE_HIDDEN</constant></term>
|
||||
|
||||
<listitem><para>Make this vtable entry hidden. It will not be shown in introspection data. If
|
||||
specified for <constant>SD_BUS_VTABLE_START()</constant>, all entries in the array are hidden.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_VTABLE_UNPRIVILEGED</constant></term>
|
||||
|
||||
<listitem><para>Mark this vtable entry as unprivileged. If not specified, the
|
||||
<constant>org.freedesktop.systemd1.Privileged</constant> annotation with value
|
||||
<literal>true</literal> will be shown in introspection data.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_VTABLE_METHOD_NO_REPLY</constant></term>
|
||||
|
||||
<listitem><para>Mark his vtable entry as a method that will not return a reply using the
|
||||
<constant>org.freedesktop.DBus.Method.NoReply</constant> annotation in introspection data.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_VTABLE_CONST</constant></term>
|
||||
<term><constant>SD_BUS_VTABLE_EMITS_CHANGE</constant></term>
|
||||
<term><constant>SD_BUS_VTABLE_EMITS_INVALIDATION</constant></term>
|
||||
|
||||
<listitem><para>Those three flags correspond to different values of the
|
||||
<constant>org.freedesktop.DBus.Property.EmitsChangedSignal</constant> annotation, which specifies
|
||||
whether the <constant>org.freedesktop.DBus.Properties.PropertiesChanged</constant> signal is
|
||||
emitted whenever the property changes. <constant>SD_BUS_VTABLE_CONST</constant> corresponds to
|
||||
<constant>const</constant> and means that the property never changes during the lifetime of the
|
||||
object it belongs to, so no signal needs to be emitted.
|
||||
<constant>SD_BUS_VTABLE_EMITS_CHANGE</constant> corresponds to <constant>true</constant> and means
|
||||
that the signal is emitted. <constant>SD_BUS_VTABLE_EMITS_INVALIDATION</constant> corresponds to
|
||||
<constant>invalides</constant> and means that the signal is emitted, but the value is not included
|
||||
in the signal.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>SD_BUS_VTABLE_PROPERTY_EXPLICIT</constant></term>
|
||||
|
||||
<listitem><para>Mark this vtable property entry as requiring explicit request to for the value to
|
||||
be shown (generally because the value is large or slow to calculate). This entry cannot be combined
|
||||
with <constant>SD_BUS_VTABLE_EMITS_CHANGE</constant>, and will not be shown in property listings by
|
||||
default (e.g. <command>busctl introspect</command>). This corresponds to the
|
||||
<constant>org.freedesktop.systemd1.Explicit</constant> annotation in introspection data.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
|
||||
<example>
|
||||
<title>Create a simple listener on the bus</title>
|
||||
|
||||
<programlisting><xi:include href="vtable-example.c" parse="text" /></programlisting>
|
||||
|
||||
<para>This creates a simple client on the bus (the user bus, when run as normal user).
|
||||
We may use the D-Bus <constant>org.freedesktop.DBus.Introspectable.Introspect</constant>
|
||||
call to acquire the XML description of the interface:</para>
|
||||
|
||||
<programlisting><xi:include href="vtable-example.xml" parse="text" /></programlisting>
|
||||
</example>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>On success, <function>sd_bus_add_object_vtable</function> and
|
||||
<function>sd_bus_add_fallback_vtable</function> calls return 0 or a positive integer. On failure, they
|
||||
return a negative errno-style error code.</para>
|
||||
|
||||
<refsect2>
|
||||
<title>Errors</title>
|
||||
|
||||
<para>Returned errors may indicate the following problems:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>-EINVAL</constant></term>
|
||||
|
||||
<listitem><para>One of the required parameters is <constant>NULL</constant> or invalid. A reserved
|
||||
D-Bus interface was passed as the <replaceable>interface</replaceable> parameter.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-ENOPKG</constant></term>
|
||||
|
||||
<listitem><para>The bus cannot be resolved.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-ECHILD</constant></term>
|
||||
|
||||
<listitem><para>The bus was created in a different process.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-ENOMEM</constant></term>
|
||||
|
||||
<listitem><para>Memory allocation failed.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-EPROTOTYPE</constant></term>
|
||||
|
||||
<listitem><para><function>sd_bus_add_object_vtable</function> and
|
||||
<function>sd_bus_add_fallback_vtable</function> have been both called
|
||||
for the same bus object path, which is not allowed.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><constant>-EEXIST</constant></term>
|
||||
|
||||
<listitem><para>This vtable has already been registered for this
|
||||
<replaceable>interface</replaceable> and <replaceable>path</replaceable>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<xi:include href="libsystemd-pkgconfig.xml" />
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
|
||||
<para>
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>busctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
</refentry>
|
70
man/vtable-example.c
Normal file
70
man/vtable-example.c
Normal file
@ -0,0 +1,70 @@
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
|
||||
#define _cleanup_(f) __attribute__((cleanup(f)))
|
||||
|
||||
typedef struct object {
|
||||
char *name;
|
||||
uint32_t number;
|
||||
} object;
|
||||
|
||||
static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
printf("Got called with userdata=%p\n", userdata);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const sd_bus_vtable vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD(
|
||||
"Method1", "s", "s", method, 0),
|
||||
SD_BUS_METHOD_WITH_NAMES_OFFSET(
|
||||
"Method2",
|
||||
"so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
|
||||
"s", SD_BUS_PARAM(returnstring),
|
||||
method, offsetof(object, number),
|
||||
SD_BUS_VTABLE_DEPRECATED),
|
||||
SD_BUS_WRITABLE_PROPERTY(
|
||||
"AutomaticStringProperty", "s", NULL, NULL,
|
||||
offsetof(object, name),
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_WRITABLE_PROPERTY(
|
||||
"AutomaticIntegerProperty", "u", NULL, NULL,
|
||||
offsetof(object, number),
|
||||
SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
#define check(x) ({ \
|
||||
int r = x; \
|
||||
errno = r < 0 ? -r : 0; \
|
||||
printf(#x ": %m\n"); \
|
||||
if (r < 0) \
|
||||
return EXIT_FAILURE; \
|
||||
})
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
|
||||
sd_bus_default(&bus);
|
||||
|
||||
object object = { .number = 666 };
|
||||
check((object.name = strdup("name")) != NULL);
|
||||
|
||||
check(sd_bus_add_object_vtable(bus, NULL, "/object",
|
||||
"org.freedesktop.systemd.VtableExample",
|
||||
vtable,
|
||||
&object));
|
||||
|
||||
while (true) {
|
||||
check(sd_bus_wait(bus, UINT64_MAX));
|
||||
check(sd_bus_process(bus, NULL));
|
||||
}
|
||||
|
||||
free(object.name);
|
||||
|
||||
return 0;
|
||||
}
|
54
man/vtable-example.xml
Normal file
54
man/vtable-example.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.freedesktop.DBus.Peer">
|
||||
<method name="Ping"/>
|
||||
<method name="GetMachineId">
|
||||
<arg type="s" name="machine_uuid" direction="out"/>
|
||||
</method>
|
||||
</interface>
|
||||
<interface name="org.freedesktop.DBus.Introspectable">
|
||||
<method name="Introspect">
|
||||
<arg name="data" type="s" direction="out"/>
|
||||
</method>
|
||||
</interface>
|
||||
<interface name="org.freedesktop.DBus.Properties">
|
||||
<method name="Get">
|
||||
<arg name="interface" direction="in" type="s"/>
|
||||
<arg name="property" direction="in" type="s"/>
|
||||
<arg name="value" direction="out" type="v"/>
|
||||
</method>
|
||||
<method name="GetAll">
|
||||
<arg name="interface" direction="in" type="s"/>
|
||||
<arg name="properties" direction="out" type="a{sv}"/>
|
||||
</method>
|
||||
<method name="Set">
|
||||
<arg name="interface" direction="in" type="s"/>
|
||||
<arg name="property" direction="in" type="s"/>
|
||||
<arg name="value" direction="in" type="v"/>
|
||||
</method>
|
||||
<signal name="PropertiesChanged">
|
||||
<arg type="s" name="interface"/>
|
||||
<arg type="a{sv}" name="changed_properties"/>
|
||||
<arg type="as" name="invalidated_properties"/>
|
||||
</signal>
|
||||
</interface>
|
||||
<interface name="org.freedesktop.systemd.VtableExample">
|
||||
<method name="Method1">
|
||||
<arg type="s" direction="in"/>
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="Method2">
|
||||
<arg type="s" name="string" direction="in"/>
|
||||
<arg type="o" name="path" direction="in"/>
|
||||
<arg type="s" name="returnstring" direction="out"/>
|
||||
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
|
||||
</method>
|
||||
<property name="AutomaticStringProperty" type="s" access="readwrite">
|
||||
</property>
|
||||
<property name="AutomaticIntegerProperty" type="u" access="readwrite">
|
||||
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/>
|
||||
</property>
|
||||
</interface>
|
||||
</node>
|
||||
|
@ -50,6 +50,7 @@ static size_t arg_snaplen = 4096;
|
||||
static bool arg_list = false;
|
||||
static bool arg_quiet = false;
|
||||
static bool arg_verbose = false;
|
||||
static bool arg_xml_interface = false;
|
||||
static bool arg_expect_reply = true;
|
||||
static bool arg_auto_start = true;
|
||||
static bool arg_allow_interactive_authorization = true;
|
||||
@ -948,6 +949,12 @@ static int introspect(int argc, char **argv, void *userdata) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
if (arg_xml_interface) {
|
||||
/* Just dump the received XML and finish */
|
||||
puts(xml);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First, get list of all properties */
|
||||
r = parse_xml_introspect(argv[2], xml, &ops, members);
|
||||
if (r < 0)
|
||||
@ -2255,6 +2262,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_SIZE,
|
||||
ARG_LIST,
|
||||
ARG_VERBOSE,
|
||||
ARG_XML_INTERFACE,
|
||||
ARG_EXPECT_REPLY,
|
||||
ARG_AUTO_START,
|
||||
ARG_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||
@ -2284,6 +2292,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "list", no_argument, NULL, ARG_LIST },
|
||||
{ "quiet", no_argument, NULL, 'q' },
|
||||
{ "verbose", no_argument, NULL, ARG_VERBOSE },
|
||||
{ "xml-interface", no_argument, NULL, ARG_XML_INTERFACE },
|
||||
{ "expect-reply", required_argument, NULL, ARG_EXPECT_REPLY },
|
||||
{ "auto-start", required_argument, NULL, ARG_AUTO_START },
|
||||
{ "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION },
|
||||
@ -2388,6 +2397,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_verbose = true;
|
||||
break;
|
||||
|
||||
case ARG_XML_INTERFACE:
|
||||
arg_xml_interface = true;
|
||||
break;
|
||||
|
||||
case ARG_EXPECT_REPLY:
|
||||
r = parse_boolean(optarg);
|
||||
if (r < 0)
|
||||
|
@ -676,3 +676,8 @@ LIBSYSTEMD_241 {
|
||||
global:
|
||||
sd_bus_close_unref;
|
||||
} LIBSYSTEMD_240;
|
||||
|
||||
LIBSYSTEMD_243 {
|
||||
global:
|
||||
sd_bus_object_vtable_format;
|
||||
} LIBSYSTEMD_241;
|
||||
|
@ -172,13 +172,10 @@ int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply) {
|
||||
sd_bus_message *q;
|
||||
int introspect_finish(struct introspect *i, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(i);
|
||||
assert(m);
|
||||
assert(reply);
|
||||
|
||||
fputs("</node>\n", i->f);
|
||||
|
||||
@ -186,25 +183,17 @@ int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_b
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_new_method_return(m, &q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
i->f = safe_fclose(i->f);
|
||||
*ret = TAKE_PTR(i->introspection);
|
||||
|
||||
r = sd_bus_message_append(q, "s", i->introspection);
|
||||
if (r < 0) {
|
||||
sd_bus_message_unref(q);
|
||||
return r;
|
||||
}
|
||||
|
||||
*reply = q;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void introspect_free(struct introspect *i) {
|
||||
assert(i);
|
||||
|
||||
safe_fclose(i->f);
|
||||
/* Normally introspect_finish() does all the work, this is just a backup for error paths */
|
||||
|
||||
safe_fclose(i->f);
|
||||
free(i->introspection);
|
||||
zero(*i);
|
||||
}
|
||||
|
@ -18,5 +18,5 @@ int introspect_begin(struct introspect *i, bool trusted);
|
||||
int introspect_write_default_interfaces(struct introspect *i, bool object_manager);
|
||||
int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix);
|
||||
int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v);
|
||||
int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply);
|
||||
int introspect_finish(struct introspect *i, char **ret);
|
||||
void introspect_free(struct introspect *i);
|
||||
|
@ -22,7 +22,7 @@ static int node_vtable_get_userdata(
|
||||
sd_bus_error *error) {
|
||||
|
||||
sd_bus_slot *s;
|
||||
void *u, *found_u;
|
||||
void *u, *found_u = NULL;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
@ -883,31 +883,33 @@ static int bus_node_exists(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_introspect(
|
||||
int introspect_path(
|
||||
sd_bus *bus,
|
||||
sd_bus_message *m,
|
||||
const char *path,
|
||||
struct node *n,
|
||||
bool require_fallback,
|
||||
bool *found_object) {
|
||||
bool ignore_nodes_modified,
|
||||
bool *found_object,
|
||||
char **ret,
|
||||
sd_bus_error *error) {
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_set_free_free_ Set *s = NULL;
|
||||
const char *previous_interface = NULL;
|
||||
struct introspect intro;
|
||||
_cleanup_(introspect_free) struct introspect intro = {};
|
||||
struct node_vtable *c;
|
||||
bool empty;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(m);
|
||||
assert(n);
|
||||
assert(found_object);
|
||||
if (!n) {
|
||||
n = hashmap_get(bus->nodes, path);
|
||||
if (!n)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
r = get_child_nodes(bus, m->path, n, 0, &s, &error);
|
||||
r = get_child_nodes(bus, path, n, 0, &s, error);
|
||||
if (r < 0)
|
||||
return bus_maybe_reply_error(m, r, &error);
|
||||
if (bus->nodes_modified)
|
||||
return r;
|
||||
if (bus->nodes_modified && !ignore_nodes_modified)
|
||||
return 0;
|
||||
|
||||
r = introspect_begin(&intro, bus->trusted);
|
||||
@ -924,15 +926,11 @@ static int process_introspect(
|
||||
if (require_fallback && !c->is_fallback)
|
||||
continue;
|
||||
|
||||
r = node_vtable_get_userdata(bus, m->path, c, NULL, &error);
|
||||
if (r < 0) {
|
||||
r = bus_maybe_reply_error(m, r, &error);
|
||||
goto finish;
|
||||
}
|
||||
if (bus->nodes_modified) {
|
||||
r = 0;
|
||||
goto finish;
|
||||
}
|
||||
r = node_vtable_get_userdata(bus, path, c, NULL, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (bus->nodes_modified && !ignore_nodes_modified)
|
||||
return 0;
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
@ -942,7 +940,6 @@ static int process_introspect(
|
||||
continue;
|
||||
|
||||
if (!streq_ptr(previous_interface, c->interface)) {
|
||||
|
||||
if (previous_interface)
|
||||
fputs(" </interface>\n", intro.f);
|
||||
|
||||
@ -951,7 +948,7 @@ static int process_introspect(
|
||||
|
||||
r = introspect_write_interface(&intro, c->vtable);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
return r;
|
||||
|
||||
previous_interface = c->interface;
|
||||
}
|
||||
@ -962,36 +959,64 @@ static int process_introspect(
|
||||
if (empty) {
|
||||
/* Nothing?, let's see if we exist at all, and if not
|
||||
* refuse to do anything */
|
||||
r = bus_node_exists(bus, n, m->path, require_fallback);
|
||||
if (r <= 0) {
|
||||
r = bus_maybe_reply_error(m, r, &error);
|
||||
goto finish;
|
||||
}
|
||||
if (bus->nodes_modified) {
|
||||
r = 0;
|
||||
goto finish;
|
||||
}
|
||||
r = bus_node_exists(bus, n, path, require_fallback);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (bus->nodes_modified && !ignore_nodes_modified)
|
||||
return 0;
|
||||
}
|
||||
|
||||
*found_object = true;
|
||||
if (found_object)
|
||||
*found_object = true;
|
||||
|
||||
r = introspect_write_child_nodes(&intro, s, m->path);
|
||||
r = introspect_write_child_nodes(&intro, s, path);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
return r;
|
||||
|
||||
r = introspect_finish(&intro, bus, m, &reply);
|
||||
r = introspect_finish(&intro, ret);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int process_introspect(
|
||||
sd_bus *bus,
|
||||
sd_bus_message *m,
|
||||
struct node *n,
|
||||
bool require_fallback,
|
||||
bool *found_object) {
|
||||
|
||||
_cleanup_free_ char *s = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(m);
|
||||
assert(n);
|
||||
assert(found_object);
|
||||
|
||||
r = introspect_path(bus, m->path, n, require_fallback, false, found_object, &s, &error);
|
||||
if (r < 0)
|
||||
return bus_maybe_reply_error(m, r, &error);
|
||||
if (r == 0)
|
||||
/* nodes_modified == true */
|
||||
return 0;
|
||||
|
||||
r = sd_bus_message_new_method_return(m, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(reply, "s", s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_send(bus, reply, NULL);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
return r;
|
||||
|
||||
r = 1;
|
||||
|
||||
finish:
|
||||
introspect_free(&intro);
|
||||
return r;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int object_manager_serialize_path(
|
||||
@ -1668,7 +1693,7 @@ static bool names_are_valid(const char *signature, const char **names, names_fla
|
||||
|
||||
/* the current version of this struct is defined in sd-bus-vtable.h, but we need to list here the historical versions
|
||||
to make sure the calling code is compatible with one of these */
|
||||
struct sd_bus_vtable_original {
|
||||
struct sd_bus_vtable_221 {
|
||||
uint8_t type:8;
|
||||
uint64_t flags:56;
|
||||
union {
|
||||
@ -1696,12 +1721,16 @@ struct sd_bus_vtable_original {
|
||||
} x;
|
||||
};
|
||||
/* Structure size up to v241 */
|
||||
#define VTABLE_ELEMENT_SIZE_ORIGINAL sizeof(struct sd_bus_vtable_original)
|
||||
/* Current structure size */
|
||||
#define VTABLE_ELEMENT_SIZE sizeof(struct sd_bus_vtable)
|
||||
#define VTABLE_ELEMENT_SIZE_221 sizeof(struct sd_bus_vtable_221)
|
||||
|
||||
/* Size of the structure when "features" field was added. If the structure definition is augmented, a copy of
|
||||
* the structure definition will need to be made (similarly to the sd_bus_vtable_221 above), and this
|
||||
* definition updated to refer to it. */
|
||||
#define VTABLE_ELEMENT_SIZE_242 sizeof(struct sd_bus_vtable)
|
||||
|
||||
static int vtable_features(const sd_bus_vtable *vtable) {
|
||||
if (vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL)
|
||||
if (vtable[0].x.start.element_size < VTABLE_ELEMENT_SIZE_242 ||
|
||||
!vtable[0].x.start.vtable_format_reference)
|
||||
return 0;
|
||||
return vtable[0].x.start.features;
|
||||
}
|
||||
@ -1711,13 +1740,7 @@ bool bus_vtable_has_names(const sd_bus_vtable *vtable) {
|
||||
}
|
||||
|
||||
const sd_bus_vtable* bus_vtable_next(const sd_bus_vtable *vtable, const sd_bus_vtable *v) {
|
||||
if (vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL) {
|
||||
const struct sd_bus_vtable_original *v2 = (const struct sd_bus_vtable_original *)v;
|
||||
v2++;
|
||||
v = (const sd_bus_vtable*)v2;
|
||||
} else /* current version */
|
||||
v++;
|
||||
return v;
|
||||
return (const sd_bus_vtable*) ((char*) v + vtable[0].x.start.element_size);
|
||||
}
|
||||
|
||||
static int add_object_vtable_internal(
|
||||
@ -1744,8 +1767,8 @@ static int add_object_vtable_internal(
|
||||
assert_return(interface_name_is_valid(interface), -EINVAL);
|
||||
assert_return(vtable, -EINVAL);
|
||||
assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
|
||||
assert_return(vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL ||
|
||||
vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE,
|
||||
assert_return(vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_221 ||
|
||||
vtable[0].x.start.element_size >= VTABLE_ELEMENT_SIZE_242,
|
||||
-EINVAL);
|
||||
assert_return(!bus_pid_changed(bus), -ECHILD);
|
||||
assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&
|
||||
@ -1928,6 +1951,9 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
/* This symbol exists solely to tell the linker that the "new" vtable format is used. */
|
||||
_public_ const unsigned sd_bus_object_vtable_format = 242;
|
||||
|
||||
_public_ int sd_bus_add_object_vtable(
|
||||
sd_bus *bus,
|
||||
sd_bus_slot **slot,
|
||||
|
@ -2,8 +2,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "bus-internal.h"
|
||||
#include "bus-introspect.h"
|
||||
|
||||
const sd_bus_vtable* bus_vtable_next(const sd_bus_vtable *vtable, const sd_bus_vtable *v);
|
||||
bool bus_vtable_has_names(const sd_bus_vtable *vtable);
|
||||
int bus_process_object(sd_bus *bus, sd_bus_message *m);
|
||||
void bus_node_gc(sd_bus *b, struct node *n);
|
||||
|
||||
int introspect_path(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
struct node *n,
|
||||
bool require_fallback,
|
||||
bool ignore_nodes_modified,
|
||||
bool *found_object,
|
||||
char **ret,
|
||||
sd_bus_error *error);
|
||||
|
@ -4,33 +4,13 @@
|
||||
#include "log.h"
|
||||
#include "tests.h"
|
||||
|
||||
static int prop_get(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
|
||||
return -EINVAL;
|
||||
}
|
||||
#include "test-vtable-data.h"
|
||||
|
||||
static int prop_set(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
|
||||
return -EINVAL;
|
||||
}
|
||||
static void test_manual_introspection(const sd_bus_vtable vtable[]) {
|
||||
struct introspect intro = {};
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
static const sd_bus_vtable vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD("Hello", "ssas", "a(uu)", NULL, 0),
|
||||
SD_BUS_METHOD("DeprecatedHello", "", "", NULL, SD_BUS_VTABLE_DEPRECATED),
|
||||
SD_BUS_METHOD("DeprecatedHelloNoReply", "", "", NULL, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_METHOD_NO_REPLY),
|
||||
SD_BUS_SIGNAL("Wowza", "sss", 0),
|
||||
SD_BUS_SIGNAL("DeprecatedWowza", "ut", SD_BUS_VTABLE_DEPRECATED),
|
||||
SD_BUS_WRITABLE_PROPERTY("AProperty", "s", prop_get, prop_set, 0, 0),
|
||||
SD_BUS_PROPERTY("AReadOnlyDeprecatedProperty", "(ut)", prop_get, 0, SD_BUS_VTABLE_DEPRECATED),
|
||||
SD_BUS_PROPERTY("ChangingProperty", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Invalidating", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
SD_BUS_PROPERTY("Constant", "t", prop_get, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EXPLICIT),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct introspect intro;
|
||||
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
assert_se(introspect_begin(&intro, false) >= 0);
|
||||
|
||||
@ -38,10 +18,18 @@ int main(int argc, char *argv[]) {
|
||||
assert_se(introspect_write_interface(&intro, vtable) >= 0);
|
||||
fputs(" </interface>\n", intro.f);
|
||||
|
||||
fflush(intro.f);
|
||||
fputs(intro.introspection, stdout);
|
||||
assert_se(introspect_finish(&intro, &s) == 0);
|
||||
fputs(s, stdout);
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
|
||||
introspect_free(&intro);
|
||||
int main(int argc, char *argv[]) {
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
test_manual_introspection(test_vtable_1);
|
||||
test_manual_introspection(test_vtable_2);
|
||||
test_manual_introspection(test_vtable_deprecated);
|
||||
test_manual_introspection((const sd_bus_vtable *) vtable_format_221);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
@ -5,120 +7,18 @@
|
||||
#undef NDEBUG
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sd-bus-vtable.h"
|
||||
|
||||
#ifndef __cplusplus
|
||||
# include "bus-objects.h"
|
||||
#endif
|
||||
|
||||
#include "test-vtable-data.h"
|
||||
|
||||
#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
|
||||
|
||||
struct context {
|
||||
bool quit;
|
||||
char *something;
|
||||
char *automatic_string_property;
|
||||
uint32_t automatic_integer_property;
|
||||
};
|
||||
|
||||
static int handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const sd_bus_vtable vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD("AlterSomething", "s", "s", handler, 0),
|
||||
SD_BUS_METHOD("Exit", "", "", handler, 0),
|
||||
SD_BUS_METHOD_WITH_OFFSET("AlterSomething2", "s", "s", handler, 200, 0),
|
||||
SD_BUS_METHOD_WITH_OFFSET("Exit2", "", "", handler, 200, 0),
|
||||
SD_BUS_METHOD_WITH_NAMES_OFFSET("AlterSomething3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
|
||||
"s", SD_BUS_PARAM(returnstring), handler, 200, 0),
|
||||
SD_BUS_METHOD_WITH_NAMES("Exit3", "bx", SD_BUS_PARAM(with_confirmation) SD_BUS_PARAM(after_msec),
|
||||
"bb", SD_BUS_PARAM(accepted) SD_BUS_PARAM(scheduled), handler, 0),
|
||||
SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
|
||||
SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something),
|
||||
SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
|
||||
SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL,
|
||||
offsetof(struct context, automatic_string_property), 0),
|
||||
SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL,
|
||||
offsetof(struct context, automatic_integer_property), 0),
|
||||
SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
|
||||
SD_BUS_SIGNAL("DummySignal", "b", 0),
|
||||
SD_BUS_SIGNAL("DummySignal2", "so", 0),
|
||||
SD_BUS_SIGNAL_WITH_NAMES("DummySignal3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path), 0),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
struct sd_bus_vtable_original {
|
||||
uint8_t type:8;
|
||||
uint64_t flags:56;
|
||||
union {
|
||||
struct {
|
||||
size_t element_size;
|
||||
} start;
|
||||
struct {
|
||||
const char *member;
|
||||
const char *signature;
|
||||
const char *result;
|
||||
sd_bus_message_handler_t handler;
|
||||
size_t offset;
|
||||
} method;
|
||||
struct {
|
||||
const char *member;
|
||||
const char *signature;
|
||||
} signal;
|
||||
struct {
|
||||
const char *member;
|
||||
const char *signature;
|
||||
sd_bus_property_get_t get;
|
||||
sd_bus_property_set_t set;
|
||||
size_t offset;
|
||||
} property;
|
||||
} x;
|
||||
};
|
||||
|
||||
static const struct sd_bus_vtable_original vtable_format_original[] = {
|
||||
{
|
||||
.type = _SD_BUS_VTABLE_START,
|
||||
.flags = 0,
|
||||
.x = {
|
||||
.start = {
|
||||
.element_size = sizeof(struct sd_bus_vtable_original)
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = _SD_BUS_VTABLE_METHOD,
|
||||
.flags = 0,
|
||||
.x = {
|
||||
.method = {
|
||||
.member = "Exit",
|
||||
.signature = "",
|
||||
.result = "",
|
||||
.handler = handler,
|
||||
.offset = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = _SD_BUS_VTABLE_END,
|
||||
.flags = 0,
|
||||
.x = { { 0 } },
|
||||
}
|
||||
};
|
||||
|
||||
static void test_vtable(void) {
|
||||
sd_bus *bus = NULL;
|
||||
struct context c = {};
|
||||
@ -126,16 +26,24 @@ static void test_vtable(void) {
|
||||
|
||||
assert(sd_bus_new(&bus) >= 0);
|
||||
|
||||
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable", vtable, &c) >= 0);
|
||||
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable2", vtable, &c) >= 0);
|
||||
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable", test_vtable_2, &c) >= 0);
|
||||
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable2", test_vtable_2, &c) >= 0);
|
||||
/* the cast on the line below is needed to test with the old version of the table */
|
||||
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtableOriginal", (const sd_bus_vtable *)vtable_format_original, &c) >= 0);
|
||||
assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable221",
|
||||
(const sd_bus_vtable *)vtable_format_221, &c) >= 0);
|
||||
|
||||
assert(sd_bus_set_address(bus, DEFAULT_BUS_PATH) >= 0);
|
||||
r = sd_bus_start(bus);
|
||||
assert(r == 0 || /* success */
|
||||
r == -ENOENT /* dbus is inactive */ );
|
||||
|
||||
#ifndef __cplusplus
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
assert_se(introspect_path(bus, "/foo", NULL, false, true, NULL, &s, NULL) == 1);
|
||||
fputs(s, stdout);
|
||||
#endif
|
||||
|
||||
sd_bus_unref(bus);
|
||||
}
|
||||
|
||||
|
132
src/libsystemd/sd-bus/test-vtable-data.h
Normal file
132
src/libsystemd/sd-bus/test-vtable-data.h
Normal file
@ -0,0 +1,132 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
/* This is meant to be included in other files, hence no headers */
|
||||
|
||||
struct context {
|
||||
bool quit;
|
||||
char *something;
|
||||
char *automatic_string_property;
|
||||
uint32_t automatic_integer_property;
|
||||
};
|
||||
|
||||
static int handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const sd_bus_vtable test_vtable_1[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD("Hello", "ssas", "a(uu)", NULL, 0),
|
||||
SD_BUS_METHOD("DeprecatedHello", "", "", NULL, SD_BUS_VTABLE_DEPRECATED),
|
||||
SD_BUS_METHOD("DeprecatedHelloNoReply", "", "", NULL, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_METHOD_NO_REPLY),
|
||||
SD_BUS_SIGNAL("Wowza", "sss", 0),
|
||||
SD_BUS_SIGNAL("DeprecatedWowza", "ut", SD_BUS_VTABLE_DEPRECATED),
|
||||
SD_BUS_WRITABLE_PROPERTY("AProperty", "s", get_handler, set_handler, 0, 0),
|
||||
SD_BUS_PROPERTY("AReadOnlyDeprecatedProperty", "(ut)", get_handler, 0, SD_BUS_VTABLE_DEPRECATED),
|
||||
SD_BUS_PROPERTY("ChangingProperty", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Invalidating", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
SD_BUS_PROPERTY("Constant", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EXPLICIT),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
static const sd_bus_vtable test_vtable_2[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_METHOD("AlterSomething", "s", "s", handler, 0),
|
||||
SD_BUS_METHOD("Exit", "", "", handler, 0),
|
||||
SD_BUS_METHOD_WITH_OFFSET("AlterSomething2", "s", "s", handler, 200, 0),
|
||||
SD_BUS_METHOD_WITH_OFFSET("Exit2", "", "", handler, 200, 0),
|
||||
SD_BUS_METHOD_WITH_NAMES_OFFSET("AlterSomething3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
|
||||
"s", SD_BUS_PARAM(returnstring), handler, 200, 0),
|
||||
SD_BUS_METHOD_WITH_NAMES("Exit3", "bx", SD_BUS_PARAM(with_confirmation) SD_BUS_PARAM(after_msec),
|
||||
"bb", SD_BUS_PARAM(accepted) SD_BUS_PARAM(scheduled), handler, 0),
|
||||
SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
|
||||
SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something),
|
||||
SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
|
||||
SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL,
|
||||
offsetof(struct context, automatic_string_property), 0),
|
||||
SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL,
|
||||
offsetof(struct context, automatic_integer_property), 0),
|
||||
SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
|
||||
SD_BUS_SIGNAL("DummySignal", "b", 0),
|
||||
SD_BUS_SIGNAL("DummySignal2", "so", 0),
|
||||
SD_BUS_SIGNAL_WITH_NAMES("DummySignal3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path), 0),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
static const sd_bus_vtable test_vtable_deprecated[] = {
|
||||
SD_BUS_VTABLE_START(SD_BUS_VTABLE_DEPRECATED),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
struct sd_bus_vtable_221 {
|
||||
uint8_t type:8;
|
||||
uint64_t flags:56;
|
||||
union {
|
||||
struct {
|
||||
size_t element_size;
|
||||
} start;
|
||||
struct {
|
||||
const char *member;
|
||||
const char *signature;
|
||||
const char *result;
|
||||
sd_bus_message_handler_t handler;
|
||||
size_t offset;
|
||||
} method;
|
||||
struct {
|
||||
const char *member;
|
||||
const char *signature;
|
||||
} signal;
|
||||
struct {
|
||||
const char *member;
|
||||
const char *signature;
|
||||
sd_bus_property_get_t get;
|
||||
sd_bus_property_set_t set;
|
||||
size_t offset;
|
||||
} property;
|
||||
} x;
|
||||
};
|
||||
|
||||
static const struct sd_bus_vtable_221 vtable_format_221[] = {
|
||||
{
|
||||
.type = _SD_BUS_VTABLE_START,
|
||||
.flags = 0,
|
||||
.x = {
|
||||
.start = {
|
||||
.element_size = sizeof(struct sd_bus_vtable_221)
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = _SD_BUS_VTABLE_METHOD,
|
||||
.flags = 0,
|
||||
.x = {
|
||||
.method = {
|
||||
.member = "Exit",
|
||||
.signature = "",
|
||||
.result = "",
|
||||
.handler = handler,
|
||||
.offset = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = _SD_BUS_VTABLE_END,
|
||||
.flags = 0,
|
||||
.x = { { 0 } },
|
||||
}
|
||||
};
|
@ -52,6 +52,15 @@ enum {
|
||||
_SD_BUS_VTABLE_PARAM_NAMES = 1 << 0,
|
||||
};
|
||||
|
||||
extern const unsigned sd_bus_object_vtable_format;
|
||||
|
||||
/* Note: unused areas in the sd_bus_vtable[] array must be initalized to 0. The stucture contains an embedded
|
||||
* union, and the compiler is NOT required to initalize the unused areas of the union when the rest of the
|
||||
* structure is initalized. Normally the array is defined as read-only data, in which case the linker places
|
||||
* it in the BSS section, which is always fully initalized, so this is not a concern. But if the array is
|
||||
* created on the stack or on the heap, care must be taken to initalize the unused areas, for examply by
|
||||
* first memsetting the whole region to zero before filling the data in. */
|
||||
|
||||
struct sd_bus_vtable {
|
||||
/* Please do not initialize this structure directly, use the
|
||||
* macros below instead */
|
||||
@ -62,6 +71,7 @@ struct sd_bus_vtable {
|
||||
struct {
|
||||
size_t element_size;
|
||||
uint64_t features;
|
||||
const unsigned *vtable_format_reference;
|
||||
} start;
|
||||
struct {
|
||||
const char *member;
|
||||
@ -93,7 +103,8 @@ struct sd_bus_vtable {
|
||||
.x = { \
|
||||
.start = { \
|
||||
.element_size = sizeof(sd_bus_vtable), \
|
||||
.features = _SD_BUS_VTABLE_PARAM_NAMES \
|
||||
.features = _SD_BUS_VTABLE_PARAM_NAMES, \
|
||||
.vtable_format_reference = &sd_bus_object_vtable_format, \
|
||||
}, \
|
||||
}, \
|
||||
}
|
||||
|
@ -6,18 +6,22 @@ for header in sys.argv[2:]:
|
||||
print('#include "{}"'.format(header.split('/')[-1]))
|
||||
|
||||
print('''
|
||||
void* functions[] = {''')
|
||||
const void* symbols[] = {''')
|
||||
|
||||
for line in open(sys.argv[1]):
|
||||
match = re.search('^ +([a-zA-Z0-9_]+);', line)
|
||||
if match:
|
||||
print(' {},'.format(match.group(1)))
|
||||
s = match.group(1)
|
||||
if s == 'sd_bus_object_vtable_format':
|
||||
print(' &{},'.format(s))
|
||||
else:
|
||||
print(' {},'.format(s))
|
||||
|
||||
print('''};
|
||||
|
||||
int main(void) {
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof(functions)/sizeof(void*); i++)
|
||||
printf("%p\\n", functions[i]);
|
||||
for (i = 0; i < sizeof(symbols)/sizeof(void*); i++)
|
||||
printf("%p\\n", symbols[i]);
|
||||
return 0;
|
||||
}''')
|
||||
|
@ -911,7 +911,8 @@ tests += [
|
||||
[],
|
||||
[threads]],
|
||||
|
||||
[['src/libsystemd/sd-bus/test-bus-vtable.c'],
|
||||
[['src/libsystemd/sd-bus/test-bus-vtable.c',
|
||||
'src/libsystemd/sd-bus/test-vtable-data.h'],
|
||||
[],
|
||||
[]],
|
||||
|
||||
@ -934,7 +935,8 @@ tests += [
|
||||
[threads],
|
||||
'', 'manual'],
|
||||
|
||||
[['src/libsystemd/sd-bus/test-bus-introspect.c'],
|
||||
[['src/libsystemd/sd-bus/test-bus-introspect.c',
|
||||
'src/libsystemd/sd-bus/test-vtable-data.h'],
|
||||
[],
|
||||
[]],
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user