]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #12332 from cdown/default_min
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 25 Apr 2019 09:06:45 +0000 (11:06 +0200)
committerGitHub <noreply@github.com>
Thu, 25 Apr 2019 09:06:45 +0000 (11:06 +0200)
cgroup: Add support for propagation of memory.min

56 files changed:
NEWS
catalog/systemd.pl.catalog.in
docs/TRANSIENT-SETTINGS.md
hwdb/60-evdev.hwdb
hwdb/60-keyboard.hwdb
man/busctl.xml
man/rules/meson.build
man/sd-bus.xml
man/sd_bus_add_object_vtable.xml [new file with mode: 0644]
man/sd_notify.xml
man/systemd.exec.xml
man/systemd.link.xml
man/systemd.network.xml
man/vtable-example.c [new file with mode: 0644]
man/vtable-example.xml [new file with mode: 0644]
network/99-default.link
rules/50-udev-default.rules.in
semaphoreci/gcc-compilation.sh [deleted file]
semaphoreci/semaphore-runner.sh [new file with mode: 0755]
semaphoreci/setup.sh [deleted file]
shell-completion/bash/journalctl
shell-completion/bash/systemctl.in
src/basic/socket-util.c
src/busctl/busctl.c
src/core/cgroup.c
src/core/dbus-cgroup.c
src/core/service.c
src/libsystemd/libsystemd.sym
src/libsystemd/sd-bus/bus-introspect.c
src/libsystemd/sd-bus/bus-introspect.h
src/libsystemd/sd-bus/bus-objects.c
src/libsystemd/sd-bus/bus-objects.h
src/libsystemd/sd-bus/test-bus-introspect.c
src/libsystemd/sd-bus/test-bus-vtable.c
src/libsystemd/sd-bus/test-vtable-data.h [new file with mode: 0644]
src/network/netdev/wireguard.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-manager.c
src/network/networkd-network.c
src/network/test-networkd-conf.c
src/shared/bootspec.c
src/shared/bootspec.h
src/shared/bus-unit-util.c
src/shared/efivars.h
src/systemd/sd-bus-vtable.h
src/test/generate-sym-test.py
src/test/meson.build
src/test/test-socket-util.c
src/udev/net/link-config.c
src/udev/net/naming-scheme.c
src/udev/net/naming-scheme.h
src/udev/udev-builtin-net_id.c
src/udev/udev-rules.c
test/TEST-16-EXTEND-TIMEOUT/testsuite.service
test/test-network/systemd-networkd-tests.py

diff --git a/NEWS b/NEWS
index 4df29b90e980e696647d886d05795b2c8a580ac2..f00ed133280b81a22151b809886f3960c04a650d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -242,8 +242,9 @@ CHANGES WITH 242:
           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
index b6c6b542053f5b048d8d6f46c5633408c705de12..b007ad1f056afa43d157ee943a1385b7d71acc18 100644 (file)
@@ -388,3 +388,17 @@ Możliwe są następujące „etykiety”:
   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@.
index 798793f3eefc4495decbe31d927fd6b95cda00d7..3aa68c0a2629d18766547f5d33545f4f06601294 100644 (file)
@@ -253,6 +253,7 @@ All cgroup/resource control settings are available for transient units
 ✓ TasksAccounting=
 ✓ TasksMax=
 ✓ Delegate=
+✓ DisableControllers=
 ✓ IPAccounting=
 ✓ IPAddressAllow=
 ✓ IPAddressDeny=
index 4f94342a095bdd62e2cf1db33e33a989d24b2b5b..d3664f4f09b69e6409867d43746370179e5335a6 100644 (file)
@@ -232,6 +232,13 @@ evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLati
  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
index 71aecd8a5320b8177e039ff0b402f9759430e0c7..4762c68a1b2e65c83ec7f331fcb79622263ed3db 100644 (file)
@@ -1036,8 +1036,12 @@ evdev:name:MSI Laptop hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnM[iI][cC][rR][oO]-S[tT][a
 # 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
@@ -1082,15 +1086,15 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOLPC:pnXO:*
  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
index e4c7fcb283ae4371ffeed986e364433cd8057097..328c1016227a635adb7d90037d47d7fd0da7eed5 100644 (file)
         </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>
 
index 9674cbb30b3be765a1bc0daf055a11c413883104..689415846642c523fbbec7e014d13bde84095da4 100644 (file)
@@ -115,6 +115,21 @@ manpages = [
    'sd_bus_match_signal',
    'sd_bus_match_signal_async'],
   ''],
+ ['sd_bus_add_object_vtable',
+  '3',
+  ['SD_BUS_METHOD',
+   'SD_BUS_METHOD_WITH_NAMES',
+   'SD_BUS_METHOD_WITH_NAMES_OFFSET',
+   'SD_BUS_METHOD_WITH_OFFSET',
+   'SD_BUS_PARAM',
+   'SD_BUS_PROPERTY',
+   'SD_BUS_SIGNAL',
+   'SD_BUS_SIGNAL_WITH_NAMES',
+   'SD_BUS_VTABLE_END',
+   'SD_BUS_VTABLE_START',
+   'SD_BUS_WRITABLE_PROPERTY',
+   'sd_bus_add_fallback_vtable'],
+  ''],
  ['sd_bus_attach_event', '3', ['sd_bus_detach_event', 'sd_bus_get_event'], ''],
  ['sd_bus_close', '3', ['sd_bus_flush'], ''],
  ['sd_bus_creds_get_pid',
index 6c925e316199c52fb2aa4a919fea362183957f70..e9a66d87ddda2e438e872cd5d3492e4c172fc720 100644 (file)
@@ -41,6 +41,7 @@
 
     <para>See
     <literallayout><citerefentry><refentrytitle>sd_bus_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+<citerefentry><refentrytitle>sd_bus_add_object_vtable</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
 <citerefentry><refentrytitle>sd_bus_attach_event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
 <citerefentry><refentrytitle>sd_bus_creds_get_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
 <citerefentry><refentrytitle>sd_bus_creds_new_from_pid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/man/sd_bus_add_object_vtable.xml b/man/sd_bus_add_object_vtable.xml
new file mode 100644 (file)
index 0000000..92be236
--- /dev/null
@@ -0,0 +1,473 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="sd_bus_add_object_vtable"
+          xmlns:xi="http://www.w3.org/2001/XInclude">
+
+  <refentryinfo>
+    <title>sd_bus_add_object_vtable</title>
+    <productname>systemd</productname>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>sd_bus_add_object_vtable</refentrytitle>
+    <manvolnum>3</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>sd_bus_add_object_vtable</refname>
+    <refname>sd_bus_add_fallback_vtable</refname>
+    <refname>SD_BUS_VTABLE_START</refname>
+    <refname>SD_BUS_VTABLE_END</refname>
+    <refname>SD_BUS_METHOD_WITH_NAMES_OFFSET</refname>
+    <refname>SD_BUS_METHOD_WITH_NAMES</refname>
+    <refname>SD_BUS_METHOD_WITH_OFFSET</refname>
+    <refname>SD_BUS_METHOD</refname>
+    <refname>SD_BUS_SIGNAL_WITH_NAMES</refname>
+    <refname>SD_BUS_SIGNAL</refname>
+    <refname>SD_BUS_WRITABLE_PROPERTY</refname>
+    <refname>SD_BUS_PROPERTY</refname>
+    <refname>SD_BUS_PARAM</refname>
+
+    <refpurpose>Declare properties and methods for a D-Bus path</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;systemd/sd-bus-vtable.h&gt;</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>
index 0084bf388298a342a93dc9c0027c286d000c35b3..00640cb290d1f0bf6c42d9c8a727e255f45986c7 100644 (file)
         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>
 
index df1e1e8681518aab443669dd45cef42761934bca..b69691b3c48ce93ed73471e93da82a65ba82d247 100644 (file)
         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>
 
@@ -822,23 +829,25 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
         <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>
@@ -1053,7 +1062,7 @@ StateDirectory=aaa/bbb ccc</programlisting>
 
         <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
index af9799e8c02a41e4c8556ff37848a849ba2f5ef1..ea744bd2517a7d3f829a402a1658f2dfb0aec2cd 100644 (file)
   <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>
index 2d8eeee88fb37c1c0a83a16890e88932eb95c8fe..be982cbb1aa7a64251fc1a74306431e69ac75182 100644 (file)
       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>
diff --git a/man/vtable-example.c b/man/vtable-example.c
new file mode 100644 (file)
index 0000000..a2a6cd1
--- /dev/null
@@ -0,0 +1,70 @@
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <systemd/sd-bus.h>
+
+#define _cleanup_(f) __attribute__((cleanup(f)))
+
+typedef struct object {
+  char *name;
+  uint32_t number;
+} object;
+
+static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+  printf("Got called with userdata=%p\n", userdata);
+  return 1;
+}
+
+static const sd_bus_vtable vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_METHOD(
+            "Method1", "s", "s", method, 0),
+        SD_BUS_METHOD_WITH_NAMES_OFFSET(
+            "Method2",
+            "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
+            "s", SD_BUS_PARAM(returnstring),
+            method, offsetof(object, number),
+            SD_BUS_VTABLE_DEPRECATED),
+        SD_BUS_WRITABLE_PROPERTY(
+            "AutomaticStringProperty", "s", NULL, NULL,
+            offsetof(object, name),
+            SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_WRITABLE_PROPERTY(
+            "AutomaticIntegerProperty", "u", NULL, NULL,
+            offsetof(object, number),
+            SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+        SD_BUS_VTABLE_END
+};
+
+#define check(x) ({                             \
+  int r = x;                                    \
+  errno = r < 0 ? -r : 0;                       \
+  printf(#x ": %m\n");                          \
+  if (r < 0)                                    \
+    return EXIT_FAILURE;                        \
+  })
+
+int main(int argc, char **argv) {
+  _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+
+  sd_bus_default(&bus);
+
+  object object = { .number = 666 };
+  check((object.name = strdup("name")) != NULL);
+
+  check(sd_bus_add_object_vtable(bus, NULL, "/object",
+                                 "org.freedesktop.systemd.VtableExample",
+                                 vtable,
+                                 &object));
+
+  while (true) {
+    check(sd_bus_wait(bus, UINT64_MAX));
+    check(sd_bus_process(bus, NULL));
+  }
+
+  free(object.name);
+
+  return 0;
+}
diff --git a/man/vtable-example.xml b/man/vtable-example.xml
new file mode 100644 (file)
index 0000000..a3cdeae
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.freedesktop.DBus.Peer">
+  <method name="Ping"/>
+  <method name="GetMachineId">
+   <arg type="s" name="machine_uuid" direction="out"/>
+  </method>
+ </interface>
+ <interface name="org.freedesktop.DBus.Introspectable">
+  <method name="Introspect">
+   <arg name="data" type="s" direction="out"/>
+  </method>
+ </interface>
+ <interface name="org.freedesktop.DBus.Properties">
+  <method name="Get">
+   <arg name="interface" direction="in" type="s"/>
+   <arg name="property" direction="in" type="s"/>
+   <arg name="value" direction="out" type="v"/>
+  </method>
+  <method name="GetAll">
+   <arg name="interface" direction="in" type="s"/>
+   <arg name="properties" direction="out" type="a{sv}"/>
+  </method>
+  <method name="Set">
+   <arg name="interface" direction="in" type="s"/>
+   <arg name="property" direction="in" type="s"/>
+   <arg name="value" direction="in" type="v"/>
+  </method>
+  <signal name="PropertiesChanged">
+   <arg type="s" name="interface"/>
+   <arg type="a{sv}" name="changed_properties"/>
+   <arg type="as" name="invalidated_properties"/>
+  </signal>
+ </interface>
+ <interface name="org.freedesktop.systemd.VtableExample">
+  <method name="Method1">
+   <arg type="s" direction="in"/>
+   <arg type="s" direction="out"/>
+  </method>
+  <method name="Method2">
+   <arg type="s" name="string" direction="in"/>
+   <arg type="o" name="path" direction="in"/>
+   <arg type="s" name="returnstring" direction="out"/>
+   <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
+  </method>
+  <property name="AutomaticStringProperty" type="s" access="readwrite">
+  </property>
+  <property name="AutomaticIntegerProperty" type="u" access="readwrite">
+   <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="invalidates"/>
+  </property>
+ </interface>
+</node>
+
index 92fcbe83eab91751854094023ff4d9c602378c98..347d4b72d2709816ec185303e430d526e9e1a713 100644 (file)
@@ -7,6 +7,9 @@
 #  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
index 191f56f42ea445ed0e70f532e7e1efe99fbd0f9c..580b8971a6687058c4c510c7de3ae869ce43154f 100644 (file)
@@ -81,6 +81,8 @@ KERNEL=="fuse", MODE="0666", OPTIONS+="static_node=fuse"
 # 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"
diff --git a/semaphoreci/gcc-compilation.sh b/semaphoreci/gcc-compilation.sh
deleted file mode 100755 (executable)
index ef499b8..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/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 ]
diff --git a/semaphoreci/semaphore-runner.sh b/semaphoreci/semaphore-runner.sh
new file mode 100755 (executable)
index 0000000..5117bb4
--- /dev/null
@@ -0,0 +1,111 @@
+#!/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
diff --git a/semaphoreci/setup.sh b/semaphoreci/setup.sh
deleted file mode 100755 (executable)
index c39238a..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/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
index 52ed2e3bcb9c8c32dd42bb985df0069d4db898af..53ffaacdb55b66dbead1d50aefb321a0c69c4b88 100644 (file)
@@ -86,6 +86,7 @@ _journalctl() {
                 ;;
             --unit|-u)
                 comps=$(journalctl -F '_SYSTEMD_UNIT' 2>/dev/null)
+                compopt -o filenames
                 ;;
             --user-unit)
                 comps=$(journalctl -F '_SYSTEMD_USER_UNIT' 2>/dev/null)
@@ -100,7 +101,7 @@ _journalctl() {
                 return 0
                 ;;
         esac
-        COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
+        COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") )
         return 0
     fi
 
index 8c86fed9746739eea94ff1a227f625ae4fc7735f..dfb2d4a4c9e9d1a3b3c4617e1cf9dbda3e3a9bb4 100644 (file)
@@ -114,11 +114,12 @@ __get_all_unit_files () { { __systemctl $1 list-unit-files "$2*"; } | { while re
 __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=(
@@ -221,6 +222,13 @@ _systemctl () {
         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[*]}"
 
@@ -306,7 +314,7 @@ _systemctl () {
                      | { 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
 }
 
index 904bafb76f92362d29e0343d791cbfe8df6760b1..32a0d9c5d060ec21b123e69dc13091ad1cb92bd8 100644 (file)
@@ -1219,17 +1219,34 @@ fallback:
         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);
@@ -1242,6 +1259,10 @@ int flush_accept(int fd) {
                 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)
index 02f12dc70138bd466f6caeb6603bf9eb6f98ea37..86efc02bd8c32da09721c9d44001c2d8aff9915c 100644 (file)
@@ -50,6 +50,7 @@ static size_t arg_snaplen = 4096;
 static bool arg_list = false;
 static bool arg_quiet = false;
 static bool arg_verbose = false;
+static bool arg_xml_interface = false;
 static bool arg_expect_reply = true;
 static bool arg_auto_start = true;
 static bool arg_allow_interactive_authorization = true;
@@ -948,6 +949,12 @@ static int introspect(int argc, char **argv, void *userdata) {
         if (r < 0)
                 return bus_log_parse_error(r);
 
+        if (arg_xml_interface) {
+                /* Just dump the received XML and finish */
+                puts(xml);
+                return 0;
+        }
+
         /* First, get list of all properties */
         r = parse_xml_introspect(argv[2], xml, &ops, members);
         if (r < 0)
@@ -2255,6 +2262,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_SIZE,
                 ARG_LIST,
                 ARG_VERBOSE,
+                ARG_XML_INTERFACE,
                 ARG_EXPECT_REPLY,
                 ARG_AUTO_START,
                 ARG_ALLOW_INTERACTIVE_AUTHORIZATION,
@@ -2284,6 +2292,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "list",                            no_argument,       NULL, ARG_LIST                            },
                 { "quiet",                           no_argument,       NULL, 'q'                                 },
                 { "verbose",                         no_argument,       NULL, ARG_VERBOSE                         },
+                { "xml-interface",                   no_argument,       NULL, ARG_XML_INTERFACE                   },
                 { "expect-reply",                    required_argument, NULL, ARG_EXPECT_REPLY                    },
                 { "auto-start",                      required_argument, NULL, ARG_AUTO_START                      },
                 { "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION },
@@ -2388,6 +2397,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_verbose = true;
                         break;
 
+                case ARG_XML_INTERFACE:
+                        arg_xml_interface = true;
+                        break;
+
                 case ARG_EXPECT_REPLY:
                         r = parse_boolean(optarg);
                         if (r < 0)
index 3cf6b53ff2d3ca8ac066d07d027fa53828315ad6..946fab24c2c15c7313fe62b351c89a34615d19d3 100644 (file)
@@ -202,6 +202,7 @@ void cgroup_context_done(CGroupContext *c) {
 }
 
 void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
+        _cleanup_free_ char *disable_controllers_str = NULL;
         CGroupIODeviceLimit *il;
         CGroupIODeviceWeight *iw;
         CGroupIODeviceLatency *l;
@@ -217,6 +218,8 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
 
         prefix = strempty(prefix);
 
+        (void) cg_mask_to_string(c->disable_controllers, &disable_controllers_str);
+
         fprintf(f,
                 "%sCPUAccounting=%s\n"
                 "%sIOAccounting=%s\n"
@@ -244,6 +247,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 "%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),
@@ -271,6 +275,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 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) {
index c8fcf448ede70dd9564c4c6f06767f39a3f07567..c427c3cafe060f15098a5b1de57160c2f7ba6703 100644 (file)
@@ -401,10 +401,10 @@ static int bus_cgroup_set_transient_property(
 
                 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");
@@ -439,13 +439,25 @@ static int bus_cgroup_set_transient_property(
                         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;
@@ -1432,7 +1444,7 @@ int bus_cgroup_set_property(
                 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;
index c4d837855785fc8737574e9a251e796d8ad37eda..56667f03e851c4e0649e662789860fff48ad391a 100644 (file)
@@ -3742,6 +3742,16 @@ static bool service_notify_message_authorized(Service *s, pid_t pid, char **tags
         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,
@@ -3888,8 +3898,15 @@ static void service_notify_message(
         }
 
         /* 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) {
index a6748ceb209cd7845851d2bb478d2b42b16bc00f..a9ab0605ce14427d8b0219e91d7b0014fd1b14a9 100644 (file)
@@ -676,3 +676,8 @@ LIBSYSTEMD_241 {
 global:
         sd_bus_close_unref;
 } LIBSYSTEMD_240;
+
+LIBSYSTEMD_243 {
+global:
+        sd_bus_object_vtable_format;
+} LIBSYSTEMD_241;
index 022eddb10f66a1e90675b6c5b84fafb78dd34e79..beab80687d6f1a6e370f3ee2009d6d3924cbee34 100644 (file)
@@ -172,13 +172,10 @@ int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
         return 0;
 }
 
-int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply) {
-        sd_bus_message *q;
+int introspect_finish(struct introspect *i, char **ret) {
         int r;
 
         assert(i);
-        assert(m);
-        assert(reply);
 
         fputs("</node>\n", i->f);
 
@@ -186,25 +183,17 @@ int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_b
         if (r < 0)
                 return r;
 
-        r = sd_bus_message_new_method_return(m, &q);
-        if (r < 0)
-                return r;
-
-        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);
 }
index bb2dd7ef7b9a1d11f30870f6a8751929acce1d43..ccbb543d0c9d491133fae5327885ba4a2d950365 100644 (file)
@@ -18,5 +18,5 @@ int introspect_begin(struct introspect *i, bool trusted);
 int introspect_write_default_interfaces(struct introspect *i, bool object_manager);
 int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix);
 int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v);
-int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply);
+int introspect_finish(struct introspect *i, char **ret);
 void introspect_free(struct introspect *i);
index d9fc25605ad043e28cbfba1f81869365adaa9667..fe3b9feea6dfe1e83b5a309ef571577a5ce3d522 100644 (file)
@@ -22,7 +22,7 @@ static int node_vtable_get_userdata(
                 sd_bus_error *error) {
 
         sd_bus_slot *s;
-        void *u, *found_u;
+        void *u, *found_u = NULL;
         int r;
 
         assert(bus);
@@ -883,31 +883,33 @@ static int bus_node_exists(
         return 0;
 }
 
-static int process_introspect(
+int introspect_path(
                 sd_bus *bus,
-                sd_bus_message *m,
+                const char *path,
                 struct node *n,
                 bool require_fallback,
-                bool *found_object) {
+                bool ignore_nodes_modified,
+                bool *found_object,
+                char **ret,
+                sd_bus_error *error) {
 
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
         _cleanup_set_free_free_ Set *s = NULL;
         const char *previous_interface = NULL;
-        struct introspect intro;
+        _cleanup_(introspect_free) struct introspect intro = {};
         struct node_vtable *c;
         bool empty;
         int r;
 
-        assert(bus);
-        assert(m);
-        assert(n);
-        assert(found_object);
+        if (!n) {
+                n = hashmap_get(bus->nodes, path);
+                if (!n)
+                        return -ENOENT;
+        }
 
-        r = get_child_nodes(bus, m->path, n, 0, &s, &error);
+        r = get_child_nodes(bus, path, n, 0, &s, error);
         if (r < 0)
-                return bus_maybe_reply_error(m, r, &error);
-        if (bus->nodes_modified)
+                return r;
+        if (bus->nodes_modified && !ignore_nodes_modified)
                 return 0;
 
         r = introspect_begin(&intro, bus->trusted);
@@ -924,15 +926,11 @@ static int process_introspect(
                 if (require_fallback && !c->is_fallback)
                         continue;
 
-                r = node_vtable_get_userdata(bus, m->path, c, NULL, &error);
-                if (r < 0) {
-                        r = bus_maybe_reply_error(m, r, &error);
-                        goto finish;
-                }
-                if (bus->nodes_modified) {
-                        r = 0;
-                        goto finish;
-                }
+                r = node_vtable_get_userdata(bus, path, c, NULL, error);
+                if (r < 0)
+                        return r;
+                if (bus->nodes_modified && !ignore_nodes_modified)
+                        return 0;
                 if (r == 0)
                         continue;
 
@@ -942,7 +940,6 @@ static int process_introspect(
                         continue;
 
                 if (!streq_ptr(previous_interface, c->interface)) {
-
                         if (previous_interface)
                                 fputs(" </interface>\n", intro.f);
 
@@ -951,7 +948,7 @@ static int process_introspect(
 
                 r = introspect_write_interface(&intro, c->vtable);
                 if (r < 0)
-                        goto finish;
+                        return r;
 
                 previous_interface = c->interface;
         }
@@ -962,36 +959,64 @@ static int process_introspect(
         if (empty) {
                 /* Nothing?, let's see if we exist at all, and if not
                  * refuse to do anything */
-                r = bus_node_exists(bus, n, m->path, require_fallback);
-                if (r <= 0) {
-                        r = bus_maybe_reply_error(m, r, &error);
-                        goto finish;
-                }
-                if (bus->nodes_modified) {
-                        r = 0;
-                        goto finish;
-                }
+                r = bus_node_exists(bus, n, path, require_fallback);
+                if (r <= 0)
+                        return r;
+                if (bus->nodes_modified && !ignore_nodes_modified)
+                        return 0;
         }
 
-        *found_object = true;
+        if (found_object)
+                *found_object = true;
 
-        r = introspect_write_child_nodes(&intro, s, m->path);
+        r = introspect_write_child_nodes(&intro, s, path);
         if (r < 0)
-                goto finish;
+                return r;
 
-        r = introspect_finish(&intro, bus, m, &reply);
+        r = introspect_finish(&intro, ret);
         if (r < 0)
-                goto finish;
+                return r;
 
-        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(
@@ -1668,7 +1693,7 @@ static bool names_are_valid(const char *signature, const char **names, names_fla
 
 /* the current version of this struct is defined in sd-bus-vtable.h, but we need to list here the historical versions
    to make sure the calling code is compatible with one of these */
-struct sd_bus_vtable_original {
+struct sd_bus_vtable_221 {
         uint8_t type:8;
         uint64_t flags:56;
         union {
@@ -1696,12 +1721,16 @@ struct sd_bus_vtable_original {
         } x;
 };
 /* Structure size up to v241 */
-#define VTABLE_ELEMENT_SIZE_ORIGINAL sizeof(struct sd_bus_vtable_original)
-/* Current structure size */
-#define VTABLE_ELEMENT_SIZE sizeof(struct sd_bus_vtable)
+#define VTABLE_ELEMENT_SIZE_221 sizeof(struct sd_bus_vtable_221)
+
+/* Size of the structure when "features" field was added. If the structure definition is augmented, a copy of
+ * the structure definition will need to be made (similarly to the sd_bus_vtable_221 above), and this
+ * definition updated to refer to it. */
+#define VTABLE_ELEMENT_SIZE_242 sizeof(struct sd_bus_vtable)
 
 static int vtable_features(const sd_bus_vtable *vtable) {
-        if (vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL)
+        if (vtable[0].x.start.element_size < VTABLE_ELEMENT_SIZE_242 ||
+            !vtable[0].x.start.vtable_format_reference)
                 return 0;
         return vtable[0].x.start.features;
 }
@@ -1711,13 +1740,7 @@ bool bus_vtable_has_names(const sd_bus_vtable *vtable) {
 }
 
 const sd_bus_vtable* bus_vtable_next(const sd_bus_vtable *vtable, const sd_bus_vtable *v) {
-        if (vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL) {
-                const struct sd_bus_vtable_original *v2 = (const struct sd_bus_vtable_original *)v;
-                v2++;
-                v = (const sd_bus_vtable*)v2;
-        } else /* current version */
-                v++;
-        return v;
+        return (const sd_bus_vtable*) ((char*) v + vtable[0].x.start.element_size);
 }
 
 static int add_object_vtable_internal(
@@ -1744,8 +1767,8 @@ static int add_object_vtable_internal(
         assert_return(interface_name_is_valid(interface), -EINVAL);
         assert_return(vtable, -EINVAL);
         assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
-        assert_return(vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_ORIGINAL ||
-                      vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE,
+        assert_return(vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_221 ||
+                      vtable[0].x.start.element_size >= VTABLE_ELEMENT_SIZE_242,
                       -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
         assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&
@@ -1928,6 +1951,9 @@ fail:
         return r;
 }
 
+/* This symbol exists solely to tell the linker that the "new" vtable format is used. */
+_public_ const unsigned sd_bus_object_vtable_format = 242;
+
 _public_ int sd_bus_add_object_vtable(
                 sd_bus *bus,
                 sd_bus_slot **slot,
index b45fe6323efc08e66472ee7417ac91b9a8d5c5d2..f650196a5439949f2bdc3a6dfdfa038ea91f8c4e 100644 (file)
@@ -2,8 +2,19 @@
 #pragma once
 
 #include "bus-internal.h"
+#include "bus-introspect.h"
 
 const sd_bus_vtable* bus_vtable_next(const sd_bus_vtable *vtable, const sd_bus_vtable *v);
 bool bus_vtable_has_names(const sd_bus_vtable *vtable);
 int bus_process_object(sd_bus *bus, sd_bus_message *m);
 void bus_node_gc(sd_bus *b, struct node *n);
+
+int introspect_path(
+                sd_bus *bus,
+                const char *path,
+                struct node *n,
+                bool require_fallback,
+                bool ignore_nodes_modified,
+                bool *found_object,
+                char **ret,
+                sd_bus_error *error);
index 9c8e93e897a01322eef8c06f457fd7948b9c1922..9c8d1434b139565c8888e77832d2f6a58ae8bdcb 100644 (file)
@@ -4,33 +4,13 @@
 #include "log.h"
 #include "tests.h"
 
-static int prop_get(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
-        return -EINVAL;
-}
-
-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);
 
@@ -38,10 +18,18 @@ int main(int argc, char *argv[]) {
         assert_se(introspect_write_interface(&intro, vtable) >= 0);
         fputs(" </interface>\n", intro.f);
 
-        fflush(intro.f);
-        fputs(intro.introspection, stdout);
+        assert_se(introspect_finish(&intro, &s) == 0);
+        fputs(s, stdout);
+        fputs("\n", stdout);
+}
+
+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;
 }
index b278094fadd0fc4be19c15e26164fad4fb9e38b1..d69ca6ac9742179b450c4a755f3dfe203c15f15e 100644 (file)
@@ -1,3 +1,5 @@
+/* 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;
@@ -126,16 +26,24 @@ static void test_vtable(void) {
 
         assert(sd_bus_new(&bus) >= 0);
 
-        assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable", vtable, &c) >= 0);
-        assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable2", vtable, &c) >= 0);
+        assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable", test_vtable_2, &c) >= 0);
+        assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable2", test_vtable_2, &c) >= 0);
         /* the cast on the line below is needed to test with the old version of the table */
-        assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtableOriginal", (const sd_bus_vtable *)vtable_format_original, &c) >= 0);
+        assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable221",
+                                        (const sd_bus_vtable *)vtable_format_221, &c) >= 0);
 
         assert(sd_bus_set_address(bus, DEFAULT_BUS_PATH) >= 0);
         r = sd_bus_start(bus);
         assert(r == 0 ||     /* success */
                r == -ENOENT  /* dbus is inactive */ );
 
+#ifndef __cplusplus
+        _cleanup_free_ char *s = NULL;
+
+        assert_se(introspect_path(bus, "/foo", NULL, false, true, NULL, &s, NULL) == 1);
+        fputs(s, stdout);
+#endif
+
         sd_bus_unref(bus);
 }
 
diff --git a/src/libsystemd/sd-bus/test-vtable-data.h b/src/libsystemd/sd-bus/test-vtable-data.h
new file mode 100644 (file)
index 0000000..333dbd5
--- /dev/null
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+/* This is meant to be included in other files, hence no headers */
+
+struct context {
+        bool quit;
+        char *something;
+        char *automatic_string_property;
+        uint32_t automatic_integer_property;
+};
+
+static int handler(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+        return 1;
+}
+
+static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
+        return 1;
+}
+
+static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
+        return 1;
+}
+
+static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) {
+        return 1;
+}
+
+static const sd_bus_vtable test_vtable_1[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_METHOD("Hello", "ssas", "a(uu)", NULL, 0),
+        SD_BUS_METHOD("DeprecatedHello", "", "", NULL, SD_BUS_VTABLE_DEPRECATED),
+        SD_BUS_METHOD("DeprecatedHelloNoReply", "", "", NULL, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_METHOD_NO_REPLY),
+        SD_BUS_SIGNAL("Wowza", "sss", 0),
+        SD_BUS_SIGNAL("DeprecatedWowza", "ut", SD_BUS_VTABLE_DEPRECATED),
+        SD_BUS_WRITABLE_PROPERTY("AProperty", "s", get_handler, set_handler, 0, 0),
+        SD_BUS_PROPERTY("AReadOnlyDeprecatedProperty", "(ut)", get_handler, 0, SD_BUS_VTABLE_DEPRECATED),
+        SD_BUS_PROPERTY("ChangingProperty", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Invalidating", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+        SD_BUS_PROPERTY("Constant", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EXPLICIT),
+        SD_BUS_VTABLE_END
+};
+
+static const sd_bus_vtable test_vtable_2[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_METHOD("AlterSomething", "s", "s", handler, 0),
+        SD_BUS_METHOD("Exit", "", "", handler, 0),
+        SD_BUS_METHOD_WITH_OFFSET("AlterSomething2", "s", "s", handler, 200, 0),
+        SD_BUS_METHOD_WITH_OFFSET("Exit2", "", "", handler, 200, 0),
+        SD_BUS_METHOD_WITH_NAMES_OFFSET("AlterSomething3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
+                        "s", SD_BUS_PARAM(returnstring), handler, 200, 0),
+        SD_BUS_METHOD_WITH_NAMES("Exit3", "bx", SD_BUS_PARAM(with_confirmation) SD_BUS_PARAM(after_msec),
+                        "bb", SD_BUS_PARAM(accepted) SD_BUS_PARAM(scheduled), handler, 0),
+        SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+        SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
+        SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something),
+                        SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
+        SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
+        SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL,
+                                 offsetof(struct context, automatic_string_property), 0),
+        SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL,
+                                 offsetof(struct context, automatic_integer_property), 0),
+        SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
+        SD_BUS_SIGNAL("DummySignal", "b", 0),
+        SD_BUS_SIGNAL("DummySignal2", "so", 0),
+        SD_BUS_SIGNAL_WITH_NAMES("DummySignal3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path), 0),
+        SD_BUS_VTABLE_END
+};
+
+static const sd_bus_vtable test_vtable_deprecated[] = {
+        SD_BUS_VTABLE_START(SD_BUS_VTABLE_DEPRECATED),
+        SD_BUS_VTABLE_END
+};
+
+struct sd_bus_vtable_221 {
+        uint8_t type:8;
+        uint64_t flags:56;
+        union {
+                struct {
+                        size_t element_size;
+                } start;
+                struct {
+                        const char *member;
+                        const char *signature;
+                        const char *result;
+                        sd_bus_message_handler_t handler;
+                        size_t offset;
+                } method;
+                struct {
+                        const char *member;
+                        const char *signature;
+                } signal;
+                struct {
+                        const char *member;
+                        const char *signature;
+                        sd_bus_property_get_t get;
+                        sd_bus_property_set_t set;
+                        size_t offset;
+                } property;
+        } x;
+};
+
+static const struct sd_bus_vtable_221 vtable_format_221[] = {
+        {
+                .type = _SD_BUS_VTABLE_START,
+                .flags = 0,
+                .x = {
+                        .start = {
+                                .element_size = sizeof(struct sd_bus_vtable_221)
+                        },
+                },
+        },
+        {
+                .type = _SD_BUS_VTABLE_METHOD,
+                .flags = 0,
+                .x = {
+                        .method = {
+                                .member = "Exit",
+                                .signature = "",
+                                .result = "",
+                                .handler = handler,
+                                .offset = 0,
+                        },
+                },
+        },
+        {
+                .type = _SD_BUS_VTABLE_END,
+                .flags = 0,
+                .x = { { 0 } },
+        }
+};
index f3084c0773f17b9f32d789a96a12479e40ba9759..5ebc5dfed84bffe52e496d6c1380d06cf6919b15 100644 (file)
@@ -452,22 +452,23 @@ int config_parse_wireguard_listen_port(
                 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;
 }
 
index 4846b13a8b8d19c2efead25967b75b6b2e0aafca..d3928e2862f3a034a4f8a7c1a9a51c3922ce7d6b 100644 (file)
@@ -409,7 +409,7 @@ void link_update_operstate(Link *link, bool also_update_master) {
         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)
@@ -605,17 +605,8 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
         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;
@@ -663,10 +654,7 @@ static Link *link_free(Link *link) {
         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);
@@ -682,17 +670,7 @@ static Link *link_free(Link *link) {
                 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);
 }
@@ -721,6 +699,10 @@ static void link_set_state(Link *link, LinkState state) {
         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);
@@ -1451,7 +1433,7 @@ static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
 
         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;
@@ -1747,28 +1729,6 @@ static int link_set_bond(Link *link) {
         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;
@@ -2531,6 +2491,55 @@ static void link_free_carrier_maps(Link *link) {
         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;
@@ -2539,15 +2548,15 @@ void link_drop(Link *link) {
 
         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) {
@@ -2640,7 +2649,7 @@ static int link_enter_join_netdev(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);
 
@@ -3053,7 +3062,7 @@ static int link_configure(Link *link) {
 
         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);
@@ -3202,7 +3211,7 @@ static int link_configure_after_setting_mtu(Link *link) {
 
         assert(link);
         assert(link->network);
-        assert(link->state == LINK_STATE_PENDING);
+        assert(link->state == LINK_STATE_INITIALIZED);
 
         if (link->setting_mtu)
                 return 0;
@@ -3353,10 +3362,13 @@ static int link_initialized_and_synced(Link *link) {
         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)
@@ -3432,6 +3444,7 @@ int link_initialized(Link *link, sd_device *device) {
                 return 0;
 
         log_link_debug(link, "udev initialized link");
+        link_set_state(link, LINK_STATE_INITIALIZED);
 
         link->sd_device = sd_device_ref(device);
 
@@ -4349,6 +4362,7 @@ void link_clean(Link *link) {
 
 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",
index e65246c87d3896c0d5d7031bc4013faa452ac949..e5497379d75b7d19114f8e5d2f9a004b382db1eb 100644 (file)
 #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;
@@ -121,7 +122,7 @@ typedef struct Link {
 
         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*);
index 677f66a478be2af779b89f4afc9ce105bf6ad4a9..c9579370cb93f684885b1315f3c04f51dd083e83 100644 (file)
@@ -1450,13 +1450,12 @@ void manager_free(Manager *m) {
         }
 
         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);
index 52cfc4bec15dec3ea8a6485c37b8f9e54e7f668b..b5bf0366f173436ba92c335ab35fb96b3a11bf6c 100644 (file)
@@ -172,6 +172,14 @@ int network_verify(Network *network) {
         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),
index 6408719d15aac2d11aa947d8117b331e2a5f3adc..05fc01d048dc7708f817824eb02715c35e22822a 100644 (file)
@@ -173,6 +173,7 @@ static void test_config_parse_address_one(const char *rvalue, int family, unsign
 
         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);
index b2f8936038bf529cc5564d376140ee25903812e3..5c823a3d84fb215094b330bc71f25d528cb7e41a 100644 (file)
@@ -725,8 +725,8 @@ int boot_entries_load_config_auto(
         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",
@@ -793,6 +793,7 @@ int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
 
         return 0;
 }
+#endif
 
 /********************************************************************************/
 
index b35eaf1110cd2bd21196e1626d88bb3721eebd40..c18d89494a512132be7adde966bf200ef2e3a062 100644 (file)
@@ -71,7 +71,13 @@ static inline BootEntry* boot_config_default_entry(BootConfig *config) {
 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;
index cae526ba40931fe695f72f900a00d7428ef6c84a..c6cbc9828c88d9ef0c16315136e4e65e797db952 100644 (file)
@@ -396,6 +396,10 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
 
                 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);
index 49d1b338fbd8bff94b20a5389f360d86d67cee0e..1346da9323d8585173ee5744ab2b05e5aaceae70 100644 (file)
@@ -79,6 +79,10 @@ static inline int efi_set_reboot_to_firmware(bool value) {
         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;
 }
index 8a73ef0503cc97454be577e408908d7bdcd2758a..e3804e203c2a1e2b4e433a6ac86a43f8aec14385 100644 (file)
@@ -52,6 +52,15 @@ enum {
         _SD_BUS_VTABLE_PARAM_NAMES     = 1 << 0,
 };
 
+extern const unsigned sd_bus_object_vtable_format;
+
+/* Note: unused areas in the sd_bus_vtable[] array must be initalized to 0. The stucture contains an embedded
+ * union, and the compiler is NOT required to initalize the unused areas of the union when the rest of the
+ * structure is initalized. Normally the array is defined as read-only data, in which case the linker places
+ * it in the BSS section, which is always fully initalized, so this is not a concern. But if the array is
+ * created on the stack or on the heap, care must be taken to initalize the unused areas, for examply by
+ * first memsetting the whole region to zero before filling the data in. */
+
 struct sd_bus_vtable {
         /* Please do not initialize this structure directly, use the
          * macros below instead */
@@ -62,6 +71,7 @@ struct sd_bus_vtable {
                 struct {
                         size_t element_size;
                         uint64_t features;
+                        const unsigned *vtable_format_reference;
                 } start;
                 struct {
                         const char *member;
@@ -93,7 +103,8 @@ struct sd_bus_vtable {
                 .x = {                                                  \
                     .start = {                                          \
                         .element_size = sizeof(sd_bus_vtable),          \
-                        .features = _SD_BUS_VTABLE_PARAM_NAMES          \
+                        .features = _SD_BUS_VTABLE_PARAM_NAMES,         \
+                        .vtable_format_reference = &sd_bus_object_vtable_format, \
                     },                                                  \
                 },                                                      \
         }
index 357cce8e44af1853f52f9e520b043bdf8ee451cc..4d358b8e345f63c80a5cc9c75d5d327bd9a50c93 100755 (executable)
@@ -6,18 +6,22 @@ for header in sys.argv[2:]:
     print('#include "{}"'.format(header.split('/')[-1]))
 
 print('''
-void* functions[] = {''')
+const void* symbols[] = {''')
 
 for line in open(sys.argv[1]):
     match = re.search('^ +([a-zA-Z0-9_]+);', line)
     if match:
-        print('    {},'.format(match.group(1)))
+        s = match.group(1)
+        if s == 'sd_bus_object_vtable_format':
+            print('    &{},'.format(s))
+        else:
+            print('    {},'.format(s))
 
 print('''};
 
 int main(void) {
     unsigned i;
-    for (i = 0; i < sizeof(functions)/sizeof(void*); i++)
-         printf("%p\\n", functions[i]);
+    for (i = 0; i < sizeof(symbols)/sizeof(void*); i++)
+         printf("%p\\n", symbols[i]);
     return 0;
 }''')
index 521985b927e4fffa82a4acd396f14fb766575a2f..e58e1cc73d3f90729f0b1ae7e7f8d1bcfb8eebcc 100644 (file)
@@ -911,7 +911,8 @@ tests += [
          [],
          [threads]],
 
-        [['src/libsystemd/sd-bus/test-bus-vtable.c'],
+        [['src/libsystemd/sd-bus/test-bus-vtable.c',
+          'src/libsystemd/sd-bus/test-vtable-data.h'],
          [],
          []],
 
@@ -934,7 +935,8 @@ tests += [
          [threads],
          '', 'manual'],
 
-        [['src/libsystemd/sd-bus/test-bus-introspect.c'],
+        [['src/libsystemd/sd-bus/test-bus-introspect.c',
+          'src/libsystemd/sd-bus/test-vtable-data.h'],
          [],
          []],
 
index 057840d76fb3cd66362c11aa5c99c78a20f5dcb9..4e9a0bddf4a3cc1c33855ecc2fb27c62562d7165 100644 (file)
@@ -810,6 +810,67 @@ static void test_send_emptydata(void) {
         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);
 
@@ -843,6 +904,7 @@ int main(int argc, char *argv[]) {
         test_receive_nopassfd();
         test_send_nodata_nofd();
         test_send_emptydata();
+        test_flush_accept();
 
         return 0;
 }
index a26c4cefa8201a7713e4610373a4f1b2d64553e2..7754959cdf3a53f9449bab58cb50a7d7cba67c7d 100644 (file)
@@ -159,6 +159,14 @@ int link_load_one(link_config_ctx *ctx, const char *filename) {
         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;
index 27cede5e2e55441b8fd572a94e88a2d9ed8f08b4..8223f9cda175d87cc1887756dce3a4337980fa1f 100644 (file)
@@ -8,6 +8,7 @@ static const NamingScheme naming_schemes[] = {
         { "v238", NAMING_V238 },
         { "v239", NAMING_V239 },
         { "v240", NAMING_V240 },
+        { "v243", NAMING_V243 },
         /* … add more schemes here, as the logic to name devices is updated … */
 };
 
index 0b3d9bff1d79350ced02a74c39144ffdf3a01f4a..1f7cb0ccb967436d3a3127feb3666671b17da958 100644 (file)
@@ -27,11 +27,13 @@ typedef enum NamingSchemeFlags {
         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;
index 03b281a77102c0e1228a79ccf9b431670958b0be..2c7dcf7d2a10ae877ac741813e19deafd717bb6f 100644 (file)
@@ -31,6 +31,7 @@
  *                                         — 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.
@@ -126,6 +127,7 @@ enum netname_type{
         NET_CCW,
         NET_VIO,
         NET_PLATFORM,
+        NET_NETDEVSIM,
 };
 
 struct netnames {
@@ -145,6 +147,7 @@ struct netnames {
         char ccw_busid[IFNAMSIZ];
         char vio_slot[IFNAMSIZ];
         char platform_path[IFNAMSIZ];
+        char netdevsim_path[IFNAMSIZ];
 };
 
 struct virtfn_info {
@@ -794,6 +797,43 @@ static int names_mac(sd_device *dev, struct netnames *names) {
         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];
@@ -897,6 +937,16 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
                 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;
index 63a967633b7e3d5740d22828995633e099c4a136..96840b272ca77df3cf5751b88a8e1a1f7915f5f1 100644 (file)
@@ -2442,7 +2442,7 @@ int udev_rules_apply_to_event(
                 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)
index e1cd5caeeaf5ebc1abbc8845b74dbe833e87a2a9..7512ba9e12b4b9642a91c5912eb7c7cf5a5ceb86 100644 (file)
@@ -12,7 +12,7 @@ Wants=testsuite-fail-runtime.service
 StopWhenUnneeded=yes
 
 [Service]
-
 Type=simple
+TimeoutStartSec=infinity
 ExecStartPre=/assess.sh
 ExecStart=/bin/true
index d9db9c1657de2ae21d5ab753d3866f728b460d7a..843125ee656dd2172bc2218b8ea64577c77fb3fa 100755 (executable)
@@ -443,16 +443,16 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         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)
@@ -478,11 +478,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         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):
@@ -544,24 +544,24 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
             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')
@@ -571,10 +571,10 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         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',