a different layout of the bootloader partitions (for example grub2).
* During package installation (with `ninja install`), we would create
- symlinks for systemd-networkd.service, systemd-networkd.socket,
- systemd-resolved.service, remote-cryptsetup.target, remote-fs.target,
+ symlinks for getty@tty1.service, systemd-networkd.service,
+ systemd-networkd.socket, systemd-resolved.service,
+ remote-cryptsetup.target, remote-fs.target,
systemd-networkd-wait-online.service, and systemd-timesyncd.service
in /etc, as if `systemctl enable` was called for those units, to make
the system usable immediately after installation. Now this is not
użytkowników (przy wykorzystaniu przestrzeni nazw użytkowników lub NFS)
nie wynosi 65534.
Obecny system ma etykietę „@TAINT@”.
+
+-- fe6faa94e7774663a0da52717891d8ef
+Subject: Proces jednostki @UNIT@ został zakończony przez OOM Killer
+Defined-By: systemd
+Support: %SUPPORT_URL%
+
+Proces jednostki @UNIT został zakończony przez mechanizm kończenia
+procesów przy braku pamięci (OOM) jądra Linux. Zwykle wskazuje to,
+że system ma mało pamięci i należało ją zwolnić. Proces powiązany
+z jednostką @UNIT@ został uznany za najlepszy do zakończenia
+i jądro wymusiło zakończenie jego działania.
+
+Proszę zauważyć, że brak pamięci mógł nie zostać spowodowany
+przez jednostkę @UNIT@.
✓ TasksAccounting=
✓ TasksMax=
✓ Delegate=
+✓ DisableControllers=
✓ IPAccounting=
✓ IPAddressAllow=
✓ IPAddressDeny=
EVDEV_ABS_35=79:1841:22
EVDEV_ABS_36=140:1325:29
+# Dell Latitude E7250
+evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7250*
+ EVDEV_ABS_00=179:3903:38
+ EVDEV_ABS_01=277:1916:32
+ EVDEV_ABS_35=179:3903:38
+ EVDEV_ABS_36=277:1916:32
+
# Dell Latitude E7470
evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*
EVDEV_ABS_00=29:2930:30
# OLPC
###########################################################
-# XO
+# XO-1 and XO-1.5
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOLPC:pnXO:*
+# XO-1.75 and XO-1.4 (sp/ is the Security Processor)
+evdev:name:AT Translated Set 2 keyboard:phys:sp/serio*/input*:ev:120013:*
+ KEYBOARD_LED_CAPSLOCK=0
+ KEYBOARD_LED_NUMLOCK=0
KEYBOARD_KEY_59=fn
KEYBOARD_KEY_81=fn_esc
KEYBOARD_KEY_f9=camera
KEYBOARD_KEY_dc=rightmeta # right grab
KEYBOARD_KEY_85=rightmeta # Right grab releases on a different scancode
KEYBOARD_KEY_d6=kbdillumtoggle # Fn+Space
- KEYBOARD_KEY_69=switchvideomode # Brightness key
- KEYBOARD_KEY_65=kp8 # up
- KEYBOARD_KEY_66=kp2 # down
- KEYBOARD_KEY_67=kp4 # left
- KEYBOARD_KEY_68=kp6 # right
- KEYBOARD_KEY_e5=kp9 # pgup
- KEYBOARD_KEY_e6=kp3 # pgdn
- KEYBOARD_KEY_e7=kp7 # home
- KEYBOARD_KEY_e8=kp1 # end
+ KEYBOARD_KEY_69=rotate_display
+ KEYBOARD_KEY_65=btn_dpad_up
+ KEYBOARD_KEY_66=btn_dpad_down
+ KEYBOARD_KEY_67=btn_dpad_left
+ KEYBOARD_KEY_68=btn_dpad_right
+ KEYBOARD_KEY_e5=btn_north
+ KEYBOARD_KEY_e6=btn_south
+ KEYBOARD_KEY_e7=btn_west
+ KEYBOARD_KEY_e8=btn_east
###########################################################
# Onkyo
</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>
'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',
<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>,
--- /dev/null
+<?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>
watchdog is enabled. </para></listitem>
</varlistentry>
+ <varlistentry>
+ <term>WATCHDOG=trigger</term>
+
+ <listitem><para>Tells the service manager that the service detected an internal error that should be handled by
+ the configured watchdog options. This will trigger the same behaviour as if <varname>WatchdogSec=</varname> is
+ enabled and the service did not send <literal>WATCHDOG=1</literal> in time. Note that
+ <varname>WatchdogSec=</varname> does not need to be enabled for <literal>WATCHDOG=trigger</literal> to trigger
+ the watchdog action. See
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+ information about the watchdog behavior. </para></listitem>
+ </varlistentry>
+
<varlistentry>
<term>WATCHDOG_USEC=…</term>
is used. In this case the source path refers to a path on the host file system, while the destination path
refers to a path below the root directory of the unit.</para>
+ <para>Note that the destination directory must exist or systemd must be able to create it. Thus, it
+ is not possible to use those options for mount points nested underneath paths specified in
+ <varname>InaccessiblePaths=</varname>, or under <filename>/home/</filename> and other protected
+ directories if <varname>ProtectHome=yes</varname> is
+ specified. <varname>TemporaryFileSystem=</varname> with <literal>:ro</literal> or
+ <varname>ProtectHome=tmpfs</varname> should be used instead.</para>
+
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
</varlistentry>
<term><varname>ProtectHome=</varname></term>
<listitem><para>Takes a boolean argument or the special values <literal>read-only</literal> or
- <literal>tmpfs</literal>. If true, the directories <filename>/home</filename>, <filename>/root</filename> and
- <filename>/run/user</filename> are made inaccessible and empty for processes invoked by this unit. If set to
- <literal>read-only</literal>, the three directories are made read-only instead. If set to <literal>tmpfs</literal>,
- temporary file systems are mounted on the three directories in read-only mode. The value <literal>tmpfs</literal>
- is useful to hide home directories not relevant to the processes invoked by the unit, while necessary directories
- are still visible by combining with <varname>BindPaths=</varname> or <varname>BindReadOnlyPaths=</varname>.</para>
+ <literal>tmpfs</literal>. If true, the directories <filename>/home</filename>,
+ <filename>/root</filename>, and <filename>/run/user</filename> are made inaccessible and empty for
+ processes invoked by this unit. If set to <literal>read-only</literal>, the three directories are
+ made read-only instead. If set to <literal>tmpfs</literal>, temporary file systems are mounted on the
+ three directories in read-only mode. The value <literal>tmpfs</literal> is useful to hide home
+ directories not relevant to the processes invoked by the unit, while still allowing necessary
+ directories to be made visible when listed in <varname>BindPaths=</varname> or
+ <varname>BindReadOnlyPaths=</varname>.</para>
<para>Setting this to <literal>yes</literal> is mostly equivalent to set the three directories in
<varname>InaccessiblePaths=</varname>. Similarly, <literal>read-only</literal> is mostly equivalent to
<varname>ReadOnlyPaths=</varname>, and <literal>tmpfs</literal> is mostly equivalent to
- <varname>TemporaryFileSystem=</varname>.</para>
+ <varname>TemporaryFileSystem=</varname> with <literal>:ro</literal>.</para>
- <para> It is recommended to enable this setting for all long-running services (in particular network-facing
- ones), to ensure they cannot get access to private user data, unless the services actually require access to
- the user's private data. This setting is implied if <varname>DynamicUser=</varname> is set. This setting cannot
- ensure protection in all cases. In general it has the same limitations as <varname>ReadOnlyPaths=</varname>,
- see below.</para>
+ <para>It is recommended to enable this setting for all long-running services (in particular
+ network-facing ones), to ensure they cannot get access to private user data, unless the services
+ actually require access to the user's private data. This setting is implied if
+ <varname>DynamicUser=</varname> is set. This setting cannot ensure protection in all cases. In
+ general it has the same limitations as <varname>ReadOnlyPaths=</varname>, see below.</para>
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
</varlistentry>
<para>This is useful to hide files or directories not relevant to the processes invoked by the unit, while necessary
files or directories can be still accessed by combining with <varname>BindPaths=</varname> or
- <varname>BindReadOnlyPaths=</varname>. See the example below.</para>
+ <varname>BindReadOnlyPaths=</varname>:</para>
<para>Example: if a unit has the following,
<programlisting>TemporaryFileSystem=/var:ro
<refsect1>
<title>[Match] Section Options</title>
- <para>A link file is said to match a device if each of the entries in the [Match] section matches, or if
- the section is empty. The following keys are accepted:</para>
+ <para>A link file is said to match a device if all matches specified by the
+ <literal>[Match]</literal> section are satisfied. When a link file does not contain valid settings
+ in <literal>[Match]</literal> section, then the file will match all devices and
+ <command>systemd-udevd</command> warns about that. Hint: to avoid the warning and to make it clear
+ that all interfaces shall be matched, add the following:
+ <programlisting>OriginalName=*</programlisting>
+ The following keys are accepted:</para>
<variablelist class='network-directives'>
<varlistentry>
is applied, all later files are ignored, even if they match as
well.</para>
- <para>A network file is said to match a device if each of the
- entries in the <literal>[Match]</literal> section matches, or if
- the section is empty. The following keys are accepted:</para>
+ <para>A network file is said to match a network interface if all matches specified by the
+ <literal>[Match]</literal> section are satisfied. When a network file does not contain valid
+ settings in <literal>[Match]</literal> section, then the file will match all interfaces and
+ <command>systemd-networkd</command> warns about that. Hint: to avoid the warning and to make it
+ clear that all interfaces shall be matched, add the following:
+ <programlisting>Name=*</programlisting>
+ The following keys are accepted:</para>
<variablelist class='network-directives'>
<varlistentry>
--- /dev/null
+#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;
+}
--- /dev/null
+<!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>
+
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
+[Match]
+OriginalName=*
+
[Link]
NamePolicy=keep kernel database onboard slot path
MACAddressPolicy=persistent
# The static_node is required on s390x and ppc (they are using MODULE_ALIAS)
KERNEL=="kvm", GROUP="kvm", MODE="@DEV_KVM_MODE@", OPTIONS+="static_node=kvm"
+KERNEL=="udmabuf", GROUP="kvm"
+
SUBSYSTEM=="ptp", ATTR{clock_name}=="KVM virtual PTP", SYMLINK += "ptp_kvm"
LABEL="default_end"
+++ /dev/null
-#!/bin/bash
-set -ex
-
-# keep this in sync with setup.sh
-CONTAINER=${RELEASE:-buster}-${ARCH:-amd64}
-AUTOPKGTESTDIR=${SEMAPHORE_CACHE_DIR:-/tmp}/autopkgtest
-# semaphore cannot expose these, but useful for interactive/local runs
-ARTIFACTS_DIR=/tmp/artifacts
-
-# add current debian/ packaging
-git fetch --depth=1 https://salsa.debian.org/systemd-team/systemd.git master
-git checkout FETCH_HEAD debian
-
-# craft changelog
-UPSTREAM_VER=$(git describe | sed 's/^v//')
-cat << EOF > debian/changelog.new
-systemd (${UPSTREAM_VER}-0) UNRELEASED; urgency=low
-
- * Automatic build for upstream test
-
- -- systemd test <pkg-systemd-maintainers@lists.alioth.debian.org> $(date -R)
-
-EOF
-cat debian/changelog >> debian/changelog.new
-mv debian/changelog.new debian/changelog
-
-# clean out patches
-rm -rf debian/patches
-# disable autopkgtests which are not for upstream
-sed -i '/# NOUPSTREAM/ q' debian/tests/control
-# enable more unit tests
-sed -i '/^CONFFLAGS =/ s/=/= -Dtests=unsafe -Dsplit-usr=true -Dslow-tests=true /' debian/rules
-# no orig tarball
-echo '1.0' > debian/source/format
-
-# build source package
-dpkg-buildpackage -S -I -I$(basename "$SEMAPHORE_CACHE_DIR") -d -us -uc -nc
-
-# now build the package and run the tests
-rm -rf "$ARTIFACTS_DIR"
-# autopkgtest exits with 2 for "some tests skipped", accept that
-$AUTOPKGTESTDIR/runner/autopkgtest --apt-upgrade \
- --env DEB_BUILD_OPTIONS=noudeb \
- --env TEST_UPSTREAM=1 ../systemd_*.dsc \
- -o "$ARTIFACTS_DIR" \
- -- lxc -s $CONTAINER \
- || [ $? -eq 2 ]
--- /dev/null
+#!/bin/bash
+
+set -eux
+
+# default to Debian testing
+DISTRO=${DISTRO:-debian}
+RELEASE=${RELEASE:-buster}
+ARCH=${ARCH:-amd64}
+CONTAINER=${RELEASE}-${ARCH}
+MAX_CACHE_AGE=604800 # one week
+CACHE_DIR=${SEMAPHORE_CACHE_DIR:=/tmp}
+CACHE="${CACHE_DIR}/${CONTAINER}.img.tar.gz"
+AUTOPKGTEST_DIR="${CACHE_DIR}/autopkgtest"
+# semaphore cannot expose these, but useful for interactive/local runs
+ARTIFACTS_DIR=/tmp/artifacts
+PHASES=(${@:-SETUP RUN})
+
+create_container() {
+ # create autopkgtest LXC image; this sometimes fails with "Unable to fetch
+ # GPG key from keyserver", so retry a few times
+ for retry in $(seq 5); do
+ sudo lxc-create -n $CONTAINER -t download -- -d $DISTRO -r $RELEASE -a $ARCH && break
+ sleep $((retry*retry))
+ done
+
+ # unconfine the container, otherwise some tests fail
+ echo 'lxc.apparmor.profile = unconfined' | sudo tee -a /var/lib/lxc/$CONTAINER/config
+
+ sudo lxc-start -n $CONTAINER
+
+ # enable source repositories so that apt-get build-dep works
+ sudo lxc-attach -n $CONTAINER -- sh -ex <<EOF
+sed 's/^deb/deb-src/' /etc/apt/sources.list >> /etc/apt/sources.list.d/sources.list
+# wait until online
+while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done
+apt-get -q update
+apt-get -y dist-upgrade
+apt-get install -y eatmydata
+EOF
+ sudo lxc-stop -n $CONTAINER
+
+ # cache it
+ sudo tar cpzf "$CACHE" /var/lib/lxc/$CONTAINER
+}
+
+for phase in "${PHASES[@]}"; do
+ case $phase in
+ SETUP)
+ # remove semaphore repos, some of them don't work and cause error messages
+ sudo rm -f /etc/apt/sources.list.d/*
+
+ # enable backports for latest LXC
+ echo 'deb http://archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse' | sudo tee -a /etc/apt/sources.list.d/backports.list
+ sudo apt-get -q update
+ sudo apt-get install -y -t xenial-backports lxc
+ sudo apt-get install -y python3-debian git dpkg-dev fakeroot
+
+ [ -d $AUTOPKGTEST_DIR ] || git clone --quiet --depth=1 https://salsa.debian.org/ci-team/autopkgtest.git "$AUTOPKGTEST_DIR"
+
+ # use cached container image, unless older than a week
+ if [ -e "$CACHE" ] && [ $(( $(date +%s) - $(stat -c %Y "$CACHE") )) -le $MAX_CACHE_AGE ]; then
+ sudo tar -C / -xpzf "$CACHE"
+ else
+ create_container
+ fi
+ ;;
+ RUN)
+ # add current debian/ packaging
+ git fetch --depth=1 https://salsa.debian.org/systemd-team/systemd.git master
+ git checkout FETCH_HEAD debian
+
+ # craft changelog
+ UPSTREAM_VER=$(git describe | sed 's/^v//')
+ cat << EOF > debian/changelog.new
+systemd (${UPSTREAM_VER}-0) UNRELEASED; urgency=low
+
+ * Automatic build for upstream test
+
+ -- systemd test <pkg-systemd-maintainers@lists.alioth.debian.org> $(date -R)
+
+EOF
+ cat debian/changelog >> debian/changelog.new
+ mv debian/changelog.new debian/changelog
+
+ # clean out patches
+ rm -rf debian/patches
+ # disable autopkgtests which are not for upstream
+ sed -i '/# NOUPSTREAM/ q' debian/tests/control
+ # enable more unit tests
+ sed -i '/^CONFFLAGS =/ s/=/= -Dtests=unsafe -Dsplit-usr=true -Dslow-tests=true /' debian/rules
+ # no orig tarball
+ echo '1.0' > debian/source/format
+
+ # build source package
+ dpkg-buildpackage -S -I -I$(basename "$CACHE_DIR") -d -us -uc -nc
+
+ # now build the package and run the tests
+ rm -rf "$ARTIFACTS_DIR"
+ # autopkgtest exits with 2 for "some tests skipped", accept that
+ $AUTOPKGTEST_DIR/runner/autopkgtest --apt-upgrade \
+ --env DEB_BUILD_OPTIONS=noudeb \
+ --env TEST_UPSTREAM=1 ../systemd_*.dsc \
+ -o "$ARTIFACTS_DIR" \
+ -- lxc -s $CONTAINER \
+ || [ $? -eq 2 ]
+ ;;
+ *)
+ echo >&2 "Unknown phase '$phase'"
+ exit 1
+ esac
+done
+++ /dev/null
-#!/bin/bash
-set -ex
-
-# default to Debian testing
-DISTRO=${DISTRO:-debian}
-RELEASE=${RELEASE:-buster}
-ARCH=${ARCH:-amd64}
-CONTAINER=${RELEASE}-${ARCH}
-MAX_CACHE_AGE=604800 # one week
-CACHE=${SEMAPHORE_CACHE_DIR:=/tmp}/${CONTAINER}.img.tar.gz
-
-create_container() {
- # create autopkgtest LXC image; this sometimes fails with "Unable to fetch
- # GPG key from keyserver", so retry a few times
- for retry in $(seq 5); do
- sudo lxc-create -n $CONTAINER -t download -- -d $DISTRO -r $RELEASE -a $ARCH && break
- sleep $((retry*retry))
- done
-
- # unconfine the container, otherwise some tests fail
- echo 'lxc.apparmor.profile = unconfined' | sudo tee -a /var/lib/lxc/$CONTAINER/config
-
- sudo lxc-start -n $CONTAINER
-
- # enable source repositories so that apt-get build-dep works
- sudo lxc-attach -n $CONTAINER -- sh -ex <<EOF
-sed 's/^deb/deb-src/' /etc/apt/sources.list >> /etc/apt/sources.list.d/sources.list
-# wait until online
-while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done
-apt-get -q update
-apt-get -y dist-upgrade
-apt-get install -y eatmydata
-EOF
- sudo lxc-stop -n $CONTAINER
-
- # cache it
- sudo tar cpzf "$CACHE" /var/lib/lxc/$CONTAINER
-}
-
-# remove semaphore repos, some of them don't work and cause error messages
-sudo rm -f /etc/apt/sources.list.d/*
-
-# enable backports for latest LXC
-echo 'deb http://archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse' | sudo tee -a /etc/apt/sources.list.d/backports.list
-sudo apt-get -q update
-sudo apt-get install -y -t xenial-backports lxc
-sudo apt-get install -y python3-debian git dpkg-dev fakeroot
-
-AUTOPKGTESTDIR=$SEMAPHORE_CACHE_DIR/autopkgtest
-[ -d $AUTOPKGTESTDIR ] || git clone --quiet --depth=1 https://salsa.debian.org/ci-team/autopkgtest.git "$AUTOPKGTESTDIR"
-
-# use cached container image, unless older than a week
-if [ -e "$CACHE" ] && [ $(( $(date +%s) - $(stat -c %Y "$CACHE") )) -le $MAX_CACHE_AGE ]; then
- sudo tar -C / -xpzf "$CACHE"
-else
- create_container
-fi
;;
--unit|-u)
comps=$(journalctl -F '_SYSTEMD_UNIT' 2>/dev/null)
+ compopt -o filenames
;;
--user-unit)
comps=$(journalctl -F '_SYSTEMD_USER_UNIT' 2>/dev/null)
return 0
;;
esac
- COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+ COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") )
return 0
fi
__get_machines() {
local a b
{ machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; } | \
- { while read a b; do echo " $a"; done; }
+ { while read a b; do echo " $a"; done; }
}
_systemctl () {
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
+ local cur_orig=$cur
local i verb comps mode
local -A OPTS=(
fi
done
+ # When trying to match a unit name with certain special characters in its name (i.e
+ # foo\x2dbar:01) they get escaped by bash along the way, thus causing any possible
+ # match to fail. Let's unescape such characters in the verb we're trying to
+ # autocomplete to avoid this, however, use the original verb (cur_orig)
+ # during the final match (COMPREPLY)
+ cur="$(echo $cur | xargs echo)"
+
if [[ -z $verb ]]; then
comps="${VERBS[*]}"
| { while read -r a b; do echo " $a"; done; } )
fi
- COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") )
+ COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur_orig") )
return 0
}
return (ssize_t) k;
}
+/* Put a limit on how many times will attempt to call accept4(). We loop
+ * only on "transient" errors, but let's make sure we don't loop forever. */
+#define MAX_FLUSH_ITERATIONS 1024
+
int flush_accept(int fd) {
struct pollfd pollfd = {
.fd = fd,
.events = POLLIN,
};
- int r;
+ int r, b;
+ socklen_t l = sizeof(b);
- /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
+ /* Similar to flush_fd() but flushes all incoming connections by accepting and immediately closing
+ * them. */
- for (;;) {
+ if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0)
+ return -errno;
+
+ assert(l == sizeof(b));
+ if (!b) /* Let's check if this socket accepts connections before calling accept(). accept4() can
+ * return EOPNOTSUPP if the fd is not a listening socket, which we should treat as a fatal
+ * error, or in case the incoming TCP connection triggered a network issue, which we want to
+ * treat as a transient error. Thus, let's rule out the first reason for EOPNOTSUPP early, so
+ * we can loop safely on transient errors below. */
+ return -ENOTTY;
+
+ for (unsigned iteration = 0;; iteration++) {
int cfd;
r = poll(&pollfd, 1, 0);
if (r == 0)
return 0;
+ if (iteration >= MAX_FLUSH_ITERATIONS)
+ return log_debug_errno(SYNTHETIC_ERRNO(EBUSY),
+ "Failed to flush connections within " STRINGIFY(MAX_FLUSH_ITERATIONS) " iterations.");
+
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (cfd < 0) {
if (errno == EAGAIN)
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;
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)
ARG_SIZE,
ARG_LIST,
ARG_VERBOSE,
+ ARG_XML_INTERFACE,
ARG_EXPECT_REPLY,
ARG_AUTO_START,
ARG_ALLOW_INTERACTIVE_AUTHORIZATION,
{ "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 },
arg_verbose = true;
break;
+ case ARG_XML_INTERFACE:
+ arg_xml_interface = true;
+ break;
+
case ARG_EXPECT_REPLY:
r = parse_boolean(optarg);
if (r < 0)
}
void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+ _cleanup_free_ char *disable_controllers_str = NULL;
CGroupIODeviceLimit *il;
CGroupIODeviceWeight *iw;
CGroupIODeviceLatency *l;
prefix = strempty(prefix);
+ (void) cg_mask_to_string(c->disable_controllers, &disable_controllers_str);
+
fprintf(f,
"%sCPUAccounting=%s\n"
"%sIOAccounting=%s\n"
"%sMemoryLimit=%" PRIu64 "\n"
"%sTasksMax=%" PRIu64 "\n"
"%sDevicePolicy=%s\n"
+ "%sDisableControllers=%s\n"
"%sDelegate=%s\n",
prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->io_accounting),
prefix, c->memory_limit,
prefix, c->tasks_max,
prefix, cgroup_device_policy_to_string(c->device_policy),
+ prefix, strnull(disable_controllers_str),
prefix, yes_no(c->delegate));
if (c->delegate) {
return 1;
- } else if (streq(name, "DelegateControllers")) {
+ } else if (STR_IN_SET(name, "DelegateControllers", "DisableControllers")) {
CGroupMask mask = 0;
- if (!UNIT_VTABLE(u)->can_delegate)
+ if (streq(name, "DelegateControllers") && !UNIT_VTABLE(u)->can_delegate)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
r = sd_bus_message_enter_container(message, 'a', "s");
if (r < 0)
return r;
- c->delegate = true;
- if (mask == 0)
- c->delegate_controllers = 0;
- else
- c->delegate_controllers |= mask;
+ if (streq(name, "DelegateControllers")) {
+
+ c->delegate = true;
+ if (mask == 0)
+ c->delegate_controllers = 0;
+ else
+ c->delegate_controllers |= mask;
+
+ unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
- unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
+ } else if (streq(name, "DisableControllers")) {
+
+ if (mask == 0)
+ c->disable_controllers = 0;
+ else
+ c->disable_controllers |= mask;
+
+ unit_write_settingf(u, flags, name, "%s=%s", name, strempty(t));
+ }
}
return 1;
return 1;
}
- if (u->transient && u->load_state == UNIT_STUB)
+ if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
return 0;
return true;
}
+static void service_force_watchdog(Service *s) {
+ if (!UNIT(s)->manager->service_watchdogs)
+ return;
+
+ log_unit_error(UNIT(s), "Watchdog request (last status: %s)!",
+ s->status_text ? s->status_text : "<unset>");
+
+ service_enter_signal(s, SERVICE_STOP_WATCHDOG, SERVICE_FAILURE_WATCHDOG);
+}
+
static void service_notify_message(
Unit *u,
const struct ucred *ucred,
}
/* Interpret WATCHDOG= */
- if (strv_find(tags, "WATCHDOG=1"))
- service_reset_watchdog(s);
+ e = strv_find_startswith(tags, "WATCHDOG=");
+ if (e) {
+ if (streq(e, "1"))
+ service_reset_watchdog(s);
+ else if (streq(e, "trigger"))
+ service_force_watchdog(s);
+ else
+ log_unit_warning(u, "Passed WATCHDOG= field is invalid, ignoring.");
+ }
e = strv_find_startswith(tags, "WATCHDOG_USEC=");
if (e) {
global:
sd_bus_close_unref;
} LIBSYSTEMD_240;
+
+LIBSYSTEMD_243 {
+global:
+ sd_bus_object_vtable_format;
+} LIBSYSTEMD_241;
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);
if (r < 0)
return r;
- r = sd_bus_message_new_method_return(m, &q);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append(q, "s", i->introspection);
- if (r < 0) {
- sd_bus_message_unref(q);
- return r;
- }
+ i->f = safe_fclose(i->f);
+ *ret = TAKE_PTR(i->introspection);
- *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);
}
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);
sd_bus_error *error) {
sd_bus_slot *s;
- void *u, *found_u;
+ void *u, *found_u = NULL;
int r;
assert(bus);
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);
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;
continue;
if (!streq_ptr(previous_interface, c->interface)) {
-
if (previous_interface)
fputs(" </interface>\n", intro.f);
r = introspect_write_interface(&intro, c->vtable);
if (r < 0)
- goto finish;
+ return r;
previous_interface = c->interface;
}
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;
- r = sd_bus_send(bus, reply, NULL);
+ 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)
- goto finish;
+ return bus_maybe_reply_error(m, r, &error);
+ if (r == 0)
+ /* nodes_modified == true */
+ return 0;
- r = 1;
+ r = sd_bus_message_new_method_return(m, &reply);
+ if (r < 0)
+ return r;
-finish:
- introspect_free(&intro);
- 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)
+ return r;
+
+ return 1;
}
static int object_manager_serialize_path(
/* 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 {
} 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;
}
}
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(
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") &&
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,
#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);
#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;
-}
-
-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;
-}
+#include "test-vtable-data.h"
-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;
+static void test_manual_introspection(const sd_bus_vtable vtable[]) {
+ struct introspect intro = {};
+ _cleanup_free_ char *s = NULL;
- test_setup_logging(LOG_DEBUG);
+ log_info("/* %s */", __func__);
assert_se(introspect_begin(&intro, false) >= 0);
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);
+}
+
+int main(int argc, char *argv[]) {
+ test_setup_logging(LOG_DEBUG);
- introspect_free(&intro);
+ 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;
}
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
#include <stdbool.h>
#include <stddef.h>
#undef NDEBUG
#include <assert.h>
#include <errno.h>
+#include <stdio.h>
#include "sd-bus-vtable.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;
-}
+#ifndef __cplusplus
+# include "bus-objects.h"
+#endif
-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;
-}
+#include "test-vtable-data.h"
-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 } },
- }
-};
+#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
static void test_vtable(void) {
sd_bus *bus = NULL;
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);
}
--- /dev/null
+/* 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 } },
+ }
+};
void *userdata) {
uint16_t *s = data;
- uint16_t port = 0;
int r;
assert(rvalue);
assert(data);
- if (!streq(rvalue, "auto")) {
- r = parse_ip_port(rvalue, s);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Invalid port specification, ignoring assignment: %s", rvalue);
- return 0;
- }
+ if (isempty(rvalue) || streq(rvalue, "auto")) {
+ *s = 0;
+ return 0;
+ }
+
+ r = parse_ip_port(rvalue, s);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Invalid port specification, ignoring assignment: %s", rvalue);
+ return 0;
}
- *s = port;
return 0;
}
if (operstate >= LINK_OPERSTATE_CARRIER) {
Link *slave;
- HASHMAP_FOREACH(slave, link->slaves, i) {
+ SET_FOREACH(slave, link->slaves, i) {
link_update_operstate(slave, false);
if (slave->operstate < LINK_OPERSTATE_CARRIER)
return 0;
}
-static void link_detach_from_manager(Link *link) {
- if (!link || !link->manager)
- return;
-
- hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
- set_remove(link->manager->links_requesting_uuid, link);
- link_clean(link);
-}
-
static Link *link_free(Link *link) {
- Link *carrier, *master;
+ Link *carrier;
Address *address;
Route *route;
Iterator i;
sd_ndisc_unref(link->ndisc);
sd_radv_unref(link->radv);
- link_detach_from_manager(link);
-
free(link->ifname);
-
free(link->kind);
(void) unlink(link->state_file);
hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
hashmap_free(link->bound_by_links);
- hashmap_free(link->slaves);
-
- if (link->network) {
- if (link->network->bond &&
- link_get(link->manager, link->network->bond->ifindex, &master) >= 0)
- (void) hashmap_remove(master->slaves, INT_TO_PTR(link->ifindex));
-
- if (link->network->bridge &&
- link_get(link->manager, link->network->bridge->ifindex, &master) >= 0)
- (void) hashmap_remove(master->slaves, INT_TO_PTR(link->ifindex));
- }
+ set_free_with_destructor(link->slaves, link_unref);
return mfree(link);
}
if (link->state == state)
return;
+ log_link_debug(link, "State changed: %s -> %s",
+ link_state_to_string(link->state),
+ link_state_to_string(state));
+
link->state = state;
link_send_changed(link, "AdministrativeState", NULL);
log_link_debug(link, "Setting MTU done.");
- if (link->state == LINK_STATE_PENDING)
+ if (link->state == LINK_STATE_INITIALIZED)
(void) link_configure_after_setting_mtu(link);
return 1;
return r;
}
-static int link_append_to_master(Link *link, NetDev *netdev) {
- Link *master;
- int r;
-
- assert(link);
- assert(netdev);
-
- r = link_get(link->manager, netdev->ifindex, &master);
- if (r < 0)
- return r;
-
- r = hashmap_ensure_allocated(&master->slaves, NULL);
- if (r < 0)
- return r;
-
- r = hashmap_put(master->slaves, INT_TO_PTR(link->ifindex), link);
- if (r < 0)
- return r;
-
- return 0;
-}
-
static int link_lldp_save(Link *link) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
return;
}
+static int link_append_to_master(Link *link, NetDev *netdev) {
+ Link *master;
+ int r;
+
+ assert(link);
+ assert(netdev);
+
+ r = link_get(link->manager, netdev->ifindex, &master);
+ if (r < 0)
+ return r;
+
+ r = set_ensure_allocated(&master->slaves, NULL);
+ if (r < 0)
+ return r;
+
+ r = set_put(master->slaves, link);
+ if (r < 0)
+ return r;
+
+ link_ref(link);
+ return 0;
+}
+
+static void link_drop_from_master(Link *link, NetDev *netdev) {
+ Link *master;
+
+ assert(link);
+
+ if (!link->manager || !netdev)
+ return;
+
+ if (link_get(link->manager, netdev->ifindex, &master) < 0)
+ return;
+
+ link_unref(set_remove(master->slaves, link));
+}
+
+static void link_detach_from_manager(Link *link) {
+ if (!link || !link->manager)
+ return;
+
+ link_unref(set_remove(link->manager->links_requesting_uuid, link));
+ link_clean(link);
+
+ /* The following must be called at last. */
+ assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
+ link_unref(link);
+}
+
void link_drop(Link *link) {
if (!link || link->state == LINK_STATE_LINGER)
return;
link_free_carrier_maps(link);
+ if (link->network) {
+ link_drop_from_master(link, link->network->bridge);
+ link_drop_from_master(link, link->network->bond);
+ }
+
log_link_debug(link, "Link removed");
(void) unlink(link->state_file);
-
link_detach_from_manager(link);
-
- link_unref(link);
-
- return;
}
static int link_joined(Link *link) {
assert(link);
assert(link->network);
- assert(link->state == LINK_STATE_PENDING);
+ assert(link->state == LINK_STATE_INITIALIZED);
link_set_state(link, LINK_STATE_CONFIGURING);
assert(link);
assert(link->network);
- assert(link->state == LINK_STATE_PENDING);
+ assert(link->state == LINK_STATE_INITIALIZED);
if (STRPTR_IN_SET(link->kind, "can", "vcan"))
return link_configure_can(link);
assert(link);
assert(link->network);
- assert(link->state == LINK_STATE_PENDING);
+ assert(link->state == LINK_STATE_INITIALIZED);
if (link->setting_mtu)
return 0;
assert(link->ifname);
assert(link->manager);
- if (link->state != LINK_STATE_PENDING)
+ /* We may get called either from the asynchronous netlink callback,
+ * or directly for link_add() if running in a container. See link_add(). */
+ if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED))
return 1;
log_link_debug(link, "Link state is up-to-date");
+ link_set_state(link, LINK_STATE_INITIALIZED);
r = link_new_bound_by_list(link);
if (r < 0)
return 0;
log_link_debug(link, "udev initialized link");
+ link_set_state(link, LINK_STATE_INITIALIZED);
link->sd_device = sd_device_ref(device);
static const char* const link_state_table[_LINK_STATE_MAX] = {
[LINK_STATE_PENDING] = "pending",
+ [LINK_STATE_INITIALIZED] = "initialized",
[LINK_STATE_CONFIGURING] = "configuring",
[LINK_STATE_CONFIGURED] = "configured",
[LINK_STATE_UNMANAGED] = "unmanaged",
#include "set.h"
typedef enum LinkState {
- LINK_STATE_PENDING,
- LINK_STATE_CONFIGURING,
- LINK_STATE_CONFIGURED,
- LINK_STATE_UNMANAGED,
- LINK_STATE_FAILED,
- LINK_STATE_LINGER,
+ LINK_STATE_PENDING, /* udev has not initialized the link */
+ LINK_STATE_INITIALIZED, /* udev has initialized the link */
+ LINK_STATE_CONFIGURING, /* configuring addresses, routes, etc. */
+ LINK_STATE_CONFIGURED, /* everything is configured */
+ LINK_STATE_UNMANAGED, /* Unmanaged=yes is set */
+ LINK_STATE_FAILED, /* at least one configuration process failed */
+ LINK_STATE_LINGER, /* RTM_DELLINK for the link has been received */
_LINK_STATE_MAX,
_LINK_STATE_INVALID = -1
} LinkState;
Hashmap *bound_by_links;
Hashmap *bound_to_links;
- Hashmap *slaves;
+ Set *slaves;
} Link;
typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*);
}
m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
- m->links = hashmap_free(m->links);
- m->links_requesting_uuid = set_free(m->links_requesting_uuid);
- set_free(m->duids_requesting_uuid);
+ m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref);
+ m->links = hashmap_free_with_destructor(m->links, link_unref);
+ m->duids_requesting_uuid = set_free(m->duids_requesting_uuid);
while ((network = m->networks))
network_free(network);
-
hashmap_free(m->networks_by_name);
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
assert(network);
assert(network->filename);
+ if (set_isempty(network->match_mac) && strv_isempty(network->match_path) &&
+ strv_isempty(network->match_driver) && strv_isempty(network->match_type) &&
+ strv_isempty(network->match_name) && !network->conditions)
+ log_warning("%s: No valid settings found in the [Match] section. "
+ "The file will match all interfaces. "
+ "If that is intended, please add Name=* in the [Match] section.",
+ network->filename);
+
/* skip out early if configuration does not match the environment */
if (!condition_test_list(network->conditions, NULL, NULL, NULL))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
assert_se(network = new0(Network, 1));
assert_se(network->filename = strdup("hogehoge.network"));
+ assert_se(config_parse_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0);
assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
assert_se(network->n_static_addresses == 1);
assert_se(network_verify(network) >= 0);
return boot_entries_load_config(esp_where, xbootldr_where, config);
}
+#if ENABLE_EFI
int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
-
static const char * const title_table[] = {
/* Pretty names for a few well-known automatically discovered entries. */
"auto-osx", "macOS",
return 0;
}
+#endif
/********************************************************************************/
void boot_config_free(BootConfig *config);
int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
int boot_entries_load_config_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config);
+#if ENABLE_EFI
int boot_entries_augment_from_loader(BootConfig *config, bool only_auto);
+#else
+static inline int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
+ return -EOPNOTSUPP;
+}
+#endif
static inline const char* boot_entry_title(const BootEntry *entry) {
return entry->show_title ?: entry->title ?: entry->id;
return bus_append_cg_blkio_weight_parse(m, field, eq);
+ if (streq(field, "DisableControllers"))
+
+ return bus_append_strv(m, "DisableControllers", eq, EXTRACT_QUOTES);
+
if (streq(field, "Delegate")) {
r = parse_boolean(eq);
return -EOPNOTSUPP;
}
+static inline char* efi_variable_path(sd_id128_t vendor, const char *name) {
+ return NULL;
+}
+
static inline int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size) {
return -EOPNOTSUPP;
}
_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 */
struct {
size_t element_size;
uint64_t features;
+ const unsigned *vtable_format_reference;
} start;
struct {
const char *member;
.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, \
}, \
}, \
}
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;
}''')
[],
[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'],
[],
[]],
[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'],
[],
[]],
assert_se(fd == -999);
}
+static void test_flush_accept(void) {
+ _cleanup_close_ int listen_stream = -1, listen_dgram = -1, listen_seqpacket = 1, connect_stream = -1, connect_dgram = -1, connect_seqpacket = -1;
+ static const union sockaddr_union sa = { .un.sun_family = AF_UNIX };
+ union sockaddr_union lsa;
+ socklen_t l;
+
+ listen_stream = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(listen_stream >= 0);
+
+ listen_dgram = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(listen_dgram >= 0);
+
+ listen_seqpacket = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(listen_seqpacket >= 0);
+
+ assert_se(flush_accept(listen_stream) < 0);
+ assert_se(flush_accept(listen_dgram) < 0);
+ assert_se(flush_accept(listen_seqpacket) < 0);
+
+ assert_se(bind(listen_stream, &sa.sa, sizeof(sa_family_t)) >= 0);
+ assert_se(bind(listen_dgram, &sa.sa, sizeof(sa_family_t)) >= 0);
+ assert_se(bind(listen_seqpacket, &sa.sa, sizeof(sa_family_t)) >= 0);
+
+ assert_se(flush_accept(listen_stream) < 0);
+ assert_se(flush_accept(listen_dgram) < 0);
+ assert_se(flush_accept(listen_seqpacket) < 0);
+
+ assert_se(listen(listen_stream, SOMAXCONN) >= 0);
+ assert_se(listen(listen_dgram, SOMAXCONN) < 0);
+ assert_se(listen(listen_seqpacket, SOMAXCONN) >= 0);
+
+ assert_se(flush_accept(listen_stream) >= 0);
+ assert_se(flush_accept(listen_dgram) < 0);
+ assert_se(flush_accept(listen_seqpacket) >= 0);
+
+ connect_stream = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(connect_stream >= 0);
+
+ connect_dgram = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(connect_dgram >= 0);
+
+ connect_seqpacket = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ assert_se(connect_seqpacket >= 0);
+
+ l = sizeof(lsa);
+ assert_se(getsockname(listen_stream, &lsa.sa, &l) >= 0);
+ assert_se(connect(connect_stream, &lsa.sa, l) >= 0);
+
+ l = sizeof(lsa);
+ assert_se(getsockname(listen_dgram, &lsa.sa, &l) >= 0);
+ assert_se(connect(connect_dgram, &lsa.sa, l) >= 0);
+
+ l = sizeof(lsa);
+ assert_se(getsockname(listen_seqpacket, &lsa.sa, &l) >= 0);
+ assert_se(connect(connect_seqpacket, &lsa.sa, l) >= 0);
+
+ assert_se(flush_accept(listen_stream) >= 0);
+ assert_se(flush_accept(listen_dgram) < 0);
+ assert_se(flush_accept(listen_seqpacket) >= 0);
+}
+
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_receive_nopassfd();
test_send_nodata_nofd();
test_send_emptydata();
+ test_flush_accept();
return 0;
}
if (link->speed > UINT_MAX)
return -ERANGE;
+ if (set_isempty(link->match_mac) && strv_isempty(link->match_path) &&
+ strv_isempty(link->match_driver) && strv_isempty(link->match_type) &&
+ strv_isempty(link->match_name) && !link->conditions)
+ log_warning("%s: No valid settings found in the [Match] section. "
+ "The file will match all interfaces. "
+ "If that is intended, please add OriginalName=* in the [Match] section.",
+ filename);
+
if (!condition_test_list(link->conditions, NULL, NULL, NULL)) {
log_debug("%s: Conditions do not match the system environment, skipping.", filename);
return 0;
{ "v238", NAMING_V238 },
{ "v239", NAMING_V239 },
{ "v240", NAMING_V240 },
+ { "v243", NAMING_V243 },
/* … add more schemes here, as the logic to name devices is updated … */
};
NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df887797c9e05074a562ddacdcdf5e */
NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Allow zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */
+ NAMING_NETDEVSIM = 1 << 5, /* Allow re-renaming of netdevsim devices */
/* And now the masks that combine the features above */
NAMING_V238 = 0,
NAMING_V239 = NAMING_V238 | NAMING_SR_IOV_V | NAMING_NPAR_ARI,
NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES,
+ NAMING_V243 = NAMING_V240 | NAMING_NETDEVSIM,
_NAMING_SCHEME_FLAGS_INVALID = -1,
} NamingSchemeFlags;
* — USB port number chain
* v<slot> - VIO slot number (IBM PowerVM)
* a<vendor><model>i<instance> — Platform bus ACPI instance id
+ * i<addr>n<phys_port_name> — Netdevsim bus address and port name
*
* All multi-function PCI devices will carry the [f<function>] number in the
* device name, including the function 0 device.
NET_CCW,
NET_VIO,
NET_PLATFORM,
+ NET_NETDEVSIM,
};
struct netnames {
char ccw_busid[IFNAMSIZ];
char vio_slot[IFNAMSIZ];
char platform_path[IFNAMSIZ];
+ char netdevsim_path[IFNAMSIZ];
};
struct virtfn_info {
return 0;
}
+static int names_netdevsim(sd_device *dev, struct netnames *names) {
+ sd_device *netdevsimdev;
+ const char *sysname;
+ unsigned addr;
+ const char *port_name = NULL;
+ int r;
+ bool ok;
+
+ if (!naming_scheme_has(NAMING_NETDEVSIM))
+ return 0;
+
+ assert(dev);
+ assert(names);
+
+ r = sd_device_get_parent_with_subsystem_devtype(dev, "netdevsim", NULL, &netdevsimdev);
+ if (r < 0)
+ return r;
+ r = sd_device_get_sysname(netdevsimdev, &sysname);
+ if (r < 0)
+ return r;
+
+ if (sscanf(sysname, "netdevsim%u", &addr) != 1)
+ return -EINVAL;
+
+ r = sd_device_get_sysattr_value(dev, "phys_port_name", &port_name);
+ if (r < 0)
+ return r;
+
+ ok = snprintf_ok(names->netdevsim_path, sizeof(names->netdevsim_path), "i%un%s", addr, port_name);
+ if (!ok)
+ return -ENOBUFS;
+
+ names->type = NET_NETDEVSIM;
+
+ return 0;
+}
+
/* IEEE Organizationally Unique Identifier vendor string */
static int ieee_oui(sd_device *dev, struct netnames *names, bool test) {
char str[32];
return 0;
}
+ /* get netdevsim path names */
+ if (names_netdevsim(dev, &names) >= 0 && names.type == NET_NETDEVSIM) {
+ char str[IFNAMSIZ];
+
+ if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.netdevsim_path))
+ udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str);
+
+ return 0;
+ }
+
/* get PCI based path names, we compose only PCI based paths */
if (names_pci(dev, &names) < 0)
return 0;
case TK_A_RUN_BUILTIN:
case TK_A_RUN_PROGRAM: {
_cleanup_free_ char *cmd = NULL;
-
+
if (event->run_final)
break;
if (cur->key.op == OP_ASSIGN_FINAL)
StopWhenUnneeded=yes
[Service]
-
Type=simple
+TimeoutStartSec=infinity
ExecStartPre=/assess.sh
ExecStart=/bin/true
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
print(output)
- self.assertTrue(output, ' mtu 2004 ')
+ self.assertRegex(output, ' mtu 2004 ')
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
print(output)
- self.assertTrue(output, ' mtu 2000 ')
- self.assertTrue(output, 'REORDER_HDR')
- self.assertTrue(output, 'LOOSE_BINDING')
- self.assertTrue(output, 'GVRP')
- self.assertTrue(output, 'MVRP')
- self.assertTrue(output, ' id 99 ')
+ self.assertRegex(output, ' mtu 2000 ')
+ self.assertRegex(output, 'REORDER_HDR')
+ self.assertRegex(output, 'LOOSE_BINDING')
+ self.assertRegex(output, 'GVRP')
+ self.assertRegex(output, 'MVRP')
+ self.assertRegex(output, ' id 99 ')
output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
print(output)
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
print(output)
- self.assertTrue(output, ' mtu 2000 ')
+ self.assertRegex(output, ' mtu 2000 ')
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvlan99']).rstrip().decode('utf-8')
print(output)
- self.assertTrue(output, ' mtu 2000 ')
+ self.assertRegex(output, ' mtu 2000 ')
@expectedFailureIfModuleIsNotAvailable('ipvlan')
def test_ipvlan(self):
subprocess.call('wg')
output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
- self.assertTrue(output, '51820')
+ self.assertRegex(output, '51820')
output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
- self.assertTrue(output, '0x4d2')
+ self.assertRegex(output, '0x4d2')
output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
- self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
- self.assertTrue(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
+ self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
+ self.assertRegex(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
- self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20')
+ self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
- self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820')
+ self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
output = subprocess.check_output(['wg', 'show', 'wg99', 'private-key']).rstrip().decode('utf-8')
- self.assertTrue(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong=')
+ self.assertRegex(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
output = subprocess.check_output(['wg', 'show', 'wg99', 'preshared-keys']).rstrip().decode('utf-8')
- self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
- self.assertTrue(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
+ self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
+ self.assertRegex(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
output = subprocess.check_output(['wg', 'show', 'wg98', 'private-key']).rstrip().decode('utf-8')
- self.assertTrue(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr+WHtZLZ90FU=')
+ self.assertRegex(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
def test_geneve(self):
self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
print(output)
- self.assertTrue(output, '192.168.22.1')
- self.assertTrue(output, '6082')
- self.assertTrue(output, 'udpcsum')
- self.assertTrue(output, 'udp6zerocsumrx')
+ self.assertRegex(output, '192.168.22.1')
+ self.assertRegex(output, '6082')
+ self.assertRegex(output, 'udpcsum')
+ self.assertRegex(output, 'udp6zerocsumrx')
def test_ipip_tunnel(self):
self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network',