summaryrefslogtreecommitdiff
path: root/src/libsystemd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd')
-rw-r--r--src/libsystemd/Makefile5
-rw-r--r--src/libsystemd/include/systemd/sd-bus.h10
-rw-r--r--src/libsystemd/include/systemd/sd-id128.h2
-rw-r--r--src/libsystemd/include/systemd/sd-messages.h1
-rw-r--r--src/libsystemd/libsystemd.sym11
-rw-r--r--src/libsystemd/sd-bus.xml51
-rw-r--r--src/libsystemd/sd-event.xml2
-rw-r--r--src/libsystemd/sd-id128.xml41
-rw-r--r--src/libsystemd/sd-journal.xml17
-rw-r--r--src/libsystemd/sd_bus_creds_get_pid.xml2
-rw-r--r--src/libsystemd/sd_bus_creds_new_from_pid.xml4
-rw-r--r--src/libsystemd/sd_bus_message_append.xml5
-rw-r--r--src/libsystemd/sd_bus_negotiate_fds.xml46
-rw-r--r--src/libsystemd/sd_bus_track_add_name.xml261
-rw-r--r--src/libsystemd/sd_bus_track_new.xml263
-rw-r--r--src/libsystemd/sd_event_new.xml5
-rw-r--r--src/libsystemd/sd_event_source_set_priority.xml8
-rw-r--r--src/libsystemd/sd_id128_get_machine.xml34
-rw-r--r--src/libsystemd/sd_is_fifo.xml8
-rw-r--r--src/libsystemd/sd_journal_add_match.xml3
-rw-r--r--src/libsystemd/sd_journal_enumerate_fields.xml3
-rw-r--r--src/libsystemd/sd_journal_get_catalog.xml4
-rw-r--r--src/libsystemd/sd_journal_get_cursor.xml3
-rw-r--r--src/libsystemd/sd_journal_get_cutoff_realtime_usec.xml3
-rw-r--r--src/libsystemd/sd_journal_get_usage.xml3
-rw-r--r--src/libsystemd/sd_journal_has_runtime_files.xml12
-rw-r--r--src/libsystemd/sd_journal_next.xml3
-rw-r--r--src/libsystemd/sd_journal_open.xml14
-rw-r--r--src/libsystemd/sd_journal_print.xml7
-rw-r--r--src/libsystemd/sd_journal_query_unique.xml3
-rw-r--r--src/libsystemd/sd_journal_seek_head.xml3
-rw-r--r--src/libsystemd/sd_journal_stream_fd.xml4
-rw-r--r--src/libsystemd/sd_notify.xml41
-rw-r--r--src/libsystemd/src/sd-bus/bus-common-errors.c25
-rw-r--r--src/libsystemd/src/sd-bus/bus-common-errors.h3
-rw-r--r--src/libsystemd/src/sd-bus/bus-error.c8
-rw-r--r--src/libsystemd/src/sd-bus/bus-internal.h8
-rw-r--r--src/libsystemd/src/sd-bus/bus-slot.c4
-rw-r--r--src/libsystemd/src/sd-bus/bus-track.c262
-rw-r--r--src/libsystemd/src/sd-bus/bus-track.h1
-rw-r--r--src/libsystemd/src/sd-bus/bus-util.c95
-rw-r--r--src/libsystemd/src/sd-bus/bus-util.h1
-rw-r--r--src/libsystemd/src/sd-bus/sd-bus.c144
-rw-r--r--src/libsystemd/src/sd-bus/test-bus-chat.c2
-rw-r--r--src/libsystemd/src/sd-bus/test-bus-creds.c9
-rw-r--r--src/libsystemd/src/sd-bus/test-bus-track.c113
-rw-r--r--src/libsystemd/src/sd-device/sd-device.c5
-rw-r--r--src/libsystemd/src/sd-hwdb/hwdb-internal.h8
-rw-r--r--src/libsystemd/src/sd-hwdb/sd-hwdb.c58
-rw-r--r--src/libsystemd/src/sd-id128/id128-util.c13
-rw-r--r--src/libsystemd/src/sd-id128/id128-util.h5
-rw-r--r--src/libsystemd/src/sd-id128/sd-id128.c22
-rw-r--r--src/libsystemd/src/sd-journal/journal-file.c190
-rw-r--r--src/libsystemd/src/sd-journal/journal-vacuum.c2
-rw-r--r--src/libsystemd/src/sd-journal/journal-verify.c15
-rw-r--r--src/libsystemd/src/sd-journal/lookup3.c6
-rw-r--r--src/libsystemd/src/sd-journal/mmap-cache.c6
-rw-r--r--src/libsystemd/src/sd-journal/sd-journal.c51
-rw-r--r--src/libsystemd/src/sd-netlink/netlink-types.c74
-rw-r--r--src/libsystemd/src/sd-netlink/netlink-types.h1
-rw-r--r--src/libsystemd/src/test.mk9
61 files changed, 1609 insertions, 413 deletions
diff --git a/src/libsystemd/Makefile b/src/libsystemd/Makefile
index 50396c278c..e85ef4a778 100644
--- a/src/libsystemd/Makefile
+++ b/src/libsystemd/Makefile
@@ -23,9 +23,9 @@
include $(dir $(lastword $(MAKEFILE_LIST)))/../../config.mk
include $(topsrcdir)/build-aux/Makefile.head.mk
-LIBSYSTEMD_CURRENT=16
+LIBSYSTEMD_CURRENT=17
LIBSYSTEMD_REVISION=0
-LIBSYSTEMD_AGE=16
+LIBSYSTEMD_AGE=17
EXTRA_DIST += \
src/libsystemd/libsystemd.pc.in \
@@ -76,6 +76,7 @@ tests += \
test-bus-error \
test-bus-creds \
test-bus-gvariant \
+ test-bus-track \
test-event \
test-netlink \
test-local-addresses \
diff --git a/src/libsystemd/include/systemd/sd-bus.h b/src/libsystemd/include/systemd/sd-bus.h
index 4e338a3270..dd50162f9f 100644
--- a/src/libsystemd/include/systemd/sd-bus.h
+++ b/src/libsystemd/include/systemd/sd-bus.h
@@ -146,6 +146,8 @@ int sd_bus_can_send(sd_bus *bus, char type);
int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *creds_mask);
int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b);
int sd_bus_get_allow_interactive_authorization(sd_bus *bus);
+int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b);
+int sd_bus_get_exit_on_disconnect(sd_bus *bus);
int sd_bus_start(sd_bus *ret);
@@ -437,8 +439,14 @@ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m);
int sd_bus_track_add_name(sd_bus_track *track, const char *name);
int sd_bus_track_remove_name(sd_bus_track *track, const char *name);
+int sd_bus_track_set_recursive(sd_bus_track *track, int b);
+int sd_bus_track_get_recursive(sd_bus_track *track);
+
unsigned sd_bus_track_count(sd_bus_track *track);
-const char* sd_bus_track_contains(sd_bus_track *track, const char *names);
+int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m);
+int sd_bus_track_count_name(sd_bus_track *track, const char *name);
+
+const char* sd_bus_track_contains(sd_bus_track *track, const char *name);
const char* sd_bus_track_first(sd_bus_track *track);
const char* sd_bus_track_next(sd_bus_track *track);
diff --git a/src/libsystemd/include/systemd/sd-id128.h b/src/libsystemd/include/systemd/sd-id128.h
index 4dff0b9b81..ee011b1861 100644
--- a/src/libsystemd/include/systemd/sd-id128.h
+++ b/src/libsystemd/include/systemd/sd-id128.h
@@ -45,8 +45,8 @@ int sd_id128_from_string(const char *s, sd_id128_t *ret);
int sd_id128_randomize(sd_id128_t *ret);
int sd_id128_get_machine(sd_id128_t *ret);
-
int sd_id128_get_boot(sd_id128_t *ret);
+int sd_id128_get_invocation(sd_id128_t *ret);
#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \
((const sd_id128_t) { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \
diff --git a/src/libsystemd/include/systemd/sd-messages.h b/src/libsystemd/include/systemd/sd-messages.h
index c8599c596d..68d7fa2ca9 100644
--- a/src/libsystemd/include/systemd/sd-messages.h
+++ b/src/libsystemd/include/systemd/sd-messages.h
@@ -39,6 +39,7 @@ _SD_BEGIN_DECLARATIONS;
#define SD_MESSAGE_JOURNAL_USAGE SD_ID128_MAKE(ec,38,7f,57,7b,84,4b,8f,a9,48,f3,3c,ad,9a,75,e6)
#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)
+#define SD_MESSAGE_TRUNCATED_CORE SD_ID128_MAKE(5a,ad,d8,e9,54,dc,4b,1a,8c,95,4d,63,fd,9e,11,37)
#define SD_MESSAGE_SESSION_START SD_ID128_MAKE(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66)
#define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a)
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 542254295c..d48ef6bbe2 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -500,3 +500,14 @@ LIBSYSTEMD_231 {
global:
sd_event_get_iteration;
} LIBSYSTEMD_230;
+
+LIBSYSTEMD_232 {
+global:
+ sd_bus_track_set_recursive;
+ sd_bus_track_get_recursive;
+ sd_bus_track_count_name;
+ sd_bus_track_count_sender;
+ sd_bus_set_exit_on_disconnect;
+ sd_bus_get_exit_on_disconnect;
+ sd_id128_get_invocation;
+} LIBSYSTEMD_231;
diff --git a/src/libsystemd/sd-bus.xml b/src/libsystemd/sd-bus.xml
index 336dd33ea0..66b1c96c15 100644
--- a/src/libsystemd/sd-bus.xml
+++ b/src/libsystemd/sd-bus.xml
@@ -44,7 +44,7 @@
<refnamediv>
<refname>sd-bus</refname>
- <refpurpose>A lightweight D-Bus and kdbus client library</refpurpose>
+ <refpurpose>A lightweight D-Bus IPC client library</refpurpose>
</refnamediv>
<refsynopsisdiv>
@@ -61,49 +61,40 @@
<refsect1>
<title>Description</title>
- <para><filename>sd-bus.h</filename> provides an implementation
- of a D-Bus client. It can interoperate both with the traditional
- <citerefentry project='man-pages'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- and with kdbus. See
+ <para><filename>sd-bus.h</filename> provides an implementation of a D-Bus IPC client. See
<ulink url="http://www.freedesktop.org/software/dbus/" />
- for more information about the big picture.
+ for more information about D-Bus IPC.
</para>
- <important>
- <para>Interfaces described here have not been declared stable yet,
- and are not accessible from <filename>libsystemd.so</filename>.
- This documentation is provided in hope it might be useful for
- developers, without any guarantees of availability or stability.
- </para>
- </important>
-
<para>See
+ <citerefentry><refentrytitle>sd-bus-errors</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>,
<citerefentry><refentrytitle>sd_bus_default</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_error_add_map</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_get_name_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_get_owner_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_append</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_append_array</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_append_string_memfd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_append_strv</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_can_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_get_cookie</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_get_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_negotiate_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_path_encode</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_request_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_send</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_set_address</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_set_allow_interactive_authorization</refentrytitle><manvolnum>3</manvolnum></citerefentry>
<citerefentry><refentrytitle>sd_bus_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_set_prepare</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>,
- <citerefentry><refentrytitle>sd_bus_get_name_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_get_owner_creds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_negotiate_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_path_encode</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd-bus-errors</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_error</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_error_add_map</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_bus_set_allow_interactive_authorization</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_bus_start</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_track_add_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_track_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
for more information about the functions available.</para>
</refsect1>
@@ -114,9 +105,9 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>busctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry project='man-pages'><refentrytitle>dbus-send</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <ulink url="https://developer.gnome.org/gio/stable/gdbus.html">gdbus</ulink>
+ <citerefentry project='man-pages'><refentrytitle>dbus-send</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/src/libsystemd/sd-event.xml b/src/libsystemd/sd-event.xml
index fc615f0906..24a69bb645 100644
--- a/src/libsystemd/sd-event.xml
+++ b/src/libsystemd/sd-event.xml
@@ -97,7 +97,7 @@
iteration a single event source is dispatched. Each time an event
source is dispatched the kernel is polled for new events, before
the next event source is dispatched. The event loop is designed to
- honour priorities and provide fairness within each priority. It is
+ honor priorities and provide fairness within each priority. It is
not designed to provide optimal throughput, as this contradicts
these goals due the limitations of the underlying <citerefentry
project='man-pages'><refentrytitle>epoll</refentrytitle><manvolnum>7</manvolnum></citerefentry>
diff --git a/src/libsystemd/sd-id128.xml b/src/libsystemd/sd-id128.xml
index ea7972055d..5f24feff8e 100644
--- a/src/libsystemd/sd-id128.xml
+++ b/src/libsystemd/sd-id128.xml
@@ -47,10 +47,12 @@
<refname>sd-id128</refname>
<refname>sd_id128_t</refname>
<refname>SD_ID128_MAKE</refname>
+ <refname>SD_ID128_NULL</refname>
<refname>SD_ID128_CONST_STR</refname>
<refname>SD_ID128_FORMAT_STR</refname>
<refname>SD_ID128_FORMAT_VAL</refname>
<refname>sd_id128_equal</refname>
+ <refname>sd_id128_is_null</refname>
<refpurpose>APIs for processing 128-bit IDs</refpurpose>
</refnamediv>
@@ -88,8 +90,8 @@
union type:</para>
<programlisting>typedef union sd_id128 {
- uint8_t bytes[16];
- uint64_t qwords[2];
+ uint8_t bytes[16];
+ uint64_t qwords[2];
} sd_id128_t;</programlisting>
<para>This union type allows accessing the 128-bit ID as 16
@@ -108,37 +110,46 @@
<programlisting>#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1)</programlisting>
+ <para><function>SD_ID128_NULL</function> may be used to refer to the 128bit ID consisting of only NUL
+ bytes.</para>
+
<para><function>SD_ID128_CONST_STR()</function> may be used to
convert constant 128-bit IDs into constant strings for output. The
following example code will output the string
"fc2e22bc6ee647b6b90729ab34a250b1":</para>
<programlisting>int main(int argc, char *argv[]) {
- puts(SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP));
+ puts(SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP));
}</programlisting>
- <para><function>SD_ID128_FORMAT_STR</function> and
+ <para><function>SD_ID128_FORMAT_STR()</function> and
<function>SD_ID128_FORMAT_VAL()</function> may be used to format a
128-bit ID in a
<citerefentry project='man-pages'><refentrytitle>printf</refentrytitle><manvolnum>3</manvolnum></citerefentry>
format string, as shown in the following example:</para>
<programlisting>int main(int argc, char *argv[]) {
- sd_id128_t id;
- id = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
- printf("The ID encoded in this C file is " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(id));
- return 0;
+ sd_id128_t id;
+ id = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
+ printf("The ID encoded in this C file is " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(id));
+ return 0;
}</programlisting>
<para>Use <function>sd_id128_equal()</function> to compare two 128-bit IDs:</para>
<programlisting>int main(int argc, char *argv[]) {
- sd_id128_t a, b, c;
- a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
- b = SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e);
- c = a;
- assert(sd_id128_equal(a, c));
- assert(!sd_id128_equal(a, b));
- return 0;
+ sd_id128_t a, b, c;
+ a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07);
+ b = SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e);
+ c = a;
+ assert(sd_id128_equal(a, c));
+ assert(!sd_id128_equal(a, b));
+ return 0;
+}</programlisting>
+
+ <para>Use <function>sd_id128_is_null()</function> to check if an 128bit ID consists of only NUL bytes:</para>
+
+ <programlisting>int main(int argc, char *argv[]) {
+ assert(sd_id128_is_null(SD_ID128_NULL));
}</programlisting>
<para>Note that new, randomized IDs may be generated with
diff --git a/src/libsystemd/sd-journal.xml b/src/libsystemd/sd-journal.xml
index 09747a480c..0f4b3e8eea 100644
--- a/src/libsystemd/sd-journal.xml
+++ b/src/libsystemd/sd-journal.xml
@@ -77,7 +77,6 @@
<citerefentry><refentrytitle>sd_journal_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_seek_head</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_journal_query_enumerate</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cutoff_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
@@ -99,6 +98,21 @@
tool.</para>
</refsect1>
+ <refsect1>
+ <title>Thread safety</title>
+
+ <para>Functions that operate on the <structname>sd_journal</structname> object are thread
+ agnostic — given <structname>sd_journal</structname> pointer may only be used from one thread at
+ a time, but multiple threads may use multiple such objects safely. Other functions —
+ those that are used to send entries to the journal, like
+ <citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ and similar, or those that are used to retrieve global information like
+ <citerefentry><refentrytitle>sd_journal_stream_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ and
+ <citerefentry><refentrytitle>sd_journal_get_catalog_for_message_id</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ — are thread-safe and may be called from multiple threads in parallel.</para>
+ </refsect1>
+
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
@@ -113,7 +127,6 @@
<citerefentry><refentrytitle>sd_journal_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_seek_head</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_journal_query_enumerate</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_journal_get_cutoff_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
diff --git a/src/libsystemd/sd_bus_creds_get_pid.xml b/src/libsystemd/sd_bus_creds_get_pid.xml
index 4c05835568..9e68d5e8c7 100644
--- a/src/libsystemd/sd_bus_creds_get_pid.xml
+++ b/src/libsystemd/sd_bus_creds_get_pid.xml
@@ -366,7 +366,7 @@
-ENXIO is returned.</para>
<para><function>sd_bus_creds_get_cgroup()</function> will retrieve
- the cgroup path. See <ulink
+ the control group path. See <ulink
url="https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt">cgroups.txt</ulink>.
</para>
diff --git a/src/libsystemd/sd_bus_creds_new_from_pid.xml b/src/libsystemd/sd_bus_creds_new_from_pid.xml
index 082f7b67db..b4d7d61d0f 100644
--- a/src/libsystemd/sd_bus_creds_new_from_pid.xml
+++ b/src/libsystemd/sd_bus_creds_new_from_pid.xml
@@ -66,12 +66,12 @@
<funcprototype>
<funcdef>uint64_t <function>sd_bus_creds_get_mask</function></funcdef>
- <paramdef>const sd_bus_creds *<parameter>c</parameter></paramdef>
+ <paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>uint64_t <function>sd_bus_creds_get_augmented_mask</function></funcdef>
- <paramdef>const sd_bus_creds *<parameter>c</parameter></paramdef>
+ <paramdef>sd_bus_creds *<parameter>c</parameter></paramdef>
</funcprototype>
<funcprototype>
diff --git a/src/libsystemd/sd_bus_message_append.xml b/src/libsystemd/sd_bus_message_append.xml
index 77fce02eae..c222d0fd0e 100644
--- a/src/libsystemd/sd_bus_message_append.xml
+++ b/src/libsystemd/sd_bus_message_append.xml
@@ -169,6 +169,11 @@
</tgroup>
</table>
+ <para>For types "s" and "g" (unicode string or signature), the pointer may be
+ <constant>NULL</constant>, which is equivalent to an empty string. See
+ <citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ for the precise interpretation of those and other types.</para>
+
</refsect1>
<refsect1>
diff --git a/src/libsystemd/sd_bus_negotiate_fds.xml b/src/libsystemd/sd_bus_negotiate_fds.xml
index a538b13cf0..1501e1427d 100644
--- a/src/libsystemd/sd_bus_negotiate_fds.xml
+++ b/src/libsystemd/sd_bus_negotiate_fds.xml
@@ -99,41 +99,27 @@
setting as negotiated by the program ultimately activated. By
default, file descriptor passing is enabled for both.</para>
- <para><function>sd_bus_negotiate_timestamps()</function> controls
- whether implicit sender timestamps shall be attached automatically
- to all incoming messages. Takes a bus object and a boolean, which,
- when true, enables timestamping, and, when false, disables it.
- Use
+ <para><function>sd_bus_negotiate_timestamp()</function> controls whether implicit sender
+ timestamps shall be attached automatically to all incoming messages. Takes a bus object and a
+ boolean, which, when true, enables timestamping, and, when false, disables it. Use
<citerefentry><refentrytitle>sd_bus_message_get_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_get_seqnum</refentrytitle><manvolnum>3</manvolnum></citerefentry>
- to query the timestamps of incoming messages. If negotiation is
- disabled or not supported, these calls will fail with
- <constant>-ENODATA</constant>. Note that not all transports
- support timestamping of messages. Specifically, timestamping is
- only available on the kdbus transport, but not on dbus1. The
- timestamping is applied by the kernel and cannot be manipulated by
- userspace. By default, message timestamping is not negotiated for
+ to query the timestamps of incoming messages. If negotiation is disabled or not supported, these
+ calls will fail with <constant>-ENODATA</constant>. Note that currently no transports support
+ timestamping of messages. By default, message timestamping is not negotiated for
connections.</para>
- <para><function>sd_bus_negotiate_creds()</function> controls
- whether and which implicit sender credentials shall be attached
- automatically to all incoming messages. Takes a bus object and a
- boolean indicating whether to enable or disable the credential
- parts encoded in the bit mask value argument. Note that not all
- transports support attaching sender credentials to messages, or do
- not support all types of sender credential parameters, or might
- suppress them under certain circumstances for individual
- messages. Specifically, implicit sender credentials on messages
- are only fully supported on kdbus transports, and dbus1 only
- supports <constant>SD_BUS_CREDS_UNIQUE_NAME</constant>. The sender
- credentials are attached by the kernel and cannot be manipulated
- by userspace, and are thus suitable for authorization
- decisions. By default, only
- <constant>SD_BUS_CREDS_WELL_KNOWN_NAMES</constant> and
- <constant>SD_BUS_CREDS_UNIQUE_NAME</constant> are enabled. In
- fact, these two credential fields are always sent along and cannot
- be turned off.</para>
+ <para><function>sd_bus_negotiate_creds()</function> controls whether and which implicit sender
+ credentials shall be attached automatically to all incoming messages. Takes a bus object and a
+ boolean indicating whether to enable or disable the credential parts encoded in the bit mask
+ value argument. Note that not all transports support attaching sender credentials to messages,
+ or do not support all types of sender credential parameters, or might suppress them under
+ certain circumstances for individual messages. Specifically, dbus1 only supports
+ <constant>SD_BUS_CREDS_UNIQUE_NAME</constant>. The sender credentials are suitable for
+ authorization decisions. By default, only <constant>SD_BUS_CREDS_WELL_KNOWN_NAMES</constant> and
+ <constant>SD_BUS_CREDS_UNIQUE_NAME</constant> are enabled. In fact, these two credential fields
+ are always sent along and cannot be turned off.</para>
<para>The <function>sd_bus_negotiate_fds()</function> function may
be called only before the connection has been started with
diff --git a/src/libsystemd/sd_bus_track_add_name.xml b/src/libsystemd/sd_bus_track_add_name.xml
new file mode 100644
index 0000000000..6a5e344cb1
--- /dev/null
+++ b/src/libsystemd/sd_bus_track_add_name.xml
@@ -0,0 +1,261 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2016 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_bus_track_add_name">
+
+ <refentryinfo>
+ <title>sd_bus_track_add_name</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_track_add_name</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_track_add_name</refname>
+ <refname>sd_bus_track_add_sender</refname>
+ <refname>sd_bus_track_remove_name</refname>
+ <refname>sd_bus_track_remove_sender</refname>
+ <refname>sd_bus_track_count</refname>
+ <refname>sd_bus_track_count_sender</refname>
+ <refname>sd_bus_track_count_name</refname>
+ <refname>sd_bus_track_contains</refname>
+ <refname>sd_bus_track_first</refname>
+ <refname>sd_bus_track_next</refname>
+
+ <refpurpose>Add, remove and retrieve bus peers tracked in a bus peer tracking object</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_add_name</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ <paramdef>const char* <parameter>name</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_add_sender</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ <paramdef>sd_bus_message* <parameter>message</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_remove_name</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ <paramdef>const char* <parameter>name</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_remove_sender</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ <paramdef>sd_bus_message* <parameter>message</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>unsigned <function>sd_bus_track_count</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_count_name</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ <paramdef>const char* <parameter>name</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_count_sender</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ <paramdef>sd_bus_message* <parameter>message</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_contains</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ <paramdef>const char* <parameter>name</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>const char* <function>sd_bus_track_first</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>const char* <function>sd_bus_track_next</function></funcdef>
+ <paramdef>sd_bus_track* <parameter>t</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_track_add_name()</function> adds a peer to track to a bus peer tracking object. The first
+ argument should refer to a bus peer tracking object created with
+ <citerefentry><refentrytitle>sd_bus_track_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>, the second
+ name should refer to a D-Bus peer name to track, either in unique or well-known service format. If the name is not
+ tracked yet it will be added to the list of names to track. If it already is being tracked and non-recursive mode
+ is enabled, no operation is executed by this call. If recursive mode is enabled a per-name counter is increased by
+ one each time this call is invoked, and <function>sd_bus_track_remove_name()</function> has to be called as many
+ times as <function>sd_bus_track_add_name()</function> was invoked before in order to stop tracking of the name. Use
+ <citerefentry><refentrytitle>sd_bus_track_set_recursive</refentrytitle><manvolnum>3</manvolnum></citerefentry> to
+ switch from the default non-recursive mode to recursive mode, or back. Note that the specified name is tracked as
+ it is, well-known names are not resolved to unique names by this call. Note that multiple bus peer tracking objects
+ may track the same name.</para>
+
+ <para><function>sd_bus_track_remove_name()</function> undoes the effect of
+ <function>sd_bus_track_add_name()</function> and removes a bus peer name from the list of peers to watch. Depending
+ on whether non-recursive or recursive mode is enabled for the bus peer tracking object this call will either remove
+ the name fully from the tracking object, or will simply decrement the per-name counter by one, removing the name
+ only when the counter reaches zero (see above). Note that a bus peer disconnecting from the bus will implicitly
+ remove its names fully from the bus peer tracking object, regardless of the current per-name counter.</para>
+
+ <para><function>sd_bus_track_add_sender()</function> and <function>sd_bus_track_remove_sender()</function> are
+ similar to <function>sd_bus_track_add_name()</function> and <function>sd_bus_track_remove_name()</function> but
+ take a bus message as argument. The sender of this bus message is determined and added to/removed from the bus peer
+ tracking object. As messages always originate from unique names, and never from well-known names this means that
+ this call will effectively only add unique names to the bus peer tracking object.</para>
+
+ <para><function>sd_bus_track_count()</function> returns the number of names currently being tracked by the
+ specified bus peer tracking object. Note that this function always returns the actual number of names tracked, and
+ hence if <function>sd_bus_track_add_name()</function> has been invoked multiple times for the same name it is only
+ counted as one, regardless if recursive mode is used or not.</para>
+
+ <para><function>sd_bus_track_count_name()</function> returns the current per-name counter for the specified
+ name. If non-recursive mode is used this returns either 1 or 0, depending on whether the specified name has been
+ added to the tracking object before, or not. If recursive mode has been enabled, values larger than 1 may be
+ returned too, in case <function>sd_bus_track_add_name()</function> has been called multiple times for the same
+ name.</para>
+
+ <para><function>sd_bus_track_count_sender()</function> is similar to
+ <function>sd_bus_track_count_name()</function>, but takes a bus message object and returns the per-name counter
+ matching the sender of the message.</para>
+
+ <para><function>sd_bus_track_contains()</function> may be used to determine whether the specified name has been
+ added at least once to the specified bus peer tracking object.</para>
+
+ <para><function>sd_bus_track_first()</function> and <function>sd_bus_track_next()</function> may be used to
+ enumerate all names currently being tracked by the passed bus peer tracking
+ object. <function>sd_bus_track_first()</function> returns the first entry in the object, and resets an internally
+ maintained read index. Each subsequent invocation of <function>sd_bus_track_next()</function> returns the next name
+ contained in the bus object. If the end is reached <constant>NULL</constant> is returned. If no names have been
+ added to the object yet <function>sd_bus_track_first()</function> will return <constant>NULL</constant>
+ immediately. The order in which names are returned is undefined; in particular which name is considered the first
+ returned is not defined. If recursive mode is enabled and the same name has been added multiple times to the bus
+ peer tracking object it is only returned once by this enumeration. If new names are added to or existing names
+ removed from the bus peer tracking object while it is being enumerated the enumeration ends on the next invocation
+ of <function>sd_bus_track_next()</function> as <constant>NULL</constant> is returned.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_bus_track_add_name()</function> and <function>sd_bus_track_add_sender()</function>
+ return 0 if the specified name has already been added to the bus peer tracking object before and positive if it
+ hasn't. On failure, they return a negative errno-style error code.</para>
+
+ <para><function>sd_bus_track_remove_name()</function> and <function>sd_bus_track_remove_sender()</function> return
+ positive if the specified name was previously tracked by the bus peer tracking object and has now been removed. In
+ non-recursive mode, 0 is returned if the specified name was not being tracked yet. In recursive mode
+ <constant>-EUNATCH</constant> is returned in this case. On failure, they return a negative errno-style error
+ code.</para>
+
+ <para><function>sd_bus_track_count()</function> returns the number of names currently being tracked, or 0 on
+ failure.</para>
+
+ <para><function>sd_bus_track_count_name()</function> and <function>sd_bus_track_count_sender()</function> return
+ the current per-name counter for the specified name or the sender of the specified message. Zero is returned for
+ names that are not being tracked yet, a positive value for names added at least once. Larger values than 1 are only
+ returned in recursive mode. On failure, a negative errno-style error code is returned.</para>
+
+ <para><function>sd_bus_track_contains()</function> returns the passed name if it exists in the bus peer tracking
+ object. On failure, and if the name has not been added yet <constant>NULL</constant> is returned.</para>
+
+ <para><function>sd_bus_track_first()</function> and <function>sd_bus_track_next()</function> return the first/next
+ name contained in the bus peer tracking object, and <constant>NULL</constant> if the end of the enumeration is
+ reached and on error.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><constant>-EUNATCH</constant></term>
+
+ <listitem><para><function>sd_bus_track_remove_name()</function> or
+ <function>sd_bus_track_remove_sender()</function> have been invoked for a name not previously added to the bus
+ peer object.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>Specified parameter is invalid.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Memory allocation failed.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para><function>sd_bus_track_add_name()</function> and the other calls described here are available as a shared library,
+ which can be compiled and linked to with the <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_bus_track_new</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/src/libsystemd/sd_bus_track_new.xml b/src/libsystemd/sd_bus_track_new.xml
new file mode 100644
index 0000000000..60e2e77f75
--- /dev/null
+++ b/src/libsystemd/sd_bus_track_new.xml
@@ -0,0 +1,263 @@
+<?xml version='1.0'?> <!--*- Mode: nxml; nxml-child-indent: 2; indent-tabs-mode: nil -*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+ This file is part of systemd.
+
+ Copyright 2016 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="sd_bus_track_new">
+
+ <refentryinfo>
+ <title>sd_bus_track_new</title>
+ <productname>systemd</productname>
+
+ <authorgroup>
+ <author>
+ <contrib>Developer</contrib>
+ <firstname>Lennart</firstname>
+ <surname>Poettering</surname>
+ <email>lennart@poettering.net</email>
+ </author>
+ </authorgroup>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>sd_bus_track_new</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>sd_bus_track_new</refname>
+ <refname>sd_bus_track_ref</refname>
+ <refname>sd_bus_track_unref</refname>
+ <refname>sd_bus_track_unrefp</refname>
+ <refname>sd_bus_track_set_recursive</refname>
+ <refname>sd_bus_track_get_recursive</refname>
+ <refname>sd_bus_track_get_bus</refname>
+ <refname>sd_bus_track_get_userdata</refname>
+ <refname>sd_bus_track_set_userdata</refname>
+
+ <refpurpose>Track bus peers</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_new</function></funcdef>
+ <paramdef>sd_bus* <parameter>bus</parameter></paramdef>
+ <paramdef>sd_bus_track** <parameter>ret</parameter></paramdef>
+ <paramdef>sd_bus_track_handler_t <parameter>handler</parameter></paramdef>
+ <paramdef>void* <parameter>userdata</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>sd_bus_track *<function>sd_bus_track_ref</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>t</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>sd_bus_track *<function>sd_bus_track_unref</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>t</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>void <function>sd_bus_track_unrefp</function></funcdef>
+ <paramdef>sd_bus_track **<parameter>t</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_get_recursive</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>t</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>int <function>sd_bus_track_set_recursive</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>t</parameter></paramdef>
+ <paramdef>int <parameter>b</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>sd_bus* <function>sd_bus_track_get_bus</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>t</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>void* <function>sd_bus_track_get_userdata</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>t</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>void* <function>sd_bus_track_set_userdata</function></funcdef>
+ <paramdef>sd_bus_track *<parameter>t</parameter></paramdef>
+ <paramdef>void *userdata</paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+
+ <para><function>sd_bus_track_new()</function> creates a new bus peer tracking object. The object is allocated for
+ the specified bus, and returned in the <parameter>*ret</parameter> parameter. After use, the object should be freed
+ again by dropping the acquired reference with <function>sd_bus_track_unref()</function> (see below). A bus peer
+ tracking object may be used to keep track of peers on a specific IPC bus, for cases where peers are making use of
+ one or more local objects, in order to control the lifecycle of the local objects and ensure they stay around as
+ long as the peers needing them are around, and unreferenced (and possibly destroyed) as soon as all relevant peers
+ have vanished. Each bus peer tracking object may be used to track zero, one or more peers add a time. References to
+ specific bus peers are added via
+ <citerefentry><refentrytitle>sd_bus_track_add_name</refentrytitle><manvolnum>3</manvolnum></citerefentry> or
+ <function>sd_bus_track_add_sender()</function>. They may be dropped again via
+ <function>sd_bus_track_remove_name()</function> and
+ <function>sd_bus_track_remove_sender()</function>. Alternatively, references on peers are removed automatically
+ when they disconnect from the bus. If non-NULL the <parameter>handler</parameter> may specify a function that is
+ invoked whenever the last reference is dropped, regardless whether the reference is dropped explicitly via
+ <function>sd_bus_track_remove_name()</function> or implicitly because the peer disconnected from the bus. The final
+ argument <parameter>userdata</parameter> may be used to attach a generic user data pointer to the object. This
+ pointer is passed to the handler callback when it is invoked.</para>
+
+ <para><function>sd_bus_track_ref()</function> creates a new reference to a bus peer tracking object. This object
+ will not be destroyed until <function>sd_bus_track_unref()</function> has been called as many times plus once
+ more. Once the reference count has dropped to zero, the specified object cannot be used anymore, further calls to
+ <function>sd_bus_track_ref()</function> or <function>sd_bus_track_unref()</function> on the same object are
+ illegal.</para>
+
+ <para><function>sd_bus_track_unref()</function> destroys a reference to a bus peer tracking object.</para>
+
+ <para><function>sd_bus_track_unrefp()</function> is similar to <function>sd_bus_track_unref()</function> but takes
+ a pointer to a pointer to an <type>sd_bus_track</type> object. This call is useful in conjunction with GCC's and
+ LLVM's <ulink url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up Variable
+ Attribute</ulink>. Note that this function is defined as inline function.</para>
+
+ <para><function>sd_bus_track_ref()</function>, <function>sd_bus_track_unref()</function> and
+ <function>sd_bus_track_unrefp()</function> execute no operation if the passed in bus peer tracking object is
+ <constant>NULL</constant>.</para>
+
+ <para>Bus peer tracking objects may exist in two modes: by default they operate in non-recursive mode, but may
+ optionally be switched into recursive mode. If operating in the default non-recursive mode a peer is either tracked
+ or not tracked. In this mode invoking <function>sd_bus_track_add_name()</function> multiple times in a row for the
+ same peer is fully equivalent to calling it just once, as the call adds the peer to the set of tracked peers if
+ necessary, and executes no operation if the peer is already being tracked. A single invocation of
+ <function>sd_bus_track_remove_name()</function> removes the reference on the peer again, regardless how many times
+ <function>sd_bus_track_add_name()</function> was called before. If operating in recursive mode, the number of times
+ <function>sd_bus_track_add_name()</function> is invoked for the same peer name is counted and
+ <function>sd_bus_track_remove_name()</function> must be called the same number of times before the peer is not
+ tracked anymore, with the exception when the tracked peer vanishes from the bus, in which case the count is
+ irrelevant and the tracking of the specific peer is immediately
+ removed. <function>sd_bus_track_get_recursive()</function> may be used to determine whether the bus peer tracking
+ object is operating in recursive mode. <function>sd_bus_track_set_recursive()</function> may be used to enable or
+ disable recursive mode. By default a bus peer tracking object operates in non-recursive mode, and
+ <function>sd_bus_track_get_recursive()</function> for a newly allocated object hence returns a value equal to
+ zero. Use <function>sd_bus_track_set_recursive()</function> to enable recursive mode, right after allocation. It
+ takes a boolean argument to enable or disable recursive mode. Note that tracking objects for which
+ <function>sd_bus_track_add_name()</function> was already invoked at least once (and which hence track already one
+ or more peers) may not be switched from recursive to non-recursive mode anymore.</para>
+
+ <para><function>sd_bus_track_get_bus()</function> returns the bus object the bus peer tracking object belongs
+ to. It returns the bus object initially passed to <function>sd_bus_track_new()</function> when the object was
+ allocated.</para>
+
+ <para><function>sd_bus_track_get_userdata()</function> returns the generic user data pointer set on the bus peer
+ tracking object at the time of creation using <function>sd_bus_track_new()</function> or at a later time, using
+ <function>sd_bus_track_set_userdata()</function>.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Return Value</title>
+
+ <para>On success, <function>sd_bus_track_new()</function> and <function>sd_bus_track_set_recursive()</function>
+ return 0 or a positive integer. On failure, they return a negative errno-style error code.</para>
+
+ <para><function>sd_bus_track_ref()</function> always returns the argument.</para>
+
+ <para><function>sd_bus_track_unref()</function> always returns <constant>NULL</constant>.</para>
+
+ <para><function>sd_bus_track_get_recursive()</function> returns 0 if non-recursive mode is selected (default), and
+ greater than 0 if recursive mode is selected. On failure a negative errno-style error code is returned.</para>
+
+ <para><function>sd_bus_track_get_bus()</function> returns the bus object associated to the bus peer tracking
+ object.</para>
+
+ <para><function>sd_bus_track_get_userdata()</function> returns the generic user data pointer associated with the
+ bus peer tracking object. <function>sd_bus_track_set_userdata()</function> returns the previous user data pointer
+ set.</para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>Reference ownership</title>
+
+ <para>The <function>sd_bus_track_new()</function> function creates a new object and the caller owns the sole
+ reference. When not needed anymore, this reference should be destroyed with
+ <function>sd_bus_track_unref()</function>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><constant>-EBUSY</constant></term>
+
+ <listitem><para>Bus peers have already been added to the bus peer tracking object and
+ <function>sd_bus_track_set_recursive()</function> was called to change tracking mode.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-EINVAL</constant></term>
+
+ <listitem><para>Specified parameter is invalid
+ (<constant>NULL</constant> in case of output
+ parameters).</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>-ENOMEM</constant></term>
+
+ <listitem><para>Memory allocation failed.</para></listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Notes</title>
+
+ <para><function>sd_bus_track_new()</function> and the other calls described here are available as a shared library,
+ which can be compiled and linked to with the <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+
+ <para>
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>sd_bus_track_add_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/src/libsystemd/sd_event_new.xml b/src/libsystemd/sd_event_new.xml
index 2c23b00a8c..c0a5e98177 100644
--- a/src/libsystemd/sd_event_new.xml
+++ b/src/libsystemd/sd_event_new.xml
@@ -183,8 +183,9 @@
<refsect1>
<title>Return Value</title>
- <para>On success, <function>sd_event_new()</function> and
- <function>sd_event_default()</function> return 0 or a positive
+ <para>On success, <function>sd_event_new()</function>,
+ <function>sd_event_default()</function> and
+ <function>sd_event_get_tid()</function> return 0 or a positive
integer. On failure, they return a negative errno-style error
code. <function>sd_event_ref()</function> always returns a pointer
to the event loop object passed
diff --git a/src/libsystemd/sd_event_source_set_priority.xml b/src/libsystemd/sd_event_source_set_priority.xml
index 8c9b39fe5e..b6bab6d316 100644
--- a/src/libsystemd/sd_event_source_set_priority.xml
+++ b/src/libsystemd/sd_event_source_set_priority.xml
@@ -57,9 +57,9 @@
<funcsynopsisinfo>#include &lt;systemd/sd-event.h&gt;</funcsynopsisinfo>
<funcsynopsisinfo><token>enum</token> {
- <constant>SD_EVENT_SOURCE_IMPORTANT</constant> = -100,
- <constant>SD_EVENT_SOURCE_NORMAL</constant> = 0,
- <constant>SD_EVENT_SOURCE_IDLE</constant> = 100,
+ <constant>SD_EVENT_PRIORITY_IMPORTANT</constant> = -100,
+ <constant>SD_EVENT_PRIORITY_NORMAL</constant> = 0,
+ <constant>SD_EVENT_PRIORITY_IDLE</constant> = 100,
};</funcsynopsisinfo>
<funcprototype>
@@ -115,7 +115,7 @@
reliable. However, it is guaranteed that if events are seen on
multiple same-priority event sources at the same time, each one is
not dispatched again until all others have been dispatched
- once. This behaviour guarantees that within each priority
+ once. This behavior guarantees that within each priority
particular event sources do not starve or dominate the event
loop.</para>
diff --git a/src/libsystemd/sd_id128_get_machine.xml b/src/libsystemd/sd_id128_get_machine.xml
index 2ad1f8f728..9a86c24aed 100644
--- a/src/libsystemd/sd_id128_get_machine.xml
+++ b/src/libsystemd/sd_id128_get_machine.xml
@@ -45,6 +45,7 @@
<refnamediv>
<refname>sd_id128_get_machine</refname>
<refname>sd_id128_get_boot</refname>
+ <refname>sd_id128_get_invocation</refname>
<refpurpose>Retrieve 128-bit IDs</refpurpose>
</refnamediv>
@@ -62,6 +63,11 @@
<paramdef>sd_id128_t *<parameter>ret</parameter></paramdef>
</funcprototype>
+ <funcprototype>
+ <funcdef>int <function>sd_id128_get_invocation</function></funcdef>
+ <paramdef>sd_id128_t *<parameter>ret</parameter></paramdef>
+ </funcprototype>
+
</funcsynopsis>
</refsynopsisdiv>
@@ -83,11 +89,15 @@
for more information. This function also internally caches the
returned ID to make this call a cheap operation.</para>
- <para>Note that <function>sd_id128_get_boot()</function> always
- returns a UUID v4 compatible ID.
- <function>sd_id128_get_machine()</function> will also return a
- UUID v4-compatible ID on new installations but might not on older.
- It is possible to convert the machine ID into a UUID v4-compatible
+ <para><function>sd_id128_get_invocation()</function> returns the invocation ID of the currently executed
+ service. In its current implementation, this reads and parses the <varname>$INVOCATION_ID</varname> environment
+ variable that the service manager sets when activating a service, see
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details. The
+ ID is cached internally. In future a different mechanism to determine the invocation ID may be added.</para>
+
+ <para>Note that <function>sd_id128_get_boot()</function> and <function>sd_id128_get_invocation()</function> always
+ return UUID v4 compatible IDs. <function>sd_id128_get_machine()</function> will also return a UUID v4-compatible
+ ID on new installations but might not on older. It is possible to convert the machine ID into a UUID v4-compatible
one. For more information, see
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
@@ -107,11 +117,10 @@
<refsect1>
<title>Notes</title>
- <para>The <function>sd_id128_get_machine()</function> and
- <function>sd_id128_get_boot()</function> interfaces are available
- as a shared library, which can be compiled and linked to with the
- <literal>libsystemd</literal> <citerefentry project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- file.</para>
+ <para>The <function>sd_id128_get_machine()</function>, <function>sd_id128_get_boot()</function> and
+ <function>sd_id128_get_invocation()</function> interfaces are available as a shared library, which can be compiled
+ and linked to with the <literal>libsystemd</literal> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
</refsect1>
<refsect1>
@@ -121,8 +130,9 @@
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>random</refentrytitle><manvolnum>4</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>sd_id128_randomize</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+ <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>sd_id128_randomize</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+ <citerefentry project='man-pages'><refentrytitle>random</refentrytitle><manvolnum>4</manvolnum></citerefentry>
</para>
</refsect1>
diff --git a/src/libsystemd/sd_is_fifo.xml b/src/libsystemd/sd_is_fifo.xml
index 627cb87aaf..7ff02cbfec 100644
--- a/src/libsystemd/sd_is_fifo.xml
+++ b/src/libsystemd/sd_is_fifo.xml
@@ -117,10 +117,10 @@
whether the specified file descriptor refers to a socket. If the
<parameter>family</parameter> parameter is not
<constant>AF_UNSPEC</constant>, it is checked whether the socket
- is of the specified family (AF_UNIX, <constant>AF_INET</constant>,
- ...). If the <parameter>type</parameter> parameter is not 0, it is
- checked whether the socket is of the specified type
- (<constant>SOCK_STREAM</constant>,
+ is of the specified family (<constant>AF_UNIX</constant>,
+ <constant>AF_INET</constant>, ...). If the <parameter>type</parameter>
+ parameter is not 0, it is checked whether the socket is of the
+ specified type (<constant>SOCK_STREAM</constant>,
<constant>SOCK_DGRAM</constant>, ...). If the
<parameter>listening</parameter> parameter is positive, it is
checked whether the socket is in accepting mode, i.e.
diff --git a/src/libsystemd/sd_journal_add_match.xml b/src/libsystemd/sd_journal_add_match.xml
index 98415d53fd..7c64329aed 100644
--- a/src/libsystemd/sd_journal_add_match.xml
+++ b/src/libsystemd/sd_journal_add_match.xml
@@ -168,6 +168,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_add_match()</function>,
<function>sd_journal_add_disjunction()</function>,
<function>sd_journal_add_conjunction()</function> and
diff --git a/src/libsystemd/sd_journal_enumerate_fields.xml b/src/libsystemd/sd_journal_enumerate_fields.xml
index fa5884106b..bc2c21ed4b 100644
--- a/src/libsystemd/sd_journal_enumerate_fields.xml
+++ b/src/libsystemd/sd_journal_enumerate_fields.xml
@@ -110,6 +110,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_enumerate_fields()</function> and <function>sd_journal_restart_fields()</function>
interfaces are available as a shared library, which can be compiled and linked to with the
<constant>libsystemd</constant> <citerefentry
diff --git a/src/libsystemd/sd_journal_get_catalog.xml b/src/libsystemd/sd_journal_get_catalog.xml
index c19eb11b20..35ec46f63e 100644
--- a/src/libsystemd/sd_journal_get_catalog.xml
+++ b/src/libsystemd/sd_journal_get_catalog.xml
@@ -112,6 +112,10 @@
<refsect1>
<title>Notes</title>
+ <para>Function <function>sd_journal_get_catalog()</function> is thread-agnostic and only a
+ single thread may operate on a given <structname>sd_journal</structname> object. Function
+ <function>sd_journal_get_catalog_for_message_id() is thread-safe.</function></para>
+
<para>The <function>sd_journal_get_catalog()</function> and
<function>sd_journal_get_catalog_for_message_id()</function>
interfaces are available as a shared library, which can be
diff --git a/src/libsystemd/sd_journal_get_cursor.xml b/src/libsystemd/sd_journal_get_cursor.xml
index a400d8b1b5..b7aa05f8b2 100644
--- a/src/libsystemd/sd_journal_get_cursor.xml
+++ b/src/libsystemd/sd_journal_get_cursor.xml
@@ -122,6 +122,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_get_cursor()</function> and
<function>sd_journal_test_cursor()</function> interfaces are
available as a shared library, which can be compiled and linked to
diff --git a/src/libsystemd/sd_journal_get_cutoff_realtime_usec.xml b/src/libsystemd/sd_journal_get_cutoff_realtime_usec.xml
index 23e7cc65e8..0950e11b44 100644
--- a/src/libsystemd/sd_journal_get_cutoff_realtime_usec.xml
+++ b/src/libsystemd/sd_journal_get_cutoff_realtime_usec.xml
@@ -120,6 +120,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The
<function>sd_journal_get_cutoff_realtime_usec()</function> and
<function>sd_journal_get_cutoff_monotonic_usec()</function>
diff --git a/src/libsystemd/sd_journal_get_usage.xml b/src/libsystemd/sd_journal_get_usage.xml
index 72c804d834..06b0ff534d 100644
--- a/src/libsystemd/sd_journal_get_usage.xml
+++ b/src/libsystemd/sd_journal_get_usage.xml
@@ -80,6 +80,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_get_usage()</function> interface is
available as a shared library, which can be compiled and linked to
with the
diff --git a/src/libsystemd/sd_journal_has_runtime_files.xml b/src/libsystemd/sd_journal_has_runtime_files.xml
index 237e649206..3f6d56ca77 100644
--- a/src/libsystemd/sd_journal_has_runtime_files.xml
+++ b/src/libsystemd/sd_journal_has_runtime_files.xml
@@ -86,6 +86,18 @@
</refsect1>
<refsect1>
+ <title>Notes</title>
+
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
+ <para>Functions listed here are available as a shared library, which can be compiled and linked
+ to with the <constant>libsystemd</constant> <citerefentry
+ project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ file.</para>
+ </refsect1>
+
+ <refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>
diff --git a/src/libsystemd/sd_journal_next.xml b/src/libsystemd/sd_journal_next.xml
index 115fe26661..7c385de260 100644
--- a/src/libsystemd/sd_journal_next.xml
+++ b/src/libsystemd/sd_journal_next.xml
@@ -146,6 +146,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_next()</function>,
<function>sd_journal_previous()</function>,
<function>sd_journal_next_skip()</function> and
diff --git a/src/libsystemd/sd_journal_open.xml b/src/libsystemd/sd_journal_open.xml
index 153af2387f..25b3048f2e 100644
--- a/src/libsystemd/sd_journal_open.xml
+++ b/src/libsystemd/sd_journal_open.xml
@@ -129,10 +129,13 @@
<para><function>sd_journal_open_directory()</function> is similar to <function>sd_journal_open()</function> but
takes an absolute directory path as argument. All journal files in this directory will be opened and interleaved
- automatically. This call also takes a flags argument. The only flags parameter accepted by this call is
- <constant>SD_JOURNAL_OS_ROOT</constant>. If specified, the journal files are searched below the usual
- <filename>/var/log/journal</filename> and <filename>/run/log/journal</filename> relative to the specified path,
- instead of directly beneath it.</para>
+ automatically. This call also takes a flags argument. The flags parameters accepted by this call are
+ <constant>SD_JOURNAL_OS_ROOT</constant>, <constant>SD_JOURNAL_SYSTEM</constant>, and
+ <constant>SD_JOURNAL_CURRENT_USER</constant>. If <constant>SD_JOURNAL_OS_ROOT</constant> is specified, journal
+ files are searched for below the usual <filename>/var/log/journal</filename> and
+ <filename>/run/log/journal</filename> relative to the specified path, instead of directly beneath it.
+ The other two flags limit which files are opened, the same as for <function>sd_journal_open()</function>.
+ </para>
<para><function>sd_journal_open_directory_fd()</function> is similar to
<function>sd_journal_open_directory()</function>, but takes a file descriptor referencing a directory in the file
@@ -205,6 +208,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_open()</function>,
<function>sd_journal_open_directory()</function> and
<function>sd_journal_close()</function> interfaces are available
diff --git a/src/libsystemd/sd_journal_print.xml b/src/libsystemd/sd_journal_print.xml
index 76542527fc..2d8dd635aa 100644
--- a/src/libsystemd/sd_journal_print.xml
+++ b/src/libsystemd/sd_journal_print.xml
@@ -201,9 +201,10 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
</refsect1>
<refsect1>
- <title>Async signal safety</title>
- <para><function>sd_journal_sendv()</function> is "async signal
- safe" in the meaning of
+ <title>Thread safety</title>
+ <para>All functions listed here are thread-safe and may be called in parallel from multiple threads.</para>
+
+ <para><function>sd_journal_sendv()</function> is "async signal safe" in the meaning of
<citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
</para>
diff --git a/src/libsystemd/sd_journal_query_unique.xml b/src/libsystemd/sd_journal_query_unique.xml
index dbff55c105..d7a41a039c 100644
--- a/src/libsystemd/sd_journal_query_unique.xml
+++ b/src/libsystemd/sd_journal_query_unique.xml
@@ -150,6 +150,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_query_unique()</function>,
<function>sd_journal_enumerate_unique()</function> and
<function>sd_journal_restart_unique()</function> interfaces are
diff --git a/src/libsystemd/sd_journal_seek_head.xml b/src/libsystemd/sd_journal_seek_head.xml
index d74c2d5bbc..985073496c 100644
--- a/src/libsystemd/sd_journal_seek_head.xml
+++ b/src/libsystemd/sd_journal_seek_head.xml
@@ -144,6 +144,9 @@
<refsect1>
<title>Notes</title>
+ <para>All functions listed here are thread-agnostic and only a single thread may operate
+ on a given <structname>sd_journal</structname> object.</para>
+
<para>The <function>sd_journal_seek_head()</function>,
<function>sd_journal_seek_tail()</function>,
<function>sd_journal_seek_monotonic_usec()</function>,
diff --git a/src/libsystemd/sd_journal_stream_fd.xml b/src/libsystemd/sd_journal_stream_fd.xml
index 2ea7731b48..db88eba1bc 100644
--- a/src/libsystemd/sd_journal_stream_fd.xml
+++ b/src/libsystemd/sd_journal_stream_fd.xml
@@ -104,6 +104,10 @@
<refsect1>
<title>Notes</title>
+ <para>Function <function>sd_journal_stream_fd()</function> is thread-safe and may be called
+ from multiple threads. All calls will return the same file descriptor, although temporarily
+ multiple file descriptors may be open.</para>
+
<para>The <function>sd_journal_stream_fd()</function> interface is
available as a shared library, which can be compiled and linked to
with the
diff --git a/src/libsystemd/sd_notify.xml b/src/libsystemd/sd_notify.xml
index 025fbec6c1..94542b80b8 100644
--- a/src/libsystemd/sd_notify.xml
+++ b/src/libsystemd/sd_notify.xml
@@ -205,28 +205,25 @@
<varlistentry>
<term>FDSTORE=1</term>
- <listitem><para>Stores additional file descriptors in the
- service manager. File descriptors sent this way will be
- maintained per-service by the service manager and be passed
- again using the usual file descriptor passing logic on the
- next invocation of the service (see
- <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
- This is useful for implementing service restart schemes where
- services serialize their state to <filename>/run</filename>,
- push their file descriptors to the system manager, and are
- then restarted, retrieving their state again via socket
- passing and <filename>/run</filename>. Note that the service
- manager will accept messages for a service only if
- <varname>FileDescriptorStoreMax=</varname> is set to non-zero
- for it (defaults to zero). See
- <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
- for details. Multiple arrays of file descriptors may be sent
- in separate messages, in which case the arrays are combined.
- Note that the service manager removes duplicate file
- descriptors before passing them to the service. Use
- <function>sd_pid_notify_with_fds()</function> to send messages
- with <literal>FDSTORE=1</literal>, see
- below.</para></listitem>
+ <listitem><para>Stores additional file descriptors in the service manager. File
+ descriptors sent this way will be maintained per-service by the service manager
+ and will be passed again using the usual file descriptor passing logic on the next
+ invocation of the service, see
+ <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ This is useful for implementing service restart schemes where services serialize
+ their state to <filename>/run</filename>, push their file descriptors to the
+ system manager, and are then restarted, retrieving their state again via socket
+ passing and <filename>/run</filename>. Note that the service manager will accept
+ messages for a service only if <varname>FileDescriptorStoreMax=</varname> is set
+ to non-zero for it (defaults to zero, see
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
+ File descriptors must be pollable, see
+ <citerefentry><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
+ Multiple arrays of file descriptors may be sent in separate messages, in which
+ case the arrays are combined. Note that the service manager removes duplicate
+ file descriptors before passing them to the service. Use
+ <function>sd_pid_notify_with_fds()</function> to send messages with
+ <literal>FDSTORE=1</literal>, see below.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/src/libsystemd/src/sd-bus/bus-common-errors.c b/src/libsystemd/src/sd-bus/bus-common-errors.c
index a19e98e94b..be589f8582 100644
--- a/src/libsystemd/src/sd-bus/bus-common-errors.c
+++ b/src/libsystemd/src/sd-bus/bus-common-errors.c
@@ -27,6 +27,7 @@
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID, ESRCH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST),
SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO),
SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO),
@@ -44,12 +45,16 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM),
SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED),
SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS, EEXIST),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING, ENOSYS),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER_MAPPING, ENXIO),
+ SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_GROUP_MAPPING, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID, ENXIO),
@@ -62,6 +67,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN, EINVAL),
SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS),
SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP),
+ SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY),
@@ -80,6 +86,25 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "FORMERR", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "SERVFAIL", EHOSTDOWN),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXDOMAIN", ENXIO),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTIMP", ENOSYS),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "REFUSED", EACCES),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YXDOMAIN", EEXIST),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YRRSET", EEXIST),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXRRSET", ENOENT),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTAUTH", EACCES),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTZONE", EREMOTE),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADVERS", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADKEY", EKEYREJECTED),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTIME", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADMODE", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADNAME", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADALG", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTRUNC", EBADMSG),
+ SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADCOOKIE", EBADR),
+
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO),
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY),
diff --git a/src/libsystemd/src/sd-bus/bus-common-errors.h b/src/libsystemd/src/sd-bus/bus-common-errors.h
index c8f369cb78..525b79fa77 100644
--- a/src/libsystemd/src/sd-bus/bus-common-errors.h
+++ b/src/libsystemd/src/sd-bus/bus-common-errors.h
@@ -23,6 +23,7 @@
#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
+#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID"
#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists"
#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
@@ -40,6 +41,8 @@
#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning"
+#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser"
+#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced"
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"
diff --git a/src/libsystemd/src/sd-bus/bus-error.c b/src/libsystemd/src/sd-bus/bus-error.c
index d6b45c47bc..f07560c4e5 100644
--- a/src/libsystemd/src/sd-bus/bus-error.c
+++ b/src/libsystemd/src/sd-bus/bus-error.c
@@ -71,11 +71,9 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = {
SD_BUS_ERROR_MAP_END
};
-/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section.
- * Hide them; for currently unknown reasons they get exported to the shared libries
- * even without being listed in the sym file. */
-extern const sd_bus_error_map __start_BUS_ERROR_MAP[] _hidden_;
-extern const sd_bus_error_map __stop_BUS_ERROR_MAP[] _hidden_;
+/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section */
+extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
+extern const sd_bus_error_map __stop_BUS_ERROR_MAP[];
/* Additional maps registered with sd_bus_error_add_map() are in this
* NULL terminated array */
diff --git a/src/libsystemd/src/sd-bus/bus-internal.h b/src/libsystemd/src/sd-bus/bus-internal.h
index 6e74da3283..4b313fd24d 100644
--- a/src/libsystemd/src/sd-bus/bus-internal.h
+++ b/src/libsystemd/src/sd-bus/bus-internal.h
@@ -210,6 +210,9 @@ struct sd_bus {
bool is_system:1;
bool is_user:1;
bool allow_interactive_authorization:1;
+ bool exit_on_disconnect:1;
+ bool exited:1;
+ bool exit_triggered:1;
int use_memfd;
@@ -321,12 +324,13 @@ struct sd_bus {
sd_bus_track *track_queue;
LIST_HEAD(sd_bus_slot, slots);
+ LIST_HEAD(sd_bus_track, tracks);
};
#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
-#define BUS_WQUEUE_MAX 1024
-#define BUS_RQUEUE_MAX 64*1024
+#define BUS_WQUEUE_MAX (192*1024)
+#define BUS_RQUEUE_MAX (192*1024)
#define BUS_MESSAGE_SIZE_MAX (64*1024*1024)
#define BUS_AUTH_SIZE_MAX (64*1024)
diff --git a/src/libsystemd/src/sd-bus/bus-slot.c b/src/libsystemd/src/sd-bus/bus-slot.c
index ffe992013a..c9c7a1c96e 100644
--- a/src/libsystemd/src/sd-bus/bus-slot.c
+++ b/src/libsystemd/src/sd-bus/bus-slot.c
@@ -213,9 +213,7 @@ _public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
bus_slot_disconnect(slot);
free(slot->description);
- free(slot);
-
- return NULL;
+ return mfree(slot);
}
_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
diff --git a/src/libsystemd/src/sd-bus/bus-track.c b/src/libsystemd/src/sd-bus/bus-track.c
index 86b321bdea..73cecfe543 100644
--- a/src/libsystemd/src/sd-bus/bus-track.c
+++ b/src/libsystemd/src/sd-bus/bus-track.c
@@ -25,16 +25,27 @@
#include "bus-track.h"
#include "bus-util.h"
+struct track_item {
+ unsigned n_ref;
+ char *name;
+ sd_bus_slot *slot;
+};
+
struct sd_bus_track {
unsigned n_ref;
+ unsigned n_adding; /* are we in the process of adding a new name? */
sd_bus *bus;
sd_bus_track_handler_t handler;
void *userdata;
Hashmap *names;
LIST_FIELDS(sd_bus_track, queue);
Iterator iterator;
- bool in_queue;
- bool modified;
+ bool in_list:1; /* In bus->tracks? */
+ bool in_queue:1; /* In bus->track_queue? */
+ bool modified:1;
+ bool recursive:1;
+
+ LIST_FIELDS(sd_bus_track, tracks);
};
#define MATCH_PREFIX \
@@ -57,15 +68,45 @@ struct sd_bus_track {
_x; \
})
+static struct track_item* track_item_free(struct track_item *i) {
+
+ if (!i)
+ return NULL;
+
+ sd_bus_slot_unref(i->slot);
+ free(i->name);
+ return mfree(i);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free);
+
static void bus_track_add_to_queue(sd_bus_track *track) {
assert(track);
+ /* Adds the bus track object to the queue of objects we should dispatch next, subject to a number of
+ * conditions. */
+
+ /* Already in the queue? */
if (track->in_queue)
return;
+ /* if we are currently in the process of adding a new name, then let's not enqueue this just yet, let's wait
+ * until the addition is complete. */
+ if (track->n_adding > 0)
+ return;
+
+ /* still referenced? */
+ if (hashmap_size(track->names) > 0)
+ return;
+
+ /* Nothing to call? */
if (!track->handler)
return;
+ /* Already closed? */
+ if (!track->in_list)
+ return;
+
LIST_PREPEND(queue, track->bus->track_queue, track);
track->in_queue = true;
}
@@ -80,6 +121,24 @@ static void bus_track_remove_from_queue(sd_bus_track *track) {
track->in_queue = false;
}
+static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) {
+ struct track_item *i;
+
+ assert(track);
+ assert(name);
+
+ i = hashmap_remove(track->names, name);
+ if (!i)
+ return 0;
+
+ track_item_free(i);
+
+ bus_track_add_to_queue(track);
+
+ track->modified = true;
+ return 1;
+}
+
_public_ int sd_bus_track_new(
sd_bus *bus,
sd_bus_track **track,
@@ -103,6 +162,9 @@ _public_ int sd_bus_track_new(
t->userdata = userdata;
t->bus = sd_bus_ref(bus);
+ LIST_PREPEND(tracks, bus->tracks, t);
+ t->in_list = true;
+
bus_track_add_to_queue(t);
*track = t;
@@ -122,7 +184,7 @@ _public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) {
}
_public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
- const char *n;
+ struct track_item *i;
if (!track)
return NULL;
@@ -134,15 +196,16 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
return NULL;
}
- while ((n = hashmap_first_key(track->names)))
- sd_bus_track_remove_name(track, n);
+ while ((i = hashmap_steal_first(track->names)))
+ track_item_free(i);
+
+ if (track->in_list)
+ LIST_REMOVE(tracks, track->bus->tracks, track);
bus_track_remove_from_queue(track);
hashmap_free(track->names);
sd_bus_unref(track->bus);
- free(track);
-
- return NULL;
+ return mfree(track);
}
static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -157,49 +220,76 @@ static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus
if (r < 0)
return 0;
- sd_bus_track_remove_name(track, name);
+ bus_track_remove_name_fully(track, name);
return 0;
}
_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
- _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
- _cleanup_free_ char *n = NULL;
+ _cleanup_(track_item_freep) struct track_item *n = NULL;
+ struct track_item *i;
const char *match;
int r;
assert_return(track, -EINVAL);
assert_return(service_name_is_valid(name), -EINVAL);
+ i = hashmap_get(track->names, name);
+ if (i) {
+ if (track->recursive) {
+ unsigned k = track->n_ref + 1;
+
+ if (k < track->n_ref) /* Check for overflow */
+ return -EOVERFLOW;
+
+ track->n_ref = k;
+ }
+
+ bus_track_remove_from_queue(track);
+ return 0;
+ }
+
r = hashmap_ensure_allocated(&track->names, &string_hash_ops);
if (r < 0)
return r;
- n = strdup(name);
+ n = new0(struct track_item, 1);
if (!n)
return -ENOMEM;
+ n->name = strdup(name);
+ if (!n->name)
+ return -ENOMEM;
/* First, subscribe to this name */
- match = MATCH_FOR_NAME(n);
- r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track);
- if (r < 0)
+ match = MATCH_FOR_NAME(name);
+
+ bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */
+
+ track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */
+ r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track);
+ track->n_adding--;
+ if (r < 0) {
+ bus_track_add_to_queue(track);
return r;
+ }
- r = hashmap_put(track->names, n, slot);
- if (r == -EEXIST)
- return 0;
- if (r < 0)
+ r = hashmap_put(track->names, n->name, n);
+ if (r < 0) {
+ bus_track_add_to_queue(track);
return r;
+ }
- /* Second, check if it is currently existing, or maybe
- * doesn't, or maybe disappeared already. */
- r = sd_bus_get_name_creds(track->bus, n, 0, NULL);
+ /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */
+ track->n_adding++; /* again, make sure this isn't dispatch while we are working in it */
+ r = sd_bus_get_name_creds(track->bus, name, 0, NULL);
+ track->n_adding--;
if (r < 0) {
- hashmap_remove(track->names, n);
+ hashmap_remove(track->names, name);
+ bus_track_add_to_queue(track);
return r;
}
+ n->n_ref = 1;
n = NULL;
- slot = NULL;
bus_track_remove_from_queue(track);
track->modified = true;
@@ -208,37 +298,48 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
}
_public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
- _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL;
- _cleanup_free_ char *n = NULL;
+ struct track_item *i;
assert_return(name, -EINVAL);
- if (!track)
+ if (!track) /* Treat a NULL track object as an empty track object */
return 0;
- slot = hashmap_remove2(track->names, (char*) name, (void**) &n);
- if (!slot)
- return 0;
+ if (!track->recursive)
+ return bus_track_remove_name_fully(track, name);
- if (hashmap_isempty(track->names))
- bus_track_add_to_queue(track);
+ i = hashmap_get(track->names, name);
+ if (!i)
+ return -EUNATCH;
+ if (i->n_ref <= 0)
+ return -EUNATCH;
- track->modified = true;
+ i->n_ref--;
+
+ if (i->n_ref <= 0)
+ return bus_track_remove_name_fully(track, name);
return 1;
}
_public_ unsigned sd_bus_track_count(sd_bus_track *track) {
- if (!track)
+
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
return 0;
+ /* This signature really should have returned an int, so that we can propagate errors. But well, ... Also, note
+ * that this returns the number of names being watched, and multiple references to the same name are not
+ * counted. */
+
return hashmap_size(track->names);
}
_public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) {
- assert_return(track, NULL);
assert_return(name, NULL);
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
+ return NULL;
+
return hashmap_get(track->names, (void*) name) ? name : NULL;
}
@@ -274,6 +375,9 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) {
assert_return(track, -EINVAL);
assert_return(m, -EINVAL);
+ if (sd_bus_message_get_bus(m) != track->bus)
+ return -EINVAL;
+
sender = sd_bus_message_get_sender(m);
if (!sender)
return -EINVAL;
@@ -284,9 +388,14 @@ _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) {
_public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) {
const char *sender;
- assert_return(track, -EINVAL);
assert_return(m, -EINVAL);
+ if (!track) /* Treat a NULL track object as an empty track object */
+ return 0;
+
+ if (sd_bus_message_get_bus(m) != track->bus)
+ return -EINVAL;
+
sender = sd_bus_message_get_sender(m);
if (!sender)
return -EINVAL;
@@ -304,7 +413,6 @@ void bus_track_dispatch(sd_bus_track *track) {
int r;
assert(track);
- assert(track->in_queue);
assert(track->handler);
bus_track_remove_from_queue(track);
@@ -320,6 +428,34 @@ void bus_track_dispatch(sd_bus_track *track) {
sd_bus_track_unref(track);
}
+void bus_track_close(sd_bus_track *track) {
+ struct track_item *i;
+
+ assert(track);
+
+ /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it
+ * immediately, as we are closing now, but first flush out all names. */
+
+ if (!track->in_list)
+ return; /* We already closed this one, don't close it again. */
+
+ /* Remember that this one is closed now */
+ LIST_REMOVE(tracks, track->bus->tracks, track);
+ track->in_list = false;
+
+ /* If there's no name in this one anyway, we don't have to dispatch */
+ if (hashmap_isempty(track->names))
+ return;
+
+ /* Let's flush out all names */
+ while ((i = hashmap_steal_first(track->names)))
+ track_item_free(i);
+
+ /* Invoke handler */
+ if (track->handler)
+ bus_track_dispatch(track);
+}
+
_public_ void *sd_bus_track_get_userdata(sd_bus_track *track) {
assert_return(track, NULL);
@@ -336,3 +472,55 @@ _public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) {
return ret;
}
+
+_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) {
+ assert_return(track, -EINVAL);
+
+ if (track->recursive == !!b)
+ return 0;
+
+ if (!hashmap_isempty(track->names))
+ return -EBUSY;
+
+ track->recursive = b;
+ return 0;
+}
+
+_public_ int sd_bus_track_get_recursive(sd_bus_track *track) {
+ assert_return(track, -EINVAL);
+
+ return track->recursive;
+}
+
+_public_ int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m) {
+ const char *sender;
+
+ assert_return(m, -EINVAL);
+
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
+ return 0;
+
+ if (sd_bus_message_get_bus(m) != track->bus)
+ return -EINVAL;
+
+ sender = sd_bus_message_get_sender(m);
+ if (!sender)
+ return -EINVAL;
+
+ return sd_bus_track_count_name(track, sender);
+}
+
+_public_ int sd_bus_track_count_name(sd_bus_track *track, const char *name) {
+ struct track_item *i;
+
+ assert_return(service_name_is_valid(name), -EINVAL);
+
+ if (!track) /* Let's consider a NULL object equivalent to an empty object */
+ return 0;
+
+ i = hashmap_get(track->names, name);
+ if (!i)
+ return 0;
+
+ return i->n_ref;
+}
diff --git a/src/libsystemd/src/sd-bus/bus-track.h b/src/libsystemd/src/sd-bus/bus-track.h
index 73b7503ae5..68398281ae 100644
--- a/src/libsystemd/src/sd-bus/bus-track.h
+++ b/src/libsystemd/src/sd-bus/bus-track.h
@@ -22,3 +22,4 @@
#include <systemd/sd-bus.h>
void bus_track_dispatch(sd_bus_track *track);
+void bus_track_close(sd_bus_track *track);
diff --git a/src/libsystemd/src/sd-bus/bus-util.c b/src/libsystemd/src/sd-bus/bus-util.c
index c82390634e..af44c0f9a4 100644
--- a/src/libsystemd/src/sd-bus/bus-util.c
+++ b/src/libsystemd/src/sd-bus/bus-util.c
@@ -1017,19 +1017,19 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
return r;
switch (type) {
+
case SD_BUS_TYPE_STRING: {
- const char *s;
char **p = userdata;
+ const char *s;
r = sd_bus_message_read_basic(m, type, &s);
if (r < 0)
- break;
+ return r;
if (isempty(s))
- break;
+ s = NULL;
- r = free_and_strdup(p, s);
- break;
+ return free_and_strdup(p, s);
}
case SD_BUS_TYPE_ARRAY: {
@@ -1038,13 +1038,12 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
r = bus_message_read_strv_extend(m, &l);
if (r < 0)
- break;
+ return r;
strv_free(*p);
*p = l;
l = NULL;
-
- break;
+ return 0;
}
case SD_BUS_TYPE_BOOLEAN: {
@@ -1053,57 +1052,48 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
r = sd_bus_message_read_basic(m, type, &b);
if (r < 0)
- break;
+ return r;
*p = b;
-
- break;
+ return 0;
}
+ case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32: {
- uint32_t u;
- uint32_t *p = userdata;
+ uint32_t u, *p = userdata;
r = sd_bus_message_read_basic(m, type, &u);
if (r < 0)
- break;
+ return r;
*p = u;
-
- break;
+ return 0;
}
+ case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64: {
- uint64_t t;
- uint64_t *p = userdata;
+ uint64_t t, *p = userdata;
r = sd_bus_message_read_basic(m, type, &t);
if (r < 0)
- break;
+ return r;
*p = t;
-
- break;
+ return 0;
}
case SD_BUS_TYPE_DOUBLE: {
- double d;
- double *p = userdata;
+ double d, *p = userdata;
r = sd_bus_message_read_basic(m, type, &d);
if (r < 0)
- break;
+ return r;
*p = d;
+ return 0;
+ }}
- break;
- }
-
- default:
- break;
- }
-
- return r;
+ return -EOPNOTSUPP;
}
int bus_message_map_all_properties(
@@ -1241,12 +1231,13 @@ int bus_map_all_properties(
return bus_message_map_all_properties(m, map, userdata);
}
-int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
+int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
+ _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
int r;
assert(transport >= 0);
assert(transport < _BUS_TRANSPORT_MAX);
- assert(bus);
+ assert(ret);
assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
@@ -1255,25 +1246,34 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
case BUS_TRANSPORT_LOCAL:
if (user)
- r = sd_bus_default_user(bus);
+ r = sd_bus_default_user(&bus);
else
- r = sd_bus_default_system(bus);
+ r = sd_bus_default_system(&bus);
break;
case BUS_TRANSPORT_REMOTE:
- r = sd_bus_open_system_remote(bus, host);
+ r = sd_bus_open_system_remote(&bus, host);
break;
case BUS_TRANSPORT_MACHINE:
- r = sd_bus_open_system_machine(bus, host);
+ r = sd_bus_open_system_machine(&bus, host);
break;
default:
assert_not_reached("Hmm, unknown transport type.");
}
+ if (r < 0)
+ return r;
- return r;
+ r = sd_bus_set_exit_on_disconnect(bus, true);
+ if (r < 0)
+ return r;
+
+ *ret = bus;
+ bus = NULL;
+
+ return 0;
}
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
@@ -1325,6 +1325,23 @@ int bus_property_get_bool(
return sd_bus_message_append_basic(reply, 'b', &b);
}
+int bus_property_get_id128(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ sd_id128_t *id = userdata;
+
+ if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */
+ return sd_bus_message_append(reply, "ay", 0);
+ else
+ return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
+}
+
#if __SIZEOF_SIZE_T__ != 8
int bus_property_get_size(
sd_bus *bus,
diff --git a/src/libsystemd/src/sd-bus/bus-util.h b/src/libsystemd/src/sd-bus/bus-util.h
index 6b45fad3ce..01dba4807d 100644
--- a/src/libsystemd/src/sd-bus/bus-util.h
+++ b/src/libsystemd/src/sd-bus/bus-util.h
@@ -79,6 +79,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b
int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all);
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
+int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
#define bus_property_get_usec ((sd_bus_property_get_t) NULL)
#define bus_property_set_usec ((sd_bus_property_set_t) NULL)
diff --git a/src/libsystemd/src/sd-bus/sd-bus.c b/src/libsystemd/src/sd-bus/sd-bus.c
index 52d3e8f2b3..e9b2bac003 100644
--- a/src/libsystemd/src/sd-bus/sd-bus.c
+++ b/src/libsystemd/src/sd-bus/sd-bus.c
@@ -108,6 +108,7 @@ static void bus_free(sd_bus *b) {
assert(b);
assert(!b->track_queue);
+ assert(!b->tracks);
b->state = BUS_CLOSED;
@@ -2641,62 +2642,101 @@ null_message:
return r;
}
-static int process_closing(sd_bus *bus, sd_bus_message **ret) {
+static int bus_exit_now(sd_bus *bus) {
+ assert(bus);
+
+ /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes
+ * sd_event_exit(), otherwise invokes libc exit(). */
+
+ if (bus->exited) /* did we already exit? */
+ return 0;
+ if (!bus->exit_triggered) /* was the exit condition triggered? */
+ return 0;
+ if (!bus->exit_on_disconnect) /* Shall we actually exit on disconnection? */
+ return 0;
+
+ bus->exited = true; /* never exit more than once */
+
+ log_debug("Bus connection disconnected, exiting.");
+
+ if (bus->event)
+ return sd_event_exit(bus->event, EXIT_FAILURE);
+ else
+ exit(EXIT_FAILURE);
+
+ assert_not_reached("exit() didn't exit?");
+}
+
+static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
- struct reply_callback *c;
+ sd_bus_slot *slot;
int r;
assert(bus);
- assert(bus->state == BUS_CLOSING);
+ assert(c);
- c = ordered_hashmap_first(bus->reply_callbacks);
- if (c) {
- _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
- sd_bus_slot *slot;
+ r = bus_message_new_synthetic_error(
+ bus,
+ c->cookie,
+ &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
+ &m);
+ if (r < 0)
+ return r;
- /* First, fail all outstanding method calls */
- r = bus_message_new_synthetic_error(
- bus,
- c->cookie,
- &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
- &m);
- if (r < 0)
- return r;
+ r = bus_seal_synthetic_message(bus, m);
+ if (r < 0)
+ return r;
- r = bus_seal_synthetic_message(bus, m);
- if (r < 0)
- return r;
+ if (c->timeout != 0) {
+ prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+ c->timeout = 0;
+ }
- if (c->timeout != 0) {
- prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
- c->timeout = 0;
- }
+ ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
+ c->cookie = 0;
- ordered_hashmap_remove(bus->reply_callbacks, &c->cookie);
- c->cookie = 0;
+ slot = container_of(c, sd_bus_slot, reply_callback);
- slot = container_of(c, sd_bus_slot, reply_callback);
+ bus->iteration_counter++;
- bus->iteration_counter++;
+ bus->current_message = m;
+ bus->current_slot = sd_bus_slot_ref(slot);
+ bus->current_handler = c->callback;
+ bus->current_userdata = slot->userdata;
+ r = c->callback(m, slot->userdata, &error_buffer);
+ bus->current_userdata = NULL;
+ bus->current_handler = NULL;
+ bus->current_slot = NULL;
+ bus->current_message = NULL;
- bus->current_message = m;
- bus->current_slot = sd_bus_slot_ref(slot);
- bus->current_handler = c->callback;
- bus->current_userdata = slot->userdata;
- r = c->callback(m, slot->userdata, &error_buffer);
- bus->current_userdata = NULL;
- bus->current_handler = NULL;
- bus->current_slot = NULL;
- bus->current_message = NULL;
+ if (slot->floating) {
+ bus_slot_disconnect(slot);
+ sd_bus_slot_unref(slot);
+ }
- if (slot->floating) {
- bus_slot_disconnect(slot);
- sd_bus_slot_unref(slot);
- }
+ sd_bus_slot_unref(slot);
- sd_bus_slot_unref(slot);
+ return bus_maybe_reply_error(m, r, &error_buffer);
+}
- return bus_maybe_reply_error(m, r, &error_buffer);
+static int process_closing(sd_bus *bus, sd_bus_message **ret) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
+ struct reply_callback *c;
+ int r;
+
+ assert(bus);
+ assert(bus->state == BUS_CLOSING);
+
+ /* First, fail all outstanding method calls */
+ c = ordered_hashmap_first(bus->reply_callbacks);
+ if (c)
+ return process_closing_reply_callback(bus, c);
+
+ /* Then, fake-drop all remaining bus tracking references */
+ if (bus->tracks) {
+ bus_track_close(bus->tracks);
+ return 1;
}
/* Then, synthesize a Disconnected message */
@@ -2728,6 +2768,10 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
if (r != 0)
goto finish;
+ /* Nothing else to do, exit now, if the condition holds */
+ bus->exit_triggered = true;
+ (void) bus_exit_now(bus);
+
if (ret) {
*ret = m;
m = NULL;
@@ -3790,3 +3834,21 @@ _public_ void sd_bus_default_flush_close(void) {
flush_close(default_user_bus);
flush_close(default_system_bus);
}
+
+_public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) {
+ assert_return(bus, -EINVAL);
+
+ /* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already
+ * disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never
+ * from the client side. */
+ bus->exit_on_disconnect = b;
+
+ /* If the exit condition was triggered already, exit immediately. */
+ return bus_exit_now(bus);
+}
+
+_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) {
+ assert_return(bus, -EINVAL);
+
+ return bus->exit_on_disconnect;
+}
diff --git a/src/libsystemd/src/sd-bus/test-bus-chat.c b/src/libsystemd/src/sd-bus/test-bus-chat.c
index 6dc643c173..2e394c56e2 100644
--- a/src/libsystemd/src/sd-bus/test-bus-chat.c
+++ b/src/libsystemd/src/sd-bus/test-bus-chat.c
@@ -352,7 +352,7 @@ finish:
static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
bool *x = userdata;
- log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m)));
+ log_error_errno(sd_bus_message_get_errno(m), "Quit callback: %m");
*x = 1;
return 1;
diff --git a/src/libsystemd/src/sd-bus/test-bus-creds.c b/src/libsystemd/src/sd-bus/test-bus-creds.c
index fd226e06d2..ae4f4804d4 100644
--- a/src/libsystemd/src/sd-bus/test-bus-creds.c
+++ b/src/libsystemd/src/sd-bus/test-bus-creds.c
@@ -28,12 +28,17 @@ int main(int argc, char *argv[]) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
int r;
- if (cg_unified() == -ENOMEDIUM) {
- puts("Skipping test: /sys/fs/cgroup/ not available");
+ log_set_max_level(LOG_DEBUG);
+ log_parse_environment();
+ log_open();
+
+ if (cg_all_unified() == -ENOMEDIUM) {
+ log_info("Skipping test: /sys/fs/cgroup/ not available");
return EXIT_TEST_SKIP;
}
r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL);
+ log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_creds_new_from_pid: %m");
assert_se(r >= 0);
bus_creds_dump(creds, NULL, true);
diff --git a/src/libsystemd/src/sd-bus/test-bus-track.c b/src/libsystemd/src/sd-bus/test-bus-track.c
new file mode 100644
index 0000000000..ad87e7f8e0
--- /dev/null
+++ b/src/libsystemd/src/sd-bus/test-bus-track.c
@@ -0,0 +1,113 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <systemd/sd-bus.h>
+
+#include "systemd-basic/macro.h"
+
+static bool track_cb_called_x = false;
+static bool track_cb_called_y = false;
+
+static int track_cb_x(sd_bus_track *t, void *userdata) {
+
+ log_error("TRACK CB X");
+
+ assert_se(!track_cb_called_x);
+ track_cb_called_x = true;
+
+ /* This means b's name disappeared. Let's now disconnect, to make sure the track handling on disconnect works
+ * as it should. */
+
+ assert_se(shutdown(sd_bus_get_fd(sd_bus_track_get_bus(t)), SHUT_RDWR) >= 0);
+ return 1;
+}
+
+static int track_cb_y(sd_bus_track *t, void *userdata) {
+ int r;
+
+ log_error("TRACK CB Y");
+
+ assert_se(!track_cb_called_y);
+ track_cb_called_y = true;
+
+ /* We got disconnected, let's close everything */
+
+ r = sd_event_exit(sd_bus_get_event(sd_bus_track_get_bus(t)), EXIT_SUCCESS);
+ assert_se(r >= 0);
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+ _cleanup_(sd_bus_track_unrefp) sd_bus_track *x = NULL, *y = NULL;
+ _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL;
+ const char *unique;
+ int r;
+
+ r = sd_event_default(&event);
+ assert_se(r >= 0);
+
+ r = sd_bus_open_system(&a);
+ if (IN_SET(r, -ECONNREFUSED, -ENOENT)) {
+ log_info("Failed to connect to bus, skipping tests.");
+ return EXIT_TEST_SKIP;
+ }
+ assert_se(r >= 0);
+
+ r = sd_bus_attach_event(a, event, SD_EVENT_PRIORITY_NORMAL);
+ assert_se(r >= 0);
+
+ r = sd_bus_open_system(&b);
+ assert_se(r >= 0);
+
+ r = sd_bus_attach_event(b, event, SD_EVENT_PRIORITY_NORMAL);
+ assert_se(r >= 0);
+
+ /* Watch b's name from a */
+ r = sd_bus_track_new(a, &x, track_cb_x, NULL);
+ assert_se(r >= 0);
+
+ r = sd_bus_get_unique_name(b, &unique);
+ assert_se(r >= 0);
+
+ r = sd_bus_track_add_name(x, unique);
+ assert_se(r >= 0);
+
+ /* Watch's a's own name from a */
+ r = sd_bus_track_new(a, &y, track_cb_y, NULL);
+ assert_se(r >= 0);
+
+ r = sd_bus_get_unique_name(a, &unique);
+ assert_se(r >= 0);
+
+ r = sd_bus_track_add_name(y, unique);
+ assert_se(r >= 0);
+
+ /* Now make b's name disappear */
+ sd_bus_close(b);
+
+ r = sd_event_loop(event);
+ assert_se(r >= 0);
+
+ assert_se(track_cb_called_x);
+ assert_se(track_cb_called_y);
+
+ return 0;
+}
diff --git a/src/libsystemd/src/sd-device/sd-device.c b/src/libsystemd/src/sd-device/sd-device.c
index 3f7e21af96..ba654eac14 100644
--- a/src/libsystemd/src/sd-device/sd-device.c
+++ b/src/libsystemd/src/sd-device/sd-device.c
@@ -31,6 +31,7 @@
#include "systemd-basic/parse-util.h"
#include "systemd-basic/path-util.h"
#include "systemd-basic/set.h"
+#include "systemd-basic/socket-util.h"
#include "systemd-basic/stat-util.h"
#include "systemd-basic/string-util.h"
#include "systemd-basic/strv.h"
@@ -629,9 +630,9 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
if (r < 0)
return r;
- sk = socket(PF_INET, SOCK_DGRAM, 0);
+ sk = socket_ioctl_fd();
if (sk < 0)
- return -errno;
+ return sk;
r = ioctl(sk, SIOCGIFNAME, &ifr);
if (r < 0)
diff --git a/src/libsystemd/src/sd-hwdb/hwdb-internal.h b/src/libsystemd/src/sd-hwdb/hwdb-internal.h
index 35d4378122..78f430e869 100644
--- a/src/libsystemd/src/sd-hwdb/hwdb-internal.h
+++ b/src/libsystemd/src/sd-hwdb/hwdb-internal.h
@@ -70,3 +70,11 @@ struct trie_value_entry_f {
le64_t key_off;
le64_t value_off;
} _packed_;
+
+/* v2 extends v1 with filename and line-number */
+struct trie_value_entry2_f {
+ le64_t key_off;
+ le64_t value_off;
+ le64_t filename_off;
+ le64_t line_number;
+} _packed_;
diff --git a/src/libsystemd/src/sd-hwdb/sd-hwdb.c b/src/libsystemd/src/sd-hwdb/sd-hwdb.c
index 0891719604..8303879455 100644
--- a/src/libsystemd/src/sd-hwdb/sd-hwdb.c
+++ b/src/libsystemd/src/sd-hwdb/sd-hwdb.c
@@ -97,15 +97,20 @@ static void linebuf_rem_char(struct linebuf *buf) {
linebuf_rem(buf, 1);
}
-static const struct trie_child_entry_f *trie_node_children(sd_hwdb *hwdb, const struct trie_node_f *node) {
- return (const struct trie_child_entry_f *)((const char *)node + le64toh(hwdb->head->node_size));
+static const struct trie_child_entry_f *trie_node_child(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) {
+ const char *base = (const char *)node;
+
+ base += le64toh(hwdb->head->node_size);
+ base += idx * le64toh(hwdb->head->child_entry_size);
+ return (const struct trie_child_entry_f *)base;
}
-static const struct trie_value_entry_f *trie_node_values(sd_hwdb *hwdb, const struct trie_node_f *node) {
+static const struct trie_value_entry_f *trie_node_value(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) {
const char *base = (const char *)node;
base += le64toh(hwdb->head->node_size);
base += node->children_count * le64toh(hwdb->head->child_entry_size);
+ base += idx * le64toh(hwdb->head->value_entry_size);
return (const struct trie_value_entry_f *)base;
}
@@ -129,19 +134,20 @@ static const struct trie_node_f *node_lookup_f(sd_hwdb *hwdb, const struct trie_
struct trie_child_entry_f search;
search.c = c;
- child = bsearch(&search, trie_node_children(hwdb, node), node->children_count,
+ child = bsearch(&search, (const char *)node + le64toh(hwdb->head->node_size), node->children_count,
le64toh(hwdb->head->child_entry_size), trie_children_cmp_f);
if (child)
return trie_node_from_off(hwdb, child->child_off);
return NULL;
}
-static int hwdb_add_property(sd_hwdb *hwdb, const char *key, const char *value) {
+static int hwdb_add_property(sd_hwdb *hwdb, const struct trie_value_entry_f *entry) {
+ const char *key;
int r;
assert(hwdb);
- assert(key);
- assert(value);
+
+ key = trie_string(hwdb, entry->key_off);
/*
* Silently ignore all properties which do not start with a
@@ -152,11 +158,25 @@ static int hwdb_add_property(sd_hwdb *hwdb, const char *key, const char *value)
key++;
+ if (le64toh(hwdb->head->value_entry_size) >= sizeof(struct trie_value_entry2_f)) {
+ const struct trie_value_entry2_f *old, *entry2;
+
+ entry2 = (const struct trie_value_entry2_f *)entry;
+ old = ordered_hashmap_get(hwdb->properties, key);
+ if (old) {
+ /* on duplicates, we order by filename and line-number */
+ r = strcmp(trie_string(hwdb, entry2->filename_off), trie_string(hwdb, old->filename_off));
+ if (r < 0 ||
+ (r == 0 && entry2->line_number < old->line_number))
+ return 0;
+ }
+ }
+
r = ordered_hashmap_ensure_allocated(&hwdb->properties, &string_hash_ops);
if (r < 0)
return r;
- r = ordered_hashmap_replace(hwdb->properties, key, (char*)value);
+ r = ordered_hashmap_replace(hwdb->properties, key, (void *)entry);
if (r < 0)
return r;
@@ -177,7 +197,7 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t
linebuf_add(buf, prefix + p, len);
for (i = 0; i < node->children_count; i++) {
- const struct trie_child_entry_f *child = &trie_node_children(hwdb, node)[i];
+ const struct trie_child_entry_f *child = trie_node_child(hwdb, node, i);
linebuf_add_char(buf, child->c);
err = trie_fnmatch_f(hwdb, trie_node_from_off(hwdb, child->child_off), 0, buf, search);
@@ -188,8 +208,7 @@ static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t
if (le64toh(node->values_count) && fnmatch(linebuf_get(buf), search, 0) == 0)
for (i = 0; i < le64toh(node->values_count); i++) {
- err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[i].key_off),
- trie_string(hwdb, trie_node_values(hwdb, node)[i].value_off));
+ err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, i));
if (err < 0)
return err;
}
@@ -254,8 +273,7 @@ static int trie_search_f(sd_hwdb *hwdb, const char *search) {
size_t n;
for (n = 0; n < le64toh(node->values_count); n++) {
- err = hwdb_add_property(hwdb, trie_string(hwdb, trie_node_values(hwdb, node)[n].key_off),
- trie_string(hwdb, trie_node_values(hwdb, node)[n].value_off));
+ err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, n));
if (err < 0)
return err;
}
@@ -410,7 +428,7 @@ static int properties_prepare(sd_hwdb *hwdb, const char *modalias) {
}
_public_ int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **_value) {
- const char *value;
+ const struct trie_value_entry_f *entry;
int r;
assert_return(hwdb, -EINVAL);
@@ -422,11 +440,11 @@ _public_ int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, c
if (r < 0)
return r;
- value = ordered_hashmap_get(hwdb->properties, key);
- if (!value)
+ entry = ordered_hashmap_get(hwdb->properties, key);
+ if (!entry)
return -ENOENT;
- *_value = value;
+ *_value = trie_string(hwdb, entry->value_off);
return 0;
}
@@ -449,8 +467,8 @@ _public_ int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias) {
}
_public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value) {
+ const struct trie_value_entry_f *entry;
const void *k;
- void *v;
assert_return(hwdb, -EINVAL);
assert_return(key, -EINVAL);
@@ -459,12 +477,12 @@ _public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **val
if (hwdb->properties_modified)
return -EAGAIN;
- ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, &v, &k);
+ ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, (void **)&entry, &k);
if (!k)
return 0;
*key = k;
- *value = v;
+ *value = trie_string(hwdb, entry->value_off);
return 1;
}
diff --git a/src/libsystemd/src/sd-id128/id128-util.c b/src/libsystemd/src/sd-id128/id128-util.c
index cd32543d0c..0314127684 100644
--- a/src/libsystemd/src/sd-id128/id128-util.c
+++ b/src/libsystemd/src/sd-id128/id128-util.c
@@ -193,3 +193,16 @@ int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) {
return id128_write_fd(fd, f, id, do_sync);
}
+
+void id128_hash_func(const void *p, struct siphash *state) {
+ siphash24_compress(p, 16, state);
+}
+
+int id128_compare_func(const void *a, const void *b) {
+ return memcmp(a, b, 16);
+}
+
+const struct hash_ops id128_hash_ops = {
+ .hash = id128_hash_func,
+ .compare = id128_compare_func,
+};
diff --git a/src/libsystemd/src/sd-id128/id128-util.h b/src/libsystemd/src/sd-id128/id128-util.h
index 0c57d693e5..7ca482a727 100644
--- a/src/libsystemd/src/sd-id128/id128-util.h
+++ b/src/libsystemd/src/sd-id128/id128-util.h
@@ -23,6 +23,7 @@
#include <systemd/sd-id128.h>
+#include "systemd-basic/hash-funcs.h"
#include "systemd-basic/macro.h"
char *id128_to_uuid_string(sd_id128_t id, char s[37]);
@@ -44,3 +45,7 @@ int id128_read(const char *p, Id128Format f, sd_id128_t *ret);
int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync);
int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync);
+
+void id128_hash_func(const void *p, struct siphash *state);
+int id128_compare_func(const void *a, const void *b) _pure_;
+extern const struct hash_ops id128_hash_ops;
diff --git a/src/libsystemd/src/sd-id128/sd-id128.c b/src/libsystemd/src/sd-id128/sd-id128.c
index 9c036fb4cb..275949c651 100644
--- a/src/libsystemd/src/sd-id128/sd-id128.c
+++ b/src/libsystemd/src/sd-id128/sd-id128.c
@@ -130,6 +130,28 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) {
return 0;
}
+_public_ int sd_id128_get_invocation(sd_id128_t *ret) {
+ static thread_local sd_id128_t saved_invocation_id = {};
+ int r;
+
+ assert_return(ret, -EINVAL);
+
+ if (sd_id128_is_null(saved_invocation_id)) {
+ const char *e;
+
+ e = secure_getenv("INVOCATION_ID");
+ if (!e)
+ return -ENXIO;
+
+ r = sd_id128_from_string(e, &saved_invocation_id);
+ if (r < 0)
+ return r;
+ }
+
+ *ret = saved_invocation_id;
+ return 0;
+}
+
static sd_id128_t make_v4_uuid(sd_id128_t id) {
/* Stolen from generate_random_uuid() of drivers/char/random.c
* in the kernel sources */
diff --git a/src/libsystemd/src/sd-journal/journal-file.c b/src/libsystemd/src/sd-journal/journal-file.c
index 7910270925..10972869c8 100644
--- a/src/libsystemd/src/sd-journal/journal-file.c
+++ b/src/libsystemd/src/sd-journal/journal-file.c
@@ -336,8 +336,13 @@ JournalFile* journal_file_close(JournalFile *f) {
#ifdef HAVE_GCRYPT
/* Write the final tag */
- if (f->seal && f->writable)
- journal_file_append_tag(f);
+ if (f->seal && f->writable) {
+ int r;
+
+ r = journal_file_append_tag(f);
+ if (r < 0)
+ log_error_errno(r, "Failed to append tag when closing journal: %m");
+ }
#endif
if (f->post_change_timer) {
@@ -392,8 +397,7 @@ JournalFile* journal_file_close(JournalFile *f) {
gcry_md_close(f->hmac);
#endif
- free(f);
- return NULL;
+ return mfree(f);
}
void journal_file_close_set(Set *s) {
@@ -566,8 +570,8 @@ static int journal_file_verify_header(JournalFile *f) {
return -ENODATA;
if (f->writable) {
- uint8_t state;
sd_id128_t machine_id;
+ uint8_t state;
int r;
r = sd_id128_get_machine(&machine_id);
@@ -588,6 +592,14 @@ static int journal_file_verify_header(JournalFile *f) {
log_debug("Journal file %s has unknown state %i.", f->path, state);
return -EBUSY;
}
+
+ /* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't
+ * be strictly ordered in the entries in the file anymore, and we can't have that since it breaks
+ * bisection. */
+ if (le64toh(f->header->tail_entry_realtime) > now(CLOCK_REALTIME)) {
+ log_debug("Journal file %s is from the future, refusing to append new data to it that'd be older.", f->path);
+ return -ETXTBSY;
+ }
}
f->compress_xz = JOURNAL_HEADER_COMPRESSED_XZ(f->header);
@@ -745,12 +757,16 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
assert(ret);
/* Objects may only be located at multiple of 64 bit */
- if (!VALID64(offset))
+ if (!VALID64(offset)) {
+ log_debug("Attempt to move to object at non-64bit boundary: %" PRIu64, offset);
return -EBADMSG;
+ }
/* Object may not be located in the file header */
- if (offset < le64toh(f->header->header_size))
+ if (offset < le64toh(f->header->header_size)) {
+ log_debug("Attempt to move to object located in file header: %" PRIu64, offset);
return -EBADMSG;
+ }
r = journal_file_move_to(f, type, false, offset, sizeof(ObjectHeader), &t);
if (r < 0)
@@ -759,17 +775,29 @@ int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset
o = (Object*) t;
s = le64toh(o->object.size);
- if (s < sizeof(ObjectHeader))
+ if (s == 0) {
+ log_debug("Attempt to move to uninitialized object: %" PRIu64, offset);
return -EBADMSG;
+ }
+ if (s < sizeof(ObjectHeader)) {
+ log_debug("Attempt to move to overly short object: %" PRIu64, offset);
+ return -EBADMSG;
+ }
- if (o->object.type <= OBJECT_UNUSED)
+ if (o->object.type <= OBJECT_UNUSED) {
+ log_debug("Attempt to move to object with invalid type: %" PRIu64, offset);
return -EBADMSG;
+ }
- if (s < minimum_header_size(o))
+ if (s < minimum_header_size(o)) {
+ log_debug("Attempt to move to truncated object: %" PRIu64, offset);
return -EBADMSG;
+ }
- if (type > OBJECT_UNUSED && o->object.type != type)
+ if (type > OBJECT_UNUSED && o->object.type != type) {
+ log_debug("Attempt to move to object of unexpected type: %" PRIu64, offset);
return -EBADMSG;
+ }
if (s > sizeof(ObjectHeader)) {
r = journal_file_move_to(f, type, false, offset, s, &t);
@@ -1372,6 +1400,12 @@ static int journal_file_append_data(
if (r < 0)
return r;
+#ifdef HAVE_GCRYPT
+ r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p);
+ if (r < 0)
+ return r;
+#endif
+
/* The linking might have altered the window, so let's
* refresh our pointer */
r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
@@ -1396,12 +1430,6 @@ static int journal_file_append_data(
fo->field.head_data_offset = le64toh(p);
}
-#ifdef HAVE_GCRYPT
- r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p);
- if (r < 0)
- return r;
-#endif
-
if (ret)
*ret = o;
@@ -2470,6 +2498,37 @@ int journal_file_compare_locations(JournalFile *af, JournalFile *bf) {
return 0;
}
+static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) {
+
+ /* Increase or decrease the specified index, in the right direction. */
+
+ if (direction == DIRECTION_DOWN) {
+ if (*i >= n - 1)
+ return 0;
+
+ (*i) ++;
+ } else {
+ if (*i <= 0)
+ return 0;
+
+ (*i) --;
+ }
+
+ return 1;
+}
+
+static bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) {
+
+ /* Consider it an error if any of the two offsets is uninitialized */
+ if (old_offset == 0 || new_offset == 0)
+ return false;
+
+ /* If we go down, the new offset must be larger than the old one. */
+ return direction == DIRECTION_DOWN ?
+ new_offset > old_offset :
+ new_offset < old_offset;
+}
+
int journal_file_next_entry(
JournalFile *f,
uint64_t p,
@@ -2500,36 +2559,34 @@ int journal_file_next_entry(
if (r <= 0)
return r;
- if (direction == DIRECTION_DOWN) {
- if (i >= n - 1)
- return 0;
-
- i++;
- } else {
- if (i <= 0)
- return 0;
-
- i--;
- }
+ r = bump_array_index(&i, direction, n);
+ if (r <= 0)
+ return r;
}
/* And jump to it */
- r = generic_array_get(f,
- le64toh(f->header->entry_array_offset),
- i,
- ret, &ofs);
- if (r == -EBADMSG && direction == DIRECTION_DOWN) {
- /* Special case: when we iterate throught the journal file linearly, and hit an entry we can't read,
- * consider this the end of the journal file. */
- log_debug_errno(r, "Encountered entry we can't read while iterating through journal file. Considering this the end of the file.");
- return 0;
+ for (;;) {
+ r = generic_array_get(f,
+ le64toh(f->header->entry_array_offset),
+ i,
+ ret, &ofs);
+ if (r > 0)
+ break;
+ if (r != -EBADMSG)
+ return r;
+
+ /* OK, so this entry is borked. Most likely some entry didn't get synced to disk properly, let's see if
+ * the next one might work for us instead. */
+ log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i);
+
+ r = bump_array_index(&i, direction, n);
+ if (r <= 0)
+ return r;
}
- if (r <= 0)
- return r;
- if (p > 0 &&
- (direction == DIRECTION_DOWN ? ofs <= p : ofs >= p)) {
- log_debug("%s: entry array corrupted at entry %" PRIu64, f->path, i);
+ /* Ensure our array is properly ordered. */
+ if (p > 0 && !check_properly_ordered(ofs, p, direction)) {
+ log_debug("%s: entry array not properly ordered at entry %" PRIu64, f->path, i);
return -EBADMSG;
}
@@ -2546,9 +2603,9 @@ int journal_file_next_entry_for_data(
direction_t direction,
Object **ret, uint64_t *offset) {
- uint64_t n, i;
- int r;
+ uint64_t i, n, ofs;
Object *d;
+ int r;
assert(f);
assert(p > 0 || !o);
@@ -2580,25 +2637,39 @@ int journal_file_next_entry_for_data(
if (r <= 0)
return r;
- if (direction == DIRECTION_DOWN) {
- if (i >= n - 1)
- return 0;
+ r = bump_array_index(&i, direction, n);
+ if (r <= 0)
+ return r;
+ }
- i++;
- } else {
- if (i <= 0)
- return 0;
+ for (;;) {
+ r = generic_array_get_plus_one(f,
+ le64toh(d->data.entry_offset),
+ le64toh(d->data.entry_array_offset),
+ i,
+ ret, &ofs);
+ if (r > 0)
+ break;
+ if (r != -EBADMSG)
+ return r;
- i--;
- }
+ log_debug_errno(r, "Data entry item %" PRIu64 " is bad, skipping over it.", i);
+
+ r = bump_array_index(&i, direction, n);
+ if (r <= 0)
+ return r;
+ }
+ /* Ensure our array is properly ordered. */
+ if (p > 0 && check_properly_ordered(ofs, p, direction)) {
+ log_debug("%s data entry array not properly ordered at entry %" PRIu64, f->path, i);
+ return -EBADMSG;
}
- return generic_array_get_plus_one(f,
- le64toh(d->data.entry_offset),
- le64toh(d->data.entry_array_offset),
- i,
- ret, offset);
+ if (offset)
+ *offset = ofs;
+
+ return 1;
}
int journal_file_move_to_entry_by_offset_for_data(
@@ -3269,7 +3340,8 @@ int journal_file_open_reliably(
-EBUSY, /* unclean shutdown */
-ESHUTDOWN, /* already archived */
-EIO, /* IO error, including SIGBUS on mmap */
- -EIDRM /* File has been deleted */))
+ -EIDRM, /* File has been deleted */
+ -ETXTBSY)) /* File is from the future */
return r;
if ((flags & O_ACCMODE) == O_RDONLY)
diff --git a/src/libsystemd/src/sd-journal/journal-vacuum.c b/src/libsystemd/src/sd-journal/journal-vacuum.c
index 4bbe3ee800..e5d49f0b5d 100644
--- a/src/libsystemd/src/sd-journal/journal-vacuum.c
+++ b/src/libsystemd/src/sd-journal/journal-vacuum.c
@@ -344,7 +344,7 @@ finish:
free(list[i].filename);
free(list);
- log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals on disk.", format_bytes(sbytes, sizeof(sbytes), freed));
+ log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals from %s.", format_bytes(sbytes, sizeof(sbytes), freed), directory);
return r;
}
diff --git a/src/libsystemd/src/sd-journal/journal-verify.c b/src/libsystemd/src/sd-journal/journal-verify.c
index de75cc94ef..756dbdaa76 100644
--- a/src/libsystemd/src/sd-journal/journal-verify.c
+++ b/src/libsystemd/src/sd-journal/journal-verify.c
@@ -119,6 +119,11 @@ static void flush_progress(void) {
log_error(OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \
} while (0)
+#define error_errno(_offset, error, _fmt, ...) do { \
+ flush_progress(); \
+ log_error_errno(error, OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \
+ } while (0)
+
static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) {
uint64_t i;
@@ -169,8 +174,8 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o
le64toh(o->object.size) - offsetof(Object, data.payload),
&b, &alloc, &b_size, 0);
if (r < 0) {
- error(offset, "%s decompression failed: %s",
- object_compressed_to_string(compression), strerror(-r));
+ error_errno(offset, r, "%s decompression failed: %m",
+ object_compressed_to_string(compression));
return r;
}
@@ -827,7 +832,7 @@ int journal_file_verify(
int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
unsigned i;
bool found_last = false;
- _cleanup_free_ char *tmp_dir = NULL;
+ const char *tmp_dir = NULL;
#ifdef HAVE_GCRYPT
uint64_t last_tag = 0;
@@ -847,7 +852,7 @@ int journal_file_verify(
} else if (f->seal)
return -ENOKEY;
- r = var_tmp(&tmp_dir);
+ r = var_tmp_dir(&tmp_dir);
if (r < 0) {
log_error_errno(r, "Failed to determine temporary directory: %m");
goto fail;
@@ -913,7 +918,7 @@ int journal_file_verify(
r = journal_file_object_verify(f, p, o);
if (r < 0) {
- error(p, "Invalid object contents: %s", strerror(-r));
+ error_errno(p, r, "Invalid object contents: %m");
goto fail;
}
diff --git a/src/libsystemd/src/sd-journal/lookup3.c b/src/libsystemd/src/sd-journal/lookup3.c
index 3d791234f4..d8f1a4977d 100644
--- a/src/libsystemd/src/sd-journal/lookup3.c
+++ b/src/libsystemd/src/sd-journal/lookup3.c
@@ -317,7 +317,7 @@ uint32_t jenkins_hashlittle( const void *key, size_t length, uint32_t initval)
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
@@ -503,7 +503,7 @@ void jenkins_hashlittle2(
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
@@ -681,7 +681,7 @@ uint32_t jenkins_hashbig( const void *key, size_t length, uint32_t initval)
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#if !defined(VALGRIND) && !defined(__SANITIZE_ADDRESS__)
switch(length)
{
diff --git a/src/libsystemd/src/sd-journal/mmap-cache.c b/src/libsystemd/src/sd-journal/mmap-cache.c
index 2fdb445f3f..3570aa1d44 100644
--- a/src/libsystemd/src/sd-journal/mmap-cache.c
+++ b/src/libsystemd/src/sd-journal/mmap-cache.c
@@ -326,10 +326,8 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) {
f->fd = fd;
r = hashmap_put(m->fds, FD_TO_PTR(fd), f);
- if (r < 0) {
- free(f);
- return NULL;
- }
+ if (r < 0)
+ return mfree(f);
return f;
}
diff --git a/src/libsystemd/src/sd-journal/sd-journal.c b/src/libsystemd/src/sd-journal/sd-journal.c
index 58307e1626..68ef58b79b 100644
--- a/src/libsystemd/src/sd-journal/sd-journal.c
+++ b/src/libsystemd/src/sd-journal/sd-journal.c
@@ -389,7 +389,7 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) {
}
static char *match_make_string(Match *m) {
- char *p, *r;
+ char *p = NULL, *r;
Match *i;
bool enclose = false;
@@ -399,15 +399,12 @@ static char *match_make_string(Match *m) {
if (m->type == MATCH_DISCRETE)
return strndup(m->data, m->size);
- p = NULL;
LIST_FOREACH(matches, i, m->matches) {
char *t, *k;
t = match_make_string(i);
- if (!t) {
- free(p);
- return NULL;
- }
+ if (!t)
+ return mfree(p);
if (p) {
k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t, NULL);
@@ -1721,9 +1718,16 @@ static sd_journal *journal_new(int flags, const char *path) {
j->data_threshold = DEFAULT_DATA_THRESHOLD;
if (path) {
- j->path = strdup(path);
- if (!j->path)
+ char *t;
+
+ t = strdup(path);
+ if (!t)
goto fail;
+
+ if (flags & SD_JOURNAL_OS_ROOT)
+ j->prefix = t;
+ else
+ j->path = t;
}
j->files = ordered_hashmap_new(&string_hash_ops);
@@ -1739,12 +1743,17 @@ fail:
return NULL;
}
+#define OPEN_ALLOWED_FLAGS \
+ (SD_JOURNAL_LOCAL_ONLY | \
+ SD_JOURNAL_RUNTIME_ONLY | \
+ SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)
+
_public_ int sd_journal_open(sd_journal **ret, int flags) {
sd_journal *j;
int r;
assert_return(ret, -EINVAL);
- assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_RUNTIME_ONLY|SD_JOURNAL_SYSTEM|SD_JOURNAL_CURRENT_USER)) == 0, -EINVAL);
+ assert_return((flags & ~OPEN_ALLOWED_FLAGS) == 0, -EINVAL);
j = journal_new(flags, NULL);
if (!j)
@@ -1763,6 +1772,9 @@ fail:
return r;
}
+#define OPEN_CONTAINER_ALLOWED_FLAGS \
+ (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM)
+
_public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) {
_cleanup_free_ char *root = NULL, *class = NULL;
sd_journal *j;
@@ -1774,7 +1786,7 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
assert_return(machine, -EINVAL);
assert_return(ret, -EINVAL);
- assert_return((flags & ~(SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM)) == 0, -EINVAL);
+ assert_return((flags & ~OPEN_CONTAINER_ALLOWED_FLAGS) == 0, -EINVAL);
assert_return(machine_name_is_valid(machine), -EINVAL);
p = strjoina("/run/systemd/machines/", machine);
@@ -1789,13 +1801,10 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
if (!streq_ptr(class, "container"))
return -EIO;
- j = journal_new(flags, NULL);
+ j = journal_new(flags, root);
if (!j)
return -ENOMEM;
- j->prefix = root;
- root = NULL;
-
r = add_search_paths(j);
if (r < 0)
goto fail;
@@ -1808,13 +1817,17 @@ fail:
return r;
}
+#define OPEN_DIRECTORY_ALLOWED_FLAGS \
+ (SD_JOURNAL_OS_ROOT | \
+ SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
+
_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) {
sd_journal *j;
int r;
assert_return(ret, -EINVAL);
assert_return(path, -EINVAL);
- assert_return((flags & ~SD_JOURNAL_OS_ROOT) == 0, -EINVAL);
+ assert_return((flags & ~OPEN_DIRECTORY_ALLOWED_FLAGS) == 0, -EINVAL);
j = journal_new(flags, path);
if (!j)
@@ -1863,6 +1876,10 @@ fail:
return r;
}
+#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \
+ (SD_JOURNAL_OS_ROOT | \
+ SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER )
+
_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
sd_journal *j;
struct stat st;
@@ -1870,7 +1887,7 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
assert_return(ret, -EINVAL);
assert_return(fd >= 0, -EBADF);
- assert_return((flags & ~SD_JOURNAL_OS_ROOT) == 0, -EINVAL);
+ assert_return((flags & ~OPEN_DIRECTORY_FD_ALLOWED_FLAGS) == 0, -EINVAL);
if (fstat(fd, &st) < 0)
return -errno;
@@ -2292,6 +2309,8 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
* inotify */
if (j->no_new_files)
r = add_current_paths(j);
+ else if (j->flags & SD_JOURNAL_OS_ROOT)
+ r = add_search_paths(j);
else if (j->toplevel_fd >= 0)
r = add_root_directory(j, NULL, false);
else if (j->path)
diff --git a/src/libsystemd/src/sd-netlink/netlink-types.c b/src/libsystemd/src/sd-netlink/netlink-types.c
index c3f3789fe5..fb881846a5 100644
--- a/src/libsystemd/src/sd-netlink/netlink-types.c
+++ b/src/libsystemd/src/sd-netlink/netlink-types.c
@@ -22,6 +22,7 @@
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <linux/can/netlink.h>
#include <linux/in6.h>
#include <linux/veth.h>
#include <linux/if_bridge.h>
@@ -305,49 +306,48 @@ static const char* const nl_union_link_info_data_table[] = {
[NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = "vti6",
[NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl",
[NL_UNION_LINK_INFO_DATA_VRF] = "vrf",
+ [NL_UNION_LINK_INFO_DATA_VCAN] = "vcan",
};
DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
- [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types),
- .types = rtnl_link_info_data_bond_types },
- [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types),
- .types = rtnl_link_info_data_bridge_types },
- [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types),
- .types = rtnl_link_info_data_vlan_types },
- [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types),
- .types = rtnl_link_info_data_veth_types },
- [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
- .types = rtnl_link_info_data_macvlan_types },
- [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
- .types = rtnl_link_info_data_macvlan_types },
- [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
- .types = rtnl_link_info_data_ipvlan_types },
- [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types),
- .types = rtnl_link_info_data_vxlan_types },
- [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
- .types = rtnl_link_info_data_iptun_types },
- [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
- .types = rtnl_link_info_data_ipgre_types },
+ [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types),
+ .types = rtnl_link_info_data_bond_types },
+ [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types),
+ .types = rtnl_link_info_data_bridge_types },
+ [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types),
+ .types = rtnl_link_info_data_vlan_types },
+ [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types),
+ .types = rtnl_link_info_data_veth_types },
+ [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
+ .types = rtnl_link_info_data_macvlan_types },
+ [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types),
+ .types = rtnl_link_info_data_macvlan_types },
+ [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
+ .types = rtnl_link_info_data_ipvlan_types },
+ [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types),
+ .types = rtnl_link_info_data_vxlan_types },
+ [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
+ .types = rtnl_link_info_data_iptun_types },
+ [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
+ .types = rtnl_link_info_data_ipgre_types },
[NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
- .types = rtnl_link_info_data_ipgre_types },
- [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
- .types = rtnl_link_info_data_ipgre_types },
- [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
- .types = rtnl_link_info_data_ipgre_types },
- [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
- .types = rtnl_link_info_data_iptun_types },
- [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
- .types = rtnl_link_info_data_ipvti_types },
- [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
- .types = rtnl_link_info_data_ipvti_types },
- [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types),
- .types = rtnl_link_info_data_ip6tnl_types },
-
- [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types),
- .types = rtnl_link_info_data_vrf_types },
-
+ .types = rtnl_link_info_data_ipgre_types },
+ [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
+ .types = rtnl_link_info_data_ipgre_types },
+ [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types),
+ .types = rtnl_link_info_data_ipgre_types },
+ [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
+ .types = rtnl_link_info_data_iptun_types },
+ [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
+ .types = rtnl_link_info_data_ipvti_types },
+ [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types),
+ .types = rtnl_link_info_data_ipvti_types },
+ [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types),
+ .types = rtnl_link_info_data_ip6tnl_types },
+ [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types),
+ .types = rtnl_link_info_data_vrf_types },
};
static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
diff --git a/src/libsystemd/src/sd-netlink/netlink-types.h b/src/libsystemd/src/sd-netlink/netlink-types.h
index 3cd57715c3..df4ddcaf92 100644
--- a/src/libsystemd/src/sd-netlink/netlink-types.h
+++ b/src/libsystemd/src/sd-netlink/netlink-types.h
@@ -87,6 +87,7 @@ typedef enum NLUnionLinkInfoData {
NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL,
NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL,
NL_UNION_LINK_INFO_DATA_VRF,
+ NL_UNION_LINK_INFO_DATA_VCAN,
_NL_UNION_LINK_INFO_DATA_MAX,
_NL_UNION_LINK_INFO_DATA_INVALID = -1
} NLUnionLinkInfoData;
diff --git a/src/libsystemd/src/test.mk b/src/libsystemd/src/test.mk
index 1a5917121e..a4d107ba6b 100644
--- a/src/libsystemd/src/test.mk
+++ b/src/libsystemd/src/test.mk
@@ -54,6 +54,15 @@ test_bus_cleanup_CFLAGS = \
test_bus_cleanup_LDADD = \
libsystemd-shared.la
+test_bus_track_SOURCES = \
+ src/libsystemd/sd-bus/test-bus-track.c
+
+test_bus_track_CFLAGS = \
+ $(SECCOMP_CFLAGS)
+
+test_bus_track_LDADD = \
+ libsystemd-shared.la
+
test_bus_server_SOURCES = \
src/libsystemd/sd-bus/test-bus-server.c