chiark / gitweb /
core: convert PID 1 to libsystemd-bus
authorLennart Poettering <lennart@poettering.net>
Tue, 19 Nov 2013 20:12:59 +0000 (21:12 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 20 Nov 2013 19:52:36 +0000 (20:52 +0100)
This patch converts PID 1 to libsystemd-bus and thus drops the
dependency on libdbus. The only remaining code using libdbus is a test
case that validates our bus marshalling against libdbus' marshalling,
and this dependency can be turned off.

This patch also adds a couple of things to libsystem-bus, that are
necessary to make the port work:

- Synthesizing of "Disconnected" messages when bus connections are
  severed.

- Support for attaching multiple vtables for the same interface on the
  same path.

This patch also fixes the SetDefaultTarget() and GetDefaultTarget() bus
calls which used an inappropriate signature.

As a side effect we will now generate PropertiesChanged messages which
carry property contents, rather than just invalidation information.

106 files changed:
Makefile.am
TODO
src/core/automount.c
src/core/automount.h
src/core/dbus-automount.c
src/core/dbus-automount.h
src/core/dbus-cgroup.c
src/core/dbus-cgroup.h
src/core/dbus-client-track.c [new file with mode: 0644]
src/core/dbus-client-track.h [new file with mode: 0644]
src/core/dbus-device.c
src/core/dbus-device.h
src/core/dbus-execute.c
src/core/dbus-execute.h
src/core/dbus-job.c
src/core/dbus-job.h
src/core/dbus-kill.c
src/core/dbus-kill.h
src/core/dbus-manager.c
src/core/dbus-manager.h
src/core/dbus-mount.c
src/core/dbus-mount.h
src/core/dbus-path.c
src/core/dbus-path.h
src/core/dbus-scope.c
src/core/dbus-scope.h
src/core/dbus-service.c
src/core/dbus-service.h
src/core/dbus-slice.c
src/core/dbus-slice.h
src/core/dbus-snapshot.c
src/core/dbus-snapshot.h
src/core/dbus-socket.c
src/core/dbus-socket.h
src/core/dbus-swap.c
src/core/dbus-swap.h
src/core/dbus-target.c
src/core/dbus-target.h
src/core/dbus-timer.c
src/core/dbus-timer.h
src/core/dbus-unit.c
src/core/dbus-unit.h
src/core/dbus.c
src/core/dbus.h
src/core/device.c
src/core/device.h
src/core/job.c
src/core/job.h
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/main.c
src/core/manager.c
src/core/manager.h
src/core/mount.c
src/core/mount.h
src/core/path.c
src/core/path.h
src/core/scope.c
src/core/scope.h
src/core/selinux-access.c
src/core/selinux-access.h
src/core/service.c
src/core/service.h
src/core/slice.c
src/core/snapshot.c
src/core/snapshot.h
src/core/socket.c
src/core/socket.h
src/core/swap.c
src/core/swap.h
src/core/target.c
src/core/timer.c
src/core/timer.h
src/core/transaction.c
src/core/transaction.h
src/core/unit.c
src/core/unit.h
src/libsystemd-bus/bus-error.h
src/libsystemd-bus/bus-internal.h
src/libsystemd-bus/bus-introspect.c
src/libsystemd-bus/bus-introspect.h
src/libsystemd-bus/bus-message.c
src/libsystemd-bus/bus-objects.c
src/libsystemd-bus/bus-signature.c
src/libsystemd-bus/bus-util.c
src/libsystemd-bus/bus-util.h
src/libsystemd-bus/sd-bus.c
src/libsystemd-bus/sd-event.c
src/libsystemd-bus/test-bus-introspect.c
src/libsystemd-bus/test-bus-marshal.c
src/login/logind-dbus.c
src/login/logind-inhibit.c
src/login/logind-seat-dbus.c
src/login/logind-session-dbus.c
src/login/logind-session.c
src/login/logind.c
src/machine/machined-dbus.c
src/shared/bus-errors.h [new file with mode: 0644]
src/shared/dbus-common.c [deleted file]
src/shared/dbus-common.h [deleted file]
src/shared/install.c
src/shared/install.h
src/shared/prioq.c
src/systemctl/systemctl.c
src/systemd/sd-bus.h
src/systemd/sd-event.h

index 82e46a98b5f94ec83ee03ccb1f91c1423c3dfff6..f7fe96c35c71b0ac12c498ec38f0aac0269e8ff4 100644 (file)
@@ -662,16 +662,19 @@ libsystemd_shared_la_SOURCES = \
        src/shared/linux/fanotify.h \
        src/shared/linux/seccomp.h \
        src/shared/linux/seccomp-bpf.h \
+       src/shared/ioprio.h \
        src/shared/missing.h \
        src/shared/list.h \
        src/shared/macro.h \
        src/shared/def.h \
+       src/shared/sparse-endian.h \
+       src/shared/refcnt.h \
+       src/shared/udev-util.h \
+       src/shared/bus-errors.h \
        src/shared/device-nodes.c \
        src/shared/device-nodes.h \
-       src/shared/sparse-endian.h \
        src/shared/util.c \
        src/shared/util.h \
-       src/shared/udev-util.h \
        src/shared/virt.c \
        src/shared/virt.h \
        src/shared/efivars.c \
@@ -712,7 +715,6 @@ libsystemd_shared_la_SOURCES = \
        src/shared/gunicode.h \
        src/shared/pager.c \
        src/shared/pager.h \
-       src/shared/ioprio.h \
        src/shared/socket-util.c \
        src/shared/socket-util.h \
        src/shared/conf-files.c \
@@ -748,7 +750,6 @@ libsystemd_shared_la_SOURCES = \
        src/shared/acpi-fpdt.c \
        src/shared/boot-timestamps.h \
        src/shared/boot-timestamps.c \
-       src/shared/refcnt.h \
        src/shared/mkdir.c \
        src/shared/mkdir.h \
        src/shared/smack-util.c \
@@ -762,21 +763,6 @@ libsystemd_shared_la_SOURCES = \
        src/shared/net-util.c \
        src/shared/net-util.h
 
-#-------------------------------------------------------------------------------
-noinst_LTLIBRARIES += \
-       libsystemd-dbus.la
-
-libsystemd_dbus_la_SOURCES = \
-       src/shared/dbus-common.c \
-       src/shared/dbus-common.h
-
-libsystemd_dbus_la_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
-libsystemd_dbus_la_LIBADD = \
-       $(DBUS_LIBS)
-
 # ------------------------------------------------------------------------------
 noinst_LTLIBRARIES += \
        libsystemd-units.la
@@ -792,8 +778,7 @@ libsystemd_units_la_SOURCES = \
        src/shared/specifier.h
 
 libsystemd_units_la_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
+       $(AM_CFLAGS)
 
 # ------------------------------------------------------------------------------
 noinst_LTLIBRARIES += \
@@ -953,6 +938,8 @@ libsystemd_core_la_SOURCES = \
        src/core/dbus-kill.h \
        src/core/dbus-cgroup.c \
        src/core/dbus-cgroup.h \
+       src/core/dbus-client-track.c \
+       src/core/dbus-client-track.h \
        src/core/cgroup.c \
        src/core/cgroup.h \
        src/core/selinux-access.c \
@@ -982,7 +969,6 @@ libsystemd_core_la_SOURCES = \
        src/core/securebits.h \
        src/core/initreq.h \
        src/core/special.h \
-       src/core/bus-errors.h \
        src/core/build.h \
        src/core/sysfs-show.h \
        src/core/switch-root.h \
@@ -1010,7 +996,6 @@ nodist_libsystemd_core_la_SOURCES = \
 
 libsystemd_core_la_CFLAGS = \
        $(AM_CFLAGS) \
-       $(DBUS_CFLAGS) \
        $(LIBWRAP_CFLAGS) \
        $(PAM_CFLAGS) \
        $(AUDIT_CFLAGS) \
@@ -1021,13 +1006,13 @@ libsystemd_core_la_LIBADD = \
        libsystemd-capability.la \
        libsystemd-units.la \
        libsystemd-label.la \
-       libsystemd-dbus.la \
        libsystemd-audit.la \
        libsystemd-id128-internal.la \
        libsystemd-daemon-internal.la \
        libudev-internal.la \
        libsystemd-shared.la \
        libsystemd-rtnl.la \
+       libsystemd-bus-internal.la \
        $(LIBWRAP_LIBS) \
        $(PAM_LIBS) \
        $(AUDIT_LIBS) \
@@ -1072,10 +1057,6 @@ src/core/syscall-to-name.h: src/core/syscall-list.txt Makefile
 systemd_SOURCES = \
        src/core/main.c
 
-systemd_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
 systemd_LDADD = \
        libsystemd-core.la \
        $(RT_LIBS)
@@ -1166,10 +1147,6 @@ test_device_nodes_LDADD = \
 test_engine_SOURCES = \
        src/test/test-engine.c
 
-test_engine_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
 test_engine_LDADD = \
        libsystemd-core.la \
        $(RT_LIBS)
@@ -1177,10 +1154,6 @@ test_engine_LDADD = \
 test_job_type_SOURCES = \
        src/test/test-job-type.c
 
-test_job_type_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
 test_job_type_LDADD = \
        libsystemd-core.la \
        $(RT_LIBS)
@@ -1191,10 +1164,6 @@ test_ns_SOURCES = \
 test_ns_LDADD = \
        libsystemd-core.la
 
-test_ns_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
 test_loopback_SOURCES = \
        src/test/test-loopback.c
 
@@ -1221,10 +1190,6 @@ endif
 test_unit_name_SOURCES = \
        src/test/test-unit-name.c
 
-test_unit_name_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
 test_unit_name_LDADD = \
        libsystemd-core.la \
        $(RT_LIBS)
@@ -1232,10 +1197,6 @@ test_unit_name_LDADD = \
 test_unit_file_SOURCES = \
        src/test/test-unit-file.c
 
-test_unit_file_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
 test_unit_file_LDADD = \
        libsystemd-core.la \
        $(RT_LIBS)
@@ -1274,10 +1235,6 @@ test_tables_SOURCES = \
        src/test/test-tables.c \
        src/shared/test-tables.h
 
-test_tables_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
 test_tables_LDADD = \
        libsystemd-logs.la \
        libsystemd-journal-internal.la \
@@ -1401,10 +1358,6 @@ test_strxcpyx_LDADD = \
 test_install_SOURCES = \
        src/test/test-install.c
 
-test_install_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
-
 test_install_LDADD = \
        libsystemd-units.la \
        libsystemd-label.la \
@@ -1422,7 +1375,6 @@ test_sched_prio_SOURCES = \
 
 test_sched_prio_CFLAGS = \
        $(AM_CFLAGS) \
-       $(DBUS_CFLAGS) \
        -D"STR(s)=\#s" -D"TEST_DIR=STR($(abs_top_srcdir)/test/)"
 
 test_sched_prio_LDADD = \
@@ -2800,9 +2752,6 @@ mtd_probe_SOURCES =  \
        src/udev/mtd_probe/mtd_probe.h \
        src/udev/mtd_probe/probe_smartmedia.c
 
-mtd_probe_CPPFLAGS = \
-       $(AM_CPPFLAGS)
-
 dist_udevrules_DATA += \
        rules/75-probe_mtd.rules
 
@@ -3893,7 +3842,6 @@ systemd_logind_LDADD = \
 
 libsystemd_logind_core_la_SOURCES = \
        src/login/logind-core.c \
-       src/login/logind-dbus.c \
        src/login/logind-device.c \
        src/login/logind-device.h \
        src/login/logind-button.c \
@@ -3910,6 +3858,7 @@ libsystemd_logind_core_la_SOURCES = \
        src/login/logind-user.h \
        src/login/logind-inhibit.c \
        src/login/logind-inhibit.h \
+       src/login/logind-dbus.c \
        src/login/logind-session-dbus.c \
        src/login/logind-seat-dbus.c \
        src/login/logind-user-dbus.c \
diff --git a/TODO b/TODO
index efc7e2a1eb7d1859cdb9c31302f6962f26ccbf16..e3874863ad44218f84f0cdb5d54b2d3f1a939680 100644 (file)
--- a/TODO
+++ b/TODO
@@ -43,6 +43,53 @@ CGroup Rework Completion:
 
 Features:
 
+* sd-event: allow multiple signal handlers per signal
+
+* timer: expose accuracy as unit setting
+
+* sd-event: do per-minute coalescing of timer events too
+
+* when we detect low battery and no AC on boot, show pretty splash and refuse boot
+
+* move libasyncns into systemd as libsystemd-asyncns
+
+* calendarspec: support value ranges with ".." notation. Example: 2013-4..8-1
+
+* pid1 porting:
+  - restore selinux access control on properties
+
+* sd-bus: when triggering property change events, allow a NULL strv indicate that all properties listed as such are send out as changed
+
+* sd-bus: enforce signatures on response messages
+
+* sd-bus: make message handlers take an sd_bus_error and generate error replies automatically if they are set
+
+* sd-bus: when replying to a bus message we should not need to specify the bus again
+
+* sd-bus: see if we can drop more message validation on the sending side
+
+* sd-bus: introduce sd_bus_creds object and attach it to messages as well as allow querying it for names
+
+* sd-bus: support "const" properties as flag
+
+* sd-bus: add api call to escape bus path components
+
+* sd-event: when a handler returns an error, just turn off its event
+  source, but do not return anything up to the event loop
+  caller. Instead add parameter to sd_event_request_quit() to take
+  retval. This way errors rippling upwards are the option, not the
+  default
+
+* sd-event: child pid handling: first invoke waitid(WNOHANG) and call event handler, only afterwards reap the process
+
+* sd-event: native support for watchdog stuff
+
+* machined, localed: when we try to kill an empty cgroup, generate an ESRCH call over the bus
+
+* sd-bus: SD_BUS_COMMENT() macro for inclusion in vtables, syntax inspired by gdbus
+
+* libsystemd-journal, libsystemd-login, libudev: add calls to easily attach these objects to sd-event event loops
+
 * be more careful what we export on the bus as (usec_t) 0 and (usec_t) -1
 
 * check :no-sender logic after PID 1 conversion
index d1379e091376a5ce11ee1a4d6466c0c5f75b6f45..49a64b124f63260cd55c9703639891a602c247ab 100644 (file)
 #include "load-fragment.h"
 #include "load-dropin.h"
 #include "unit-name.h"
-#include "dbus-automount.h"
-#include "bus-errors.h"
 #include "special.h"
 #include "label.h"
 #include "mkdir.h"
 #include "path-util.h"
-#include "dbus-common.h"
+#include "dbus-automount.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
         [AUTOMOUNT_DEAD] = UNIT_INACTIVE,
@@ -51,6 +51,7 @@ static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = {
 };
 
 static int open_dev_autofs(Manager *m);
+static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata);
 
 static void automount_init(Unit *u) {
         Automount *a = AUTOMOUNT(u);
@@ -58,11 +59,8 @@ static void automount_init(Unit *u) {
         assert(u);
         assert(u->load_state == UNIT_STUB);
 
-        a->pipe_watch.fd = a->pipe_fd = -1;
-        a->pipe_watch.type = WATCH_INVALID;
-
+        a->pipe_fd = -1;
         a->directory_mode = 0755;
-
         UNIT(a)->ignore_on_isolate = true;
 }
 
@@ -91,7 +89,8 @@ static void unmount_autofs(Automount *a) {
 
         automount_send_ready(a, -EHOSTDOWN);
 
-        unit_unwatch_fd(UNIT(a), &a->pipe_watch);
+        a->pipe_event_source = sd_event_source_unref(a->pipe_event_source);
+
         close_nointr_nofail(a->pipe_fd);
         a->pipe_fd = -1;
 
@@ -257,7 +256,7 @@ static int automount_coldplug(Unit *u) {
 
                         assert(a->pipe_fd >= 0);
 
-                        r = unit_watch_fd(UNIT(a), a->pipe_fd, EPOLLIN, &a->pipe_watch);
+                        r = sd_event_add_io(u->manager->event, a->pipe_fd, EPOLLIN, automount_dispatch_io, u, &a->pipe_event_source);
                         if (r < 0)
                                 return r;
                 }
@@ -532,7 +531,7 @@ static void automount_enter_waiting(Automount *a) {
         close_nointr_nofail(ioctl_fd);
         ioctl_fd = -1;
 
-        r = unit_watch_fd(UNIT(a), p[0], EPOLLIN, &a->pipe_watch);
+        r = sd_event_add_io(UNIT(a)->manager->event, p[0], EPOLLIN, automount_dispatch_io, a, &a->pipe_event_source);
         if (r < 0)
                 goto fail;
 
@@ -558,14 +557,12 @@ fail:
 }
 
 static void automount_enter_runnning(Automount *a) {
-        _cleanup_dbus_error_free_ DBusError error;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         struct stat st;
         int r;
 
         assert(a);
 
-        dbus_error_init(&error);
-
         /* We don't take mount requests anymore if we are supposed to
          * shut down anyway */
         if (unit_stop_pending(UNIT(a))) {
@@ -593,7 +590,7 @@ static void automount_enter_runnning(Automount *a) {
                 if (r < 0) {
                         log_warning_unit(UNIT(a)->id,
                                          "%s failed to queue mount startup job: %s",
-                                         UNIT(a)->id, bus_error(&error, r));
+                                         UNIT(a)->id, bus_error_message(&error, r));
                         goto fail;
                 }
         }
@@ -748,9 +745,9 @@ static bool automount_check_gc(Unit *u) {
         return UNIT_VTABLE(UNIT_TRIGGER(u))->check_gc(UNIT_TRIGGER(u));
 }
 
-static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
-        Automount *a = AUTOMOUNT(u);
+static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
         union autofs_v5_packet_union packet;
+        Automount *a = AUTOMOUNT(userdata);
         ssize_t l;
         int r;
 
@@ -758,13 +755,13 @@ static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
         assert(fd == a->pipe_fd);
 
         if (events != EPOLLIN) {
-                log_error_unit(u->id, "Got invalid poll event on pipe.");
+                log_error_unit(UNIT(a)->id, "Got invalid poll event on pipe.");
                 goto fail;
         }
 
         l = loop_read(a->pipe_fd, &packet, sizeof(packet), true);
         if (l != sizeof(packet)) {
-                log_error_unit(u->id, "Invalid read from pipe: %s", l < 0 ? strerror(-l) : "short read");
+                log_error_unit(UNIT(a)->id, "Invalid read from pipe: %s", l < 0 ? strerror(-l) : "short read");
                 goto fail;
         }
 
@@ -776,21 +773,21 @@ static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                         _cleanup_free_ char *p = NULL;
 
                         get_process_comm(packet.v5_packet.pid, &p);
-                        log_debug_unit(u->id,
+                        log_debug_unit(UNIT(a)->id,
                                        "Got direct mount request on %s, triggered by %lu (%s)",
                                        a->where, (unsigned long) packet.v5_packet.pid, strna(p));
                 } else
-                        log_debug_unit(u->id, "Got direct mount request on %s", a->where);
+                        log_debug_unit(UNIT(a)->id, "Got direct mount request on %s", a->where);
 
                 r = set_ensure_allocated(&a->tokens, trivial_hash_func, trivial_compare_func);
                 if (r < 0) {
-                        log_error_unit(u->id, "Failed to allocate token set.");
+                        log_error_unit(UNIT(a)->id, "Failed to allocate token set.");
                         goto fail;
                 }
 
                 r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                 if (r < 0) {
-                        log_error_unit(u->id, "Failed to remember token: %s", strerror(-r));
+                        log_error_unit(UNIT(a)->id, "Failed to remember token: %s", strerror(-r));
                         goto fail;
                 }
 
@@ -798,14 +795,15 @@ static void automount_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                 break;
 
         default:
-                log_error_unit(u->id, "Received unknown automount request %i", packet.hdr.type);
+                log_error_unit(UNIT(a)->id, "Received unknown automount request %i", packet.hdr.type);
                 break;
         }
 
-        return;
+        return 0;
 
 fail:
         automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
+        return 0;
 }
 
 static void automount_shutdown(Manager *m) {
@@ -844,6 +842,7 @@ DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
 
 const UnitVTable automount_vtable = {
         .object_size = sizeof(Automount),
+
         .sections =
                 "Unit\0"
                 "Automount\0"
@@ -871,13 +870,11 @@ const UnitVTable automount_vtable = {
 
         .check_gc = automount_check_gc,
 
-        .fd_event = automount_fd_event,
-
         .reset_failed = automount_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Automount",
-        .bus_message_handler = bus_automount_message_handler,
-        .bus_invalidating_properties = bus_automount_invalidating_properties,
+        .bus_vtable = bus_automount_vtable,
+        .bus_changing_properties = bus_automount_changing_properties,
 
         .shutdown = automount_shutdown,
 
index a7a25d34e0aaf1750012682779ccec37455eea6e..60f55223897e94133d7de959fbeb76034507455d 100644 (file)
@@ -49,8 +49,8 @@ struct Automount {
         char *where;
 
         int pipe_fd;
+        sd_event_source *pipe_event_source;
         mode_t directory_mode;
-        Watch pipe_watch;
         dev_t dev_id;
 
         Set *tokens;
index 720f9ba6d12f5a8656c4b9f7a123fd396faa2bd8..420cfaa331dbffd510f21ce0df650414ff6236d0 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "automount.h"
 #include "dbus-unit.h"
 #include "dbus-automount.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_AUTOMOUNT_INTERFACE                                      \
-        " <interface name=\"org.freedesktop.systemd1.Automount\">\n" \
-        "  <property name=\"Where\" type=\"s\" access=\"read\"/>\n"  \
-        "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                    \
-        "<node>\n"                                                   \
-        BUS_UNIT_INTERFACE                                           \
-        BUS_AUTOMOUNT_INTERFACE                                      \
-        BUS_PROPERTIES_INTERFACE                                     \
-        BUS_PEER_INTERFACE                                           \
-        BUS_INTROSPECTABLE_INTERFACE                                 \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Automount\0"
-
-const char bus_automount_interface[] = BUS_AUTOMOUNT_INTERFACE;
+#include "bus-util.h"
 
-const char bus_automount_invalidating_properties[] =
-        "Result\0";
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, automount_result, AutomountResult);
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_automount_append_automount_result, automount_result, AutomountResult);
-
-static const BusProperty bus_automount_properties[] = {
-        { "Where",         bus_property_append_string, "s", offsetof(Automount, where),    true },
-        { "DirectoryMode", bus_property_append_mode,   "u", offsetof(Automount, directory_mode) },
-        { "Result",        bus_automount_append_automount_result, "s", offsetof(Automount, result) },
-        { NULL, }
+const sd_bus_vtable bus_automount_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Automount, where), 0),
+        SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Automount, directory_mode), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Automount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Automount *am = AUTOMOUNT(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",      bus_unit_properties,      u  },
-                { "org.freedesktop.systemd1.Automount", bus_automount_properties, am },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_automount_changing_properties[] = {
+        "Result",
+        NULL
+};
index b338e25fc12c92c96f877c04f40e16d2aa2f294c..0b9618368ed152c46166aa157f2348b7d1a25088 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
 
-#include "unit.h"
-
-DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_automount_interface[];
-extern const char bus_automount_invalidating_properties[];
+extern const sd_bus_vtable bus_automount_vtable[];
+extern const char* const bus_automount_changing_properties[];
index f198357637579a5fc9820e352d01afd80555f1a0..4dbb83a76912fec0e419277a4b7487396a3c5146 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "bus-util.h"
 #include "path-util.h"
+#include "cgroup-util.h"
+#include "cgroup.h"
 #include "dbus-cgroup.h"
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_cgroup_append_device_policy, cgroup_device_policy, CGroupDevicePolicy);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
+
+static int property_get_blockio_device_weight(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-static int bus_cgroup_append_device_weights(DBusMessageIter *i, const char *property, void *data) {
-        DBusMessageIter sub, sub2;
-        CGroupContext *c = data;
+        CGroupContext *c = userdata;
         CGroupBlockIODeviceWeight *w;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(st)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(st)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
-
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &w->path) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &w->weight) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_cgroup_append_device_bandwidths(DBusMessageIter *i, const char *property, void *data) {
-        DBusMessageIter sub, sub2;
-        CGroupContext *c = data;
+static int property_get_blockio_device_bandwidths(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        CGroupContext *c = userdata;
         CGroupBlockIODeviceBandwidth *b;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(st)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(st)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
 
                 if (streq(property, "BlockIOReadBandwidth") != b->read)
                         continue;
 
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &b->path) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &b->bandwidth) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(st)", b->path, b->bandwidth);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_cgroup_append_device_allow(DBusMessageIter *i, const char *property, void *data) {
-        DBusMessageIter sub, sub2;
-        CGroupContext *c = data;
+static int property_get_device_allow(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        CGroupContext *c = userdata;
         CGroupDeviceAllow *a;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(device_allow, a, c->device_allow) {
-                const char *rwm;
-                char buf[4];
                 unsigned k = 0;
+                char rwm[4];
 
                 if (a->r)
-                        buf[k++] = 'r';
+                        rwm[k++] = 'r';
                 if (a->w)
-                        buf[k++] = 'w';
+                        rwm[k++] = 'w';
                 if (a->m)
-                        buf[k++] = 'm';
+                        rwm[k++] = 'm';
 
-                buf[k] = 0;
-                rwm = buf;
+                rwm[k] = 0;
 
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->path) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &rwm) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-const BusProperty bus_cgroup_context_properties[] = {
-        { "CPUAccounting",           bus_property_append_bool,            "b",     offsetof(CGroupContext, cpu_accounting)     },
-        { "CPUShares",               bus_property_append_ul,              "t",     offsetof(CGroupContext, cpu_shares)         },
-        { "BlockIOAccounting",       bus_property_append_bool,            "b",     offsetof(CGroupContext, blockio_accounting) },
-        { "BlockIOWeight",           bus_property_append_ul,              "t",     offsetof(CGroupContext, blockio_weight)     },
-        { "BlockIODeviceWeight",     bus_cgroup_append_device_weights,    "a(st)", 0                                           },
-        { "BlockIOReadBandwidth",    bus_cgroup_append_device_bandwidths, "a(st)", 0                                           },
-        { "BlockIOWriteBandwidth",   bus_cgroup_append_device_bandwidths, "a(st)", 0                                           },
-        { "MemoryAccounting",        bus_property_append_bool,            "b",     offsetof(CGroupContext, memory_accounting)  },
-        { "MemoryLimit",             bus_property_append_uint64,          "t",     offsetof(CGroupContext, memory_limit)       },
-        { "DevicePolicy",            bus_cgroup_append_device_policy,     "s",     offsetof(CGroupContext, device_policy)      },
-        { "DeviceAllow",             bus_cgroup_append_device_allow,      "a(ss)", 0                                           },
-        {}
+const sd_bus_vtable bus_cgroup_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
+        SD_BUS_PROPERTY("CPUShares", "t", bus_property_get_ulong, offsetof(CGroupContext, cpu_shares), 0),
+        SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
+        SD_BUS_PROPERTY("BlockIOWeight", "t", bus_property_get_ulong, offsetof(CGroupContext, blockio_weight), 0),
+        SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
+        SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
+        SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
+        SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
+        SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
+        SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
+        SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
+        SD_BUS_VTABLE_END
 };
 
 int bus_cgroup_set_property(
                 Unit *u,
                 CGroupContext *c,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
+
+        int r;
 
-        assert(name);
         assert(u);
         assert(c);
-        assert(i);
+        assert(name);
+        assert(message);
 
         if (streq(name, "CPUAccounting")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-                        dbus_message_iter_get_basic(i, &b);
-
                         c->cpu_accounting = b;
                         unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
                 }
@@ -170,14 +182,13 @@ int bus_cgroup_set_property(
                 uint64_t u64;
                 unsigned long ul;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "t", &u64);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_get_basic(i, &u64);
                 ul = (unsigned long) u64;
-
-                if (u64 <= 0 || u64 != (uint64_t) ul)
-                        return -EINVAL;
+                if (ul <= 0 || (uint64_t) ul != u64)
+                        return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
 
                 if (mode != UNIT_CHECK) {
                         c->cpu_shares = ul;
@@ -187,14 +198,13 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "BlockIOAccounting")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-                        dbus_message_iter_get_basic(i, &b);
-
                         c->blockio_accounting = b;
                         unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
                 }
@@ -205,14 +215,13 @@ int bus_cgroup_set_property(
                 uint64_t u64;
                 unsigned long ul;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "t", &u64);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_get_basic(i, &u64);
                 ul = (unsigned long) u64;
-
-                if (u64 < 10 || u64 > 1000)
-                        return -EINVAL;
+                if (ul < 10 || ul > 1000)
+                        return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
 
                 if (mode != UNIT_CHECK) {
                         c->blockio_weight = ul;
@@ -222,42 +231,31 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) {
-                DBusMessageIter sub;
-                unsigned n = 0;
+                const char *path;
                 bool read = true;
+                unsigned n = 0;
+                uint64_t u64;
 
                 if (streq(name, "BlockIOWriteBandwidth"))
                         read = false;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
-                         return -EINVAL;
-
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
-                        DBusMessageIter sub2;
-                        const char *path;
-                        uint64_t u64;
+                r = sd_bus_message_enter_container(message, 'a', "(st)");
+                if (r < 0)
+                        return r;
 
-                        dbus_message_iter_recurse(&sub, &sub2);
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
-                            bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &u64, false) < 0)
-                                return -EINVAL;
+                while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
 
                         if (mode != UNIT_CHECK) {
-                                CGroupBlockIODeviceBandwidth *a = NULL;
-                                CGroupBlockIODeviceBandwidth *b;
-                                bool exist = false;
+                                CGroupBlockIODeviceBandwidth *a = NULL, *b;
 
                                 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
                                         if (path_equal(path, b->path) && read == b->read) {
                                                 a = b;
-                                                exist = true;
                                                 break;
                                         }
                                 }
 
-                                if (!exist) {
+                                if (!a) {
                                         a = new0(CGroupBlockIODeviceBandwidth, 1);
                                         if (!a)
                                                 return -ENOMEM;
@@ -268,23 +266,22 @@ int bus_cgroup_set_property(
                                                 free(a);
                                                 return -ENOMEM;
                                         }
+
+                                        LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
                                 }
 
                                 a->bandwidth = u64;
-
-                                if (!exist)
-                                        LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
                         }
 
                         n++;
-                        dbus_message_iter_next(&sub);
                 }
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
+                        CGroupBlockIODeviceBandwidth *a, *next;
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
-                        CGroupBlockIODeviceBandwidth *a;
-                        CGroupBlockIODeviceBandwidth *next;
                         size_t size = 0;
 
                         if (n == 0) {
@@ -316,44 +313,32 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "BlockIODeviceWeight")) {
-                DBusMessageIter sub;
+                const char *path;
+                uint64_t u64;
                 unsigned n = 0;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
-                        return -EINVAL;
+                r = sd_bus_message_enter_container(message, 'a', "(st)");
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
-                        DBusMessageIter sub2;
-                        const char *path;
-                        uint64_t u64;
+                while (( r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
                         unsigned long ul;
 
-                        dbus_message_iter_recurse(&sub, &sub2);
-
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
-                            bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &u64, false) < 0)
-                                return -EINVAL;
-
                         ul = (unsigned long) u64;
                         if (ul < 10 || ul > 1000)
-                                return -EINVAL;
+                                return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
 
                         if (mode != UNIT_CHECK) {
-                                CGroupBlockIODeviceWeight *a = NULL;
-                                CGroupBlockIODeviceWeight *b;
-                                bool exist = false;
+                                CGroupBlockIODeviceWeight *a = NULL, *b;
 
                                 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
                                         if (path_equal(b->path, path)) {
                                                 a = b;
-                                                exist = true;
                                                 break;
                                         }
                                 }
 
-                                if (!exist) {
+                                if (!a) {
                                         a = new0(CGroupBlockIODeviceWeight, 1);
                                         if (!a)
                                                 return -ENOMEM;
@@ -363,16 +348,13 @@ int bus_cgroup_set_property(
                                                 free(a);
                                                 return -ENOMEM;
                                         }
+                                        LIST_PREPEND(device_weights,c->blockio_device_weights, a);
                                 }
 
                                 a->weight = ul;
-
-                                if (!exist)
-                                        LIST_PREPEND(device_weights,c->blockio_device_weights, a);
                         }
 
                         n++;
-                        dbus_message_iter_next(&sub);
                 }
 
                 if (mode != UNIT_CHECK) {
@@ -401,14 +383,13 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "MemoryAccounting")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-                        dbus_message_iter_get_basic(i, &b);
-
                         c->memory_accounting = b;
                         unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
                 }
@@ -416,14 +397,13 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "MemoryLimit")) {
+                uint64_t limit;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "t", &limit);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        uint64_t limit;
-                        dbus_message_iter_get_basic(i, &limit);
-
                         c->memory_limit = limit;
                         unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit);
                 }
@@ -434,10 +414,10 @@ int bus_cgroup_set_property(
                 const char *policy;
                 CGroupDevicePolicy p;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "s", &policy);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_get_basic(i, &policy);
                 p = cgroup_device_policy_from_string(policy);
                 if (p < 0)
                         return -EINVAL;
@@ -454,51 +434,35 @@ int bus_cgroup_set_property(
                 return 1;
 
         } else if (streq(name, "DeviceAllow")) {
-                DBusMessageIter sub;
+                const char *path, *rwm;
                 unsigned n = 0;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
-                        return -EINVAL;
-
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
-                        DBusMessageIter sub2;
-                        const char *path, *rwm;
+                r = sd_bus_message_enter_container(message, 'a', "(ss)");
+                if (r < 0)
+                        return r;
 
-                        dbus_message_iter_recurse(&sub, &sub2);
+                while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
 
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
-                            bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) < 0)
-                                return -EINVAL;
-
-                        if (!path_startswith(path, "/dev")) {
-                                dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node");
-                                return -EINVAL;
-                        }
+                        if (!path_startswith(path, "/dev"))
+                                return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
 
                         if (isempty(rwm))
                                 rwm = "rwm";
 
-                        if (!in_charset(rwm, "rwm")) {
-                                dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
-                                return -EINVAL;
-                        }
+                        if (!in_charset(rwm, "rwm"))
+                                return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
 
                         if (mode != UNIT_CHECK) {
-                                CGroupDeviceAllow *a = NULL;
-                                CGroupDeviceAllow *b;
-                                bool exist = false;
+                                CGroupDeviceAllow *a = NULL, *b;
 
                                 LIST_FOREACH(device_allow, b, c->device_allow) {
                                         if (path_equal(b->path, path)) {
                                                 a = b;
-                                                exist = true;
                                                 break;
                                         }
                                 }
 
-                                if (!exist) {
+                                if (!a) {
                                         a = new0(CGroupDeviceAllow, 1);
                                         if (!a)
                                                 return -ENOMEM;
@@ -508,18 +472,17 @@ int bus_cgroup_set_property(
                                                 free(a);
                                                 return -ENOMEM;
                                         }
+
+                                        LIST_PREPEND(device_allow, c->device_allow, a);
                                 }
 
                                 a->r = !!strchr(rwm, 'r');
                                 a->w = !!strchr(rwm, 'w');
                                 a->m = !!strchr(rwm, 'm');
 
-                                if (!exist)
-                                        LIST_PREPEND(device_allow, c->device_allow, a);
                         }
 
                         n++;
-                        dbus_message_iter_next(&sub);
                 }
 
                 if (mode != UNIT_CHECK) {
index e5ac4c3af788b64b9767cb063a3eb3082fc1c0ea..c2a3910f3d6466ccf13ffaf56ba58fe3b9a4eb7f 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
-#include "manager.h"
-#include "dbus-common.h"
+#include "sd-bus.h"
 #include "cgroup.h"
 
-#define BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"CPUAccounting\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"CPUShares\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIOAccounting\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIOWeight\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIODeviceWeight\" type=\"a(st)\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIOReadBandwidth=\" type=\"a(st)\" access=\"read\"/>\n" \
-        "  <property name=\"BlockIOWriteBandwidth=\" type=\"a(st)\" access=\"read\"/>\n" \
-        "  <property name=\"MemoryAccounting\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"MemoryLimit\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"DevicePolicy\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"DeviceAllow\" type=\"a(ss)\" access=\"read\"/>\n"
-
-extern const BusProperty bus_cgroup_context_properties[];
-
-int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+extern const sd_bus_vtable bus_cgroup_vtable[];
+
+int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
diff --git a/src/core/dbus-client-track.c b/src/core/dbus-client-track.c
new file mode 100644 (file)
index 0000000..ce514b5
--- /dev/null
@@ -0,0 +1,250 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 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 "dbus-client-track.h"
+
+static unsigned tracked_client_hash(const void *a) {
+        const BusTrackedClient *x = a;
+
+        return string_hash_func(x->name) ^ PTR_TO_UINT(x->bus);
+}
+
+static int tracked_client_compare(const void *a, const void *b) {
+        const BusTrackedClient *x = a, *y = b;
+        int r;
+
+        r = strcmp(x->name, y->name);
+        if (r != 0)
+                return r;
+
+        if (x->bus < y->bus)
+                return -1;
+        if (x->bus > y->bus)
+                return 1;
+
+        return 0;
+}
+
+static int on_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        BusTrackedClient *c = userdata;
+        const char *name, *old, *new;
+        int r;
+
+        assert(bus);
+        assert(message);
+
+        r = sd_bus_message_read(message, "sss", &name, &old, &new);
+        if (r < 0) {
+                log_debug("Failed to parse NameOwnerChanged message.");
+                return 0;
+        }
+
+        bus_client_untrack(c->set, bus, name);
+        return 0;
+}
+
+static char *build_match(const char *name) {
+
+        return strjoin("type='signal',"
+                       "sender='org.freedesktop.DBus',"
+                       "path='/org/freedesktop/DBus',"
+                       "interface='org.freedesktop.DBus',"
+                       "member='NameOwnerChanged',"
+                       "arg0='", name, "'", NULL);
+}
+
+int bus_client_track(Set **s, sd_bus *bus, const char *name) {
+        BusTrackedClient *c, *found;
+        size_t l;
+        int r;
+
+        assert(s);
+        assert(bus);
+
+        r = set_ensure_allocated(s, tracked_client_hash, tracked_client_compare);
+        if (r < 0)
+                return r;
+
+        name = strempty(name);
+
+        l = strlen(name);
+
+        c = alloca(offsetof(BusTrackedClient, name) + l + 1);
+        c->set = *s;
+        c->bus = bus;
+        strcpy(c->name, name);
+
+        found = set_get(*s, c);
+        if (found)
+                return 0;
+
+        c = memdup(c, offsetof(BusTrackedClient, name) + l + 1);
+        if (!c)
+                return -ENOMEM;
+
+        r = set_put(*s, c);
+        if (r < 0) {
+                free(c);
+                return r;
+        }
+
+        if (!isempty(name)) {
+                _cleanup_free_ char *match = NULL;
+
+                match = build_match(name);
+                if (!match) {
+                        set_remove(*s, c);
+                        free(c);
+                        return -ENOMEM;
+                }
+
+                r = sd_bus_add_match(bus, match, on_name_owner_changed, c);
+                if (r < 0) {
+                        set_remove(*s, c);
+                        free(c);
+                        return r;
+                }
+        }
+
+        sd_bus_ref(c->bus);
+        return 1;
+}
+
+static void bus_client_free_one(Set *s, BusTrackedClient *c) {
+        assert(s);
+        assert(c);
+
+        if (!isempty(c->name)) {
+                _cleanup_free_ char *match = NULL;
+
+                match = build_match(c->name);
+                if (match)
+                        sd_bus_remove_match(c->bus, match, on_name_owner_changed, c);
+        }
+
+        sd_bus_unref(c->bus);
+        set_remove(s, c);
+        free(c);
+}
+
+int bus_client_untrack(Set *s, sd_bus *bus, const char *name) {
+        BusTrackedClient *c, *found;
+        size_t l;
+
+        assert(bus);
+        assert(s);
+        assert(name);
+
+        name = strempty(name);
+
+        l = strlen(name);
+
+        c = alloca(offsetof(BusTrackedClient, name) + l + 1);
+        c->bus = bus;
+        strcpy(c->name, name);
+
+        found = set_get(s, c);
+        if (!found)
+                return 0;
+
+        bus_client_free_one(s, found);
+        return 1;
+}
+
+void bus_client_track_free(Set *s) {
+        BusTrackedClient *c;
+
+        while ((c = set_first(s)))
+                bus_client_free_one(s, c);
+
+        set_free(s);
+}
+
+int bus_client_untrack_bus(Set *s, sd_bus *bus) {
+        BusTrackedClient *c;
+        Iterator i;
+        int r = 0;
+
+        SET_FOREACH(c, s, i)
+                if (c->bus == bus) {
+                        bus_client_free_one(s, c);
+                        r++;
+                }
+
+        return r;
+}
+
+void bus_client_track_serialize(Manager *m, FILE *f, Set *s) {
+        BusTrackedClient *c;
+        Iterator i;
+
+        assert(m);
+        assert(f);
+
+        SET_FOREACH(c, s, i) {
+                if (c->bus == m->api_bus)
+                        fprintf(f, "subscribed=%s", isempty(c->name) ? "*" : c->name);
+                else
+                        fprintf(f, "subscribed=%p %s", c->bus, isempty(c->name) ? "*" : c->name);
+        }
+}
+
+int bus_client_track_deserialize_item(Manager *m, Set **s, const char *line) {
+        const char *e, *q, *name;
+        sd_bus *bus;
+        void *p;
+        int r;
+
+        e = startswith(line, "subscribed=");
+        if (!e)
+                return 0;
+
+        q = strpbrk(e, WHITESPACE);
+        if (!q) {
+                if (m->api_bus) {
+                        bus = m->api_bus;
+                        name = e;
+                        goto finish;
+                }
+
+                return 1;
+        }
+
+        if (sscanf(e, "%p", &p) != 1) {
+                log_debug("Failed to parse subscription pointer.");
+                return -EINVAL;
+        }
+
+        bus = set_get(m->private_buses, p);
+        if (!bus)
+                return 1;
+
+        name = q + strspn(q, WHITESPACE);
+
+finish:
+        r = bus_client_track(s, bus, streq(name, "*") ? NULL : name);
+        if (r < 0) {
+                log_debug("Failed to deserialize client subscription: %s", strerror(-r));
+                return r;
+        }
+
+        return 1;
+}
diff --git a/src/core/dbus-client-track.h b/src/core/dbus-client-track.h
new file mode 100644 (file)
index 0000000..0167647
--- /dev/null
@@ -0,0 +1,42 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 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 "sd-bus.h"
+#include "set.h"
+#include "manager.h"
+
+typedef struct BusTrackedClient {
+        Set *set;
+        sd_bus *bus;
+        char name[0];
+} BusTrackedClient;
+
+int bus_client_track(Set **s, sd_bus *bus, const char *name);
+
+int bus_client_untrack(Set *s, sd_bus *bus, const char *name);
+int bus_client_untrack_bus(Set *s, sd_bus *bus);
+
+void bus_client_track_free(Set *s);
+
+void bus_client_track_serialize(Manager *m, FILE *f, Set *s);
+int bus_client_track_deserialize_item(Manager *m, Set **s, const char *line);
index ef484a86b7be16ed065b83ee440647ec01e087ff..621bab0426d2ffbf36693bc7734ab9dbfc25f205 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include "unit.h"
+#include "device.h"
 #include "dbus-unit.h"
 #include "dbus-device.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 
-#define BUS_DEVICE_INTERFACE                                            \
-        " <interface name=\"org.freedesktop.systemd1.Device\">\n"       \
-        "  <property name=\"SysFSPath\" type=\"s\" access=\"read\"/>\n" \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_DEVICE_INTERFACE                                            \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Device\0"
-
-const char bus_device_interface[] = BUS_DEVICE_INTERFACE;
-
-const char bus_device_invalidating_properties[] =
-        "SysFSPath\0";
-
-static const BusProperty bus_device_properties[] = {
-        { "SysFSPath", bus_property_append_string, "s", offsetof(Device, sysfs), true },
-        { NULL, }
+const sd_bus_vtable bus_device_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("SysFSPath", "s", NULL, offsetof(Device, sysfs), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-
-DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Device *d = DEVICE(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",   bus_unit_properties,   u },
-                { "org.freedesktop.systemd1.Device", bus_device_properties, d },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_device_changing_properties[] = {
+        "SysFSPath",
+        NULL
+};
index 311e0685d17e2f2099d0ae2f44ae581cc35ab64c..f248c28db354c33340ff284c0b16fbae5fd1130e 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_device_interface[];
-extern const char bus_device_invalidating_properties[];
+extern const sd_bus_vtable bus_device_vtable[];
+extern const char* const bus_device_changing_properties[];
index 2402e8c34d58018b53ba364946abf5c05b5970c5..ca7ee5c10be4e1aba33012cca9c5a7cfb6b5e637 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-#include <dbus/dbus.h>
 #include <sys/prctl.h>
 
-#include "dbus-execute.h"
+#include "bus-util.h"
 #include "missing.h"
 #include "ioprio.h"
 #include "strv.h"
-#include "dbus-common.h"
 #include "syscall-list.h"
 #include "fileio.h"
+#include "execute.h"
+#include "dbus-execute.h"
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
+BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
 
-static int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
-        char **env_files = data, **j;
-        DBusMessageIter sub, sub2;
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
 
-        assert(i);
-        assert(property);
+static int property_get_environment_files(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sb)", &sub))
-                return -ENOMEM;
+        ExecContext *c = userdata;
+        char **j;
+        int r;
 
-        STRV_FOREACH(j, env_files) {
-                dbus_bool_t b = false;
-                char *fn = *j;
+        assert(bus);
+        assert(reply);
+        assert(c);
+
+        r = sd_bus_message_open_container(reply, 'a', "(sb)");
+        if (r < 0)
+                return r;
 
-                if (fn[0] == '-') {
-                        b = true;
-                        fn++;
-                }
+        STRV_FOREACH(j, c->environment_files) {
+                const char *fn = *j;
 
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &fn) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        return sd_bus_message_close_container(reply);
+}
+
+static int property_get_rlimit(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        struct rlimit *rl;
+        uint64_t u;
+
+        assert(bus);
+        assert(reply);
+        assert(userdata);
 
-        return 0;
+        rl = *(struct rlimit**) userdata;
+        if (rl)
+                u = (uint64_t) rl->rlim_max;
+        else {
+                struct rlimit buf = {};
+                int z;
+
+                z = rlimit_from_string(property);
+                assert(z >= 0);
+
+                getrlimit(z, &buf);
+
+                u = (uint64_t) buf.rlim_max;
+        }
+
+        return sd_bus_message_append(reply, "t", u);
 }
 
-static int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_oom_score_adjust(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->oom_score_adjust_set)
@@ -80,80 +123,111 @@ static int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *p
                 _cleanup_free_ char *t = NULL;
 
                 n = 0;
-                if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
+                if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
                         safe_atoi(t, &n);
-                }
         }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_nice(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->nice_set)
                 n = c->nice;
-        else
+        else {
+                errno = 0;
                 n = getpriority(PRIO_PROCESS, 0);
+                if (errno != 0)
+                        n = 0;
+        }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_ioprio(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->ioprio_set)
                 n = c->ioprio;
-        else
+        else {
                 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
+                if (n < 0)
+                        n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
+        }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_cpu_sched_policy(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->cpu_sched_set)
                 n = c->cpu_sched_policy;
-        else
+        else {
                 n = sched_getscheduler(0);
+                if (n < 0)
+                        n = SCHED_OTHER;
+        }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_cpu_sched_priority(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        ExecContext *c = userdata;
         int32_t n;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->cpu_sched_set)
@@ -167,44 +241,44 @@ static int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char
                         n = 0;
         }
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "i", n);
 }
 
-static int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
-        dbus_bool_t b;
-        DBusMessageIter sub;
+static int property_get_cpu_affinity(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(c);
+        ExecContext *c = userdata;
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(c);
 
         if (c->cpuset)
-                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
+                return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
         else
-                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
-
-        if (!b)
-                return -ENOMEM;
-
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+                return sd_bus_message_append_array(reply, 'y', NULL, 0);
 }
 
-static int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_timer_slack_nsec(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        ExecContext *c = userdata;
         uint64_t u;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->timer_slack_nsec != (nsec_t) -1)
@@ -212,37 +286,45 @@ static int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *p
         else
                 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "t", u);
 }
 
-static int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
-        uint64_t normal, inverted;
+static int property_get_capability_bounding_set(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
+        ExecContext *c = userdata;
+
+        assert(bus);
+        assert(reply);
         assert(c);
 
         /* We store this negated internally, to match the kernel, but
          * we expose it normalized. */
-
-        normal = *(uint64_t*) data;
-        inverted = ~normal;
-
-        return bus_property_append_uint64(i, property, &inverted);
+        return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
 }
 
-static int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
+static int property_get_capabilities(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        ExecContext *c = userdata;
         char *t = NULL;
         const char *s;
-        dbus_bool_t b;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(c);
 
         if (c->capabilities)
@@ -253,184 +335,150 @@ static int bus_execute_append_capabilities(DBusMessageIter *i, const char *prope
         if (!s)
                 return -ENOMEM;
 
-        b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
+        r = sd_bus_message_append(reply, "s", s);
 
         if (t)
                 cap_free(t);
 
-        if (!b)
-                return -ENOMEM;
-
-        return 0;
+        return r;
 }
 
-static int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
-        int r;
-        uint64_t u;
-
-        assert(i);
-        assert(property);
-        assert(c);
-
-        assert_se((r = rlimit_from_string(property)) >= 0);
+static int property_get_syscall_filter(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        if (c->rlimit[r])
-                u = (uint64_t) c->rlimit[r]->rlim_max;
-        else {
-                struct rlimit rl = {};
+        ExecContext *c = userdata;
 
-                getrlimit(r, &rl);
+        assert(bus);
+        assert(reply);
+        assert(c);
 
-                u = (uint64_t) rl.rlim_max;
-        }
+        if (c->syscall_filter)
+                return sd_bus_message_append_array(reply, 'u', c->syscall_filter, (syscall_max() + 31) >> 4);
+        else
+                return sd_bus_message_append_array(reply, 'u', NULL, 0);
+}
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
-                return -ENOMEM;
+const sd_bus_vtable bus_exec_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), 0),
+        SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, 0),
+        SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), 0),
+        SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), 0),
+        SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), 0),
+        SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), 0),
+        SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), 0),
+        SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), 0),
+        SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), 0),
+        SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), 0),
+        SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), 0),
+        SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), 0),
+        SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), 0),
+        SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), 0),
+        SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), 0),
+        SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), 0),
+        SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), 0),
+        SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), 0),
+        SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), 0),
+        SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), 0),
+        SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), 0),
+        SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, 0),
+        SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, 0),
+        SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, 0),
+        SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, 0),
+        SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, 0),
+        SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, 0),
+        SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, 0),
+        SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), 0),
+        SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), 0),
+        SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), 0),
+        SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), 0),
+        SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), 0),
+        SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), 0),
+        SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), 0),
+        SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), 0),
+        SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), 0),
+        SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), 0),
+        SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), 0),
+        SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), 0),
+        SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, 0),
+        SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), 0),
+        SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, 0),
+        SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), 0),
+        SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), 0),
+        SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), 0),
+        SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), 0),
+        SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), 0),
+        SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), 0),
+        SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), 0),
+        SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), 0),
+        SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), 0),
+        SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), 0),
+        SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), 0),
+        SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), 0),
+        SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), 0),
+        SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), 0),
+        SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), 0),
+        SD_BUS_PROPERTY("SystemCallFilter", "au", property_get_syscall_filter, 0, 0),
+        SD_BUS_VTABLE_END
+};
 
-        return 0;
-}
+int bus_property_get_exec_command(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
-        ExecCommand *c = data;
-        DBusMessageIter sub, sub2, sub3;
+        ExecCommand *c = *(ExecCommand**) userdata;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(command, c, c) {
-                char **l;
-                uint32_t pid;
-                int32_t code, status;
-                dbus_bool_t b;
-
                 if (!c->path)
                         continue;
 
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
-                    !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
-                        return -ENOMEM;
-
-                STRV_FOREACH(l, c->argv)
-                        if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
-                                return -ENOMEM;
-
-                pid = (uint32_t) c->exec_status.pid;
-                code = (int32_t) c->exec_status.code;
-                status = (int32_t) c->exec_status.status;
-
-                b = !!c->ignore;
-
-                if (!dbus_message_iter_close_container(&sub2, &sub3) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
-                        return -ENOMEM;
-
-                if (!dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_append(reply, "s", c->path);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_append_strv(reply, c->argv);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_append(reply, "bttttuii",
+                                          c->ignore,
+                                          c->exec_status.start_timestamp.realtime,
+                                          c->exec_status.start_timestamp.monotonic,
+                                          c->exec_status.exit_timestamp.realtime,
+                                          c->exec_status.exit_timestamp.monotonic,
+                                          (uint32_t) c->exec_status.pid,
+                                          (int32_t) c->exec_status.code,
+                                          (int32_t) c->exec_status.status);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_close_container(reply);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
-}
-
-static int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data) {
-        ExecContext *c = data;
-        dbus_bool_t b;
-        DBusMessageIter sub;
-
-        assert(i);
-        assert(property);
-        assert(c);
-
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "u", &sub))
-                return -ENOMEM;
-
-        if (c->syscall_filter)
-                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, (syscall_max() + 31) >> 4);
-        else
-                b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, 0);
-
-        if (!b)
-                return -ENOMEM;
-
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
-
-const BusProperty bus_exec_context_properties[] = {
-        { "Environment",              bus_property_append_strv,             "as", offsetof(ExecContext, environment),            true },
-        { "EnvironmentFiles",         bus_execute_append_env_files,      "a(sb)", offsetof(ExecContext, environment_files),      true },
-        { "UMask",                    bus_property_append_mode,              "u", offsetof(ExecContext, umask)                        },
-        { "LimitCPU",                 bus_execute_append_rlimits,            "t", 0 },
-        { "LimitFSIZE",               bus_execute_append_rlimits,            "t", 0 },
-        { "LimitDATA",                bus_execute_append_rlimits,            "t", 0 },
-        { "LimitSTACK",               bus_execute_append_rlimits,            "t", 0 },
-        { "LimitCORE",                bus_execute_append_rlimits,            "t", 0 },
-        { "LimitRSS",                 bus_execute_append_rlimits,            "t", 0 },
-        { "LimitNOFILE",              bus_execute_append_rlimits,            "t", 0 },
-        { "LimitAS",                  bus_execute_append_rlimits,            "t", 0 },
-        { "LimitNPROC",               bus_execute_append_rlimits,            "t", 0 },
-        { "LimitMEMLOCK",             bus_execute_append_rlimits,            "t", 0 },
-        { "LimitLOCKS",               bus_execute_append_rlimits,            "t", 0 },
-        { "LimitSIGPENDING",          bus_execute_append_rlimits,            "t", 0 },
-        { "LimitMSGQUEUE",            bus_execute_append_rlimits,            "t", 0 },
-        { "LimitNICE",                bus_execute_append_rlimits,            "t", 0 },
-        { "LimitRTPRIO",              bus_execute_append_rlimits,            "t", 0 },
-        { "LimitRTTIME",              bus_execute_append_rlimits,            "t", 0 },
-        { "WorkingDirectory",         bus_property_append_string,            "s", offsetof(ExecContext, working_directory),      true },
-        { "RootDirectory",            bus_property_append_string,            "s", offsetof(ExecContext, root_directory),         true },
-        { "OOMScoreAdjust",           bus_execute_append_oom_score_adjust,   "i", 0 },
-        { "Nice",                     bus_execute_append_nice,               "i", 0 },
-        { "IOScheduling",             bus_execute_append_ioprio,             "i", 0 },
-        { "CPUSchedulingPolicy",      bus_execute_append_cpu_sched_policy,   "i", 0 },
-        { "CPUSchedulingPriority",    bus_execute_append_cpu_sched_priority, "i", 0 },
-        { "CPUAffinity",              bus_execute_append_affinity,          "ay", 0 },
-        { "TimerSlackNSec",           bus_execute_append_timer_slack_nsec,   "t", 0 },
-        { "CPUSchedulingResetOnFork", bus_property_append_bool,              "b", offsetof(ExecContext, cpu_sched_reset_on_fork)      },
-        { "NonBlocking",              bus_property_append_bool,              "b", offsetof(ExecContext, non_blocking)                 },
-        { "StandardInput",            bus_execute_append_input,              "s", offsetof(ExecContext, std_input)                    },
-        { "StandardOutput",           bus_execute_append_output,             "s", offsetof(ExecContext, std_output)                   },
-        { "StandardError",            bus_execute_append_output,             "s", offsetof(ExecContext, std_error)                    },
-        { "TTYPath",                  bus_property_append_string,            "s", offsetof(ExecContext, tty_path),               true },
-        { "TTYReset",                 bus_property_append_bool,              "b", offsetof(ExecContext, tty_reset)                    },
-        { "TTYVHangup",               bus_property_append_bool,              "b", offsetof(ExecContext, tty_vhangup)                  },
-        { "TTYVTDisallocate",         bus_property_append_bool,              "b", offsetof(ExecContext, tty_vt_disallocate)           },
-        { "SyslogPriority",           bus_property_append_int,               "i", offsetof(ExecContext, syslog_priority)              },
-        { "SyslogIdentifier",         bus_property_append_string,            "s", offsetof(ExecContext, syslog_identifier),      true },
-        { "SyslogLevelPrefix",        bus_property_append_bool,              "b", offsetof(ExecContext, syslog_level_prefix)          },
-        { "Capabilities",             bus_execute_append_capabilities,       "s", 0 },
-        { "SecureBits",               bus_property_append_int,               "i", offsetof(ExecContext, secure_bits)                  },
-        { "CapabilityBoundingSet",    bus_execute_append_capability_bs,      "t", offsetof(ExecContext, capability_bounding_set_drop) },
-        { "User",                     bus_property_append_string,            "s", offsetof(ExecContext, user),                   true },
-        { "Group",                    bus_property_append_string,            "s", offsetof(ExecContext, group),                  true },
-        { "SupplementaryGroups",      bus_property_append_strv,             "as", offsetof(ExecContext, supplementary_groups),   true },
-        { "TCPWrapName",              bus_property_append_string,            "s", offsetof(ExecContext, tcpwrap_name),           true },
-        { "PAMName",                  bus_property_append_string,            "s", offsetof(ExecContext, pam_name),               true },
-        { "ReadWriteDirectories",     bus_property_append_strv,             "as", offsetof(ExecContext, read_write_dirs),        true },
-        { "ReadOnlyDirectories",      bus_property_append_strv,             "as", offsetof(ExecContext, read_only_dirs),         true },
-        { "InaccessibleDirectories",  bus_property_append_strv,             "as", offsetof(ExecContext, inaccessible_dirs),      true },
-        { "MountFlags",               bus_property_append_ul,                "t", offsetof(ExecContext, mount_flags)                  },
-        { "PrivateTmp",               bus_property_append_bool,              "b", offsetof(ExecContext, private_tmp)                  },
-        { "PrivateNetwork",           bus_property_append_bool,              "b", offsetof(ExecContext, private_network)              },
-        { "SameProcessGroup",         bus_property_append_bool,              "b", offsetof(ExecContext, same_pgrp)                    },
-        { "UtmpIdentifier",           bus_property_append_string,            "s", offsetof(ExecContext, utmp_id),                true },
-        { "IgnoreSIGPIPE",            bus_property_append_bool,              "b", offsetof(ExecContext, ignore_sigpipe)               },
-        { "NoNewPrivileges",          bus_property_append_bool,              "b", offsetof(ExecContext, no_new_privileges)            },
-        { "SystemCallFilter",         bus_execute_append_syscall_filter,    "au", 0                                                   },
-        {}
-};
index 79bf30838a519886f9783ede7b32d1988be0d9eb..957742beee2ef3f38c92a6781c0461872dcde127 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
+#include "execute.h"
 
-#include "manager.h"
-#include "dbus-common.h"
+#define BUS_EXEC_STATUS_VTABLE(prefix, offset, flags)                   \
+        BUS_PROPERTY_DUAL_TIMESTAMP(prefix "StartTimestamp", (offset) + offsetof(ExecStatus, start_timestamp), flags), \
+        BUS_PROPERTY_DUAL_TIMESTAMP(prefix "ExitTimestamp", (offset) + offsetof(ExecStatus, exit_timestamp), flags), \
+        SD_BUS_PROPERTY(prefix "PID", "u", bus_property_get_pid, (offset) + offsetof(ExecStatus, pid), flags), \
+        SD_BUS_PROPERTY(prefix "Code", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, code), flags), \
+        SD_BUS_PROPERTY(prefix "Status", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, status), flags)
 
-#define BUS_EXEC_STATUS_INTERFACE(prefix)                               \
-        "  <property name=\"" prefix "StartTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "StartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "ExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "ExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "PID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "Code\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"" prefix "Status\" type=\"i\" access=\"read\"/>\n"
+#define BUS_EXEC_COMMAND_VTABLE(name, offset, flags)                    \
+        SD_BUS_PROPERTY(name, "a(sasbttttuii)", bus_property_get_exec_command, offset, flags)
 
-#define BUS_EXEC_CONTEXT_INTERFACE                                      \
-        "  <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"EnvironmentFiles\" type=\"a(sb)\" access=\"read\"/>\n" \
-        "  <property name=\"UMask\" type=\"u\" access=\"read\"/>\n"     \
-        "  <property name=\"LimitCPU\" type=\"t\" access=\"read\"/>\n"  \
-        "  <property name=\"LimitFSIZE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitDATA\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitSTACK\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitCORE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitRSS\" type=\"t\" access=\"read\"/>\n"  \
-        "  <property name=\"LimitNOFILE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitAS\" type=\"t\" access=\"read\"/>\n"   \
-        "  <property name=\"LimitNPROC\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitMEMLOCK\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitLOCKS\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitSIGPENDING\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitMSGQUEUE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitNICE\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitRTPRIO\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LimitRTTIME\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"WorkingDirectory\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"RootDirectory\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"OOMScoreAdjust\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"Nice\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"IOScheduling\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"CPUSchedulingPolicy\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"CPUSchedulingPriority\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"CPUAffinity\" type=\"ay\" access=\"read\"/>\n" \
-        "  <property name=\"TimerSlackNSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"CPUSchedulingResetOnFork\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"NonBlocking\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"StandardInput\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"StandardOutput\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"StandardError\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"TTYPath\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"TTYReset\" type=\"b\" access=\"read\"/>\n"   \
-        "  <property name=\"TTYVHangup\" type=\"b\" access=\"read\"/>\n"   \
-        "  <property name=\"TTYVTDisallocate\" type=\"b\" access=\"read\"/>\n"   \
-        "  <property name=\"SyslogPriority\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"SyslogIdentifier\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SyslogLevelPrefix\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Capabilities\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SecureBits\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"CapabilityBoundingSet\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"User\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Group\" type=\"s\" access=\"read\"/>\n"     \
-        "  <property name=\"SupplementaryGroups\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"TCPWrapName\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"PAMName\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"ReadWriteDirectories\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ReadOnlyDirectories\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"InaccessibleDirectories\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"MountFlags\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"PrivateTmp\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"PrivateNetwork\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"SameProcessGroup\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"UtmpIdentifier\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"IgnoreSIGPIPE\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"NoNewPrivileges\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"SystemCallFilter\" type=\"au\" access=\"read\"/>\n"
+extern const sd_bus_vtable bus_exec_vtable[];
 
-#define BUS_EXEC_COMMAND_INTERFACE(name)                             \
-        "  <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
-
-extern const BusProperty bus_exec_context_properties[];
-
-#define BUS_EXEC_COMMAND_PROPERTY(name, command, indirect)             \
-        { name, bus_execute_append_command, "a(sasbttttuii)", (command), (indirect), NULL }
-
-int bus_execute_append_command(DBusMessageIter *u, const char *property, void *data);
+int bus_property_get_exec_output(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
index e1d7504e85464f6dd25dccd7128124869f0cc517..e774383793b932bcddbce857867bb44d9263adba 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
-#include "dbus.h"
 #include "log.h"
-#include "dbus-job.h"
-#include "dbus-common.h"
+#include "sd-bus.h"
 #include "selinux-access.h"
+#include "job.h"
+#include "dbus-job.h"
+#include "dbus-client-track.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState);
+
+static int property_get_unit(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-#define BUS_JOB_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Job\">\n"        \
-        "  <method name=\"Cancel\"/>\n"                               \
-        "  <property name=\"Id\" type=\"u\" access=\"read\"/>\n"      \
-        "  <property name=\"Unit\" type=\"(so)\" access=\"read\"/>\n" \
-        "  <property name=\"JobType\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"State\" type=\"s\" access=\"read\"/>\n"   \
-        " </interface>\n"
-
-#define INTROSPECTION                                                 \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                     \
-        "<node>\n"                                                    \
-        BUS_JOB_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                      \
-        BUS_PEER_INTERFACE                                            \
-        BUS_INTROSPECTABLE_INTERFACE                                  \
-        "</node>\n"
-
-const char bus_job_interface[] = BUS_JOB_INTERFACE;
-
-#define INTERFACES_LIST                              \
-        BUS_GENERIC_INTERFACES_LIST                  \
-        "org.freedesktop.systemd1.Job\0"
-
-#define INVALIDATING_PROPERTIES                 \
-        "State\0"
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_state, job_state, JobState);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_job_append_type, job_type, JobType);
-
-static int bus_job_append_unit(DBusMessageIter *i, const char *property, void *data) {
-        Job *j = data;
-        DBusMessageIter sub;
         _cleanup_free_ char *p = NULL;
+        Job *j = userdata;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(j);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
-                return -ENOMEM;
-
         p = unit_dbus_path(j->unit);
         if (!p)
                 return -ENOMEM;
 
-        if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &j->unit->id) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
-                return -ENOMEM;
-        }
-
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "(so)", j->unit->id, p);
 }
 
-static const BusProperty bus_job_properties[] = {
-        { "Id",      bus_property_append_uint32, "u", offsetof(Job, id)    },
-        { "State",   bus_job_append_state,       "s", offsetof(Job, state) },
-        { "JobType", bus_job_append_type,        "s", offsetof(Job, type)  },
-        { "Unit",    bus_job_append_unit,     "(so)", 0 },
-        { NULL, }
-};
-
-static DBusHandlerResult bus_job_message_dispatch(Job *j, DBusConnection *connection, DBusMessage *message) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-
-        if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Job", "Cancel")) {
-
-                SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
-                job_finish_and_invalidate(j, JOB_CANCELED, true);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        return DBUS_HANDLER_RESULT_NEED_MEMORY;
-        } else {
-                const BusBoundProperties bps[] = {
-                        { "org.freedesktop.systemd1.Job", bus_job_properties, j },
-                        { NULL, }
-                };
-
-                SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
-                return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
-        }
-
-        if (!bus_maybe_send_reply(connection, message, reply))
-                return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
-        return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBusMessage  *message, void *data) {
-        Manager *m = data;
-        Job *j;
-        int r;
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+static int method_cancel(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Job *j = userdata;
 
-        assert(connection);
+        assert(bus);
         assert(message);
-        assert(m);
-
-        if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/job")) {
-                /* Be nice to gdbus and return introspection data for our mid-level paths */
-
-                if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
-                        _cleanup_free_ char *introspection = NULL;
-                        FILE *f;
-                        Iterator i;
-                        size_t size;
-
-                        SELINUX_ACCESS_CHECK(connection, message, "status");
-
-                        reply = dbus_message_new_method_return(message);
-                        if (!reply)
-                                goto oom;
-
-                        /* We roll our own introspection code here, instead of
-                         * relying on bus_default_message_handler() because we
-                         * need to generate our introspection string
-                         * dynamically. */
-
-                        f = open_memstream(&introspection, &size);
-                        if (!f)
-                                goto oom;
-
-                        fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
-                              "<node>\n", f);
-
-                        fputs(BUS_INTROSPECTABLE_INTERFACE, f);
-                        fputs(BUS_PEER_INTERFACE, f);
-
-                        HASHMAP_FOREACH(j, m->jobs, i)
-                                fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
-
-                        fputs("</node>\n", f);
-
-                        if (ferror(f)) {
-                                fclose(f);
-                                goto oom;
-                        }
-
-                        fclose(f);
-
-                        if (!introspection)
-                                goto oom;
-
-                        if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
-                                goto oom;
-                        }
-
-                        if (!bus_maybe_send_reply(connection, message, reply))
-                                goto oom;
-
-                        return DBUS_HANDLER_RESULT_HANDLED;
-                }
-
-                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-        }
-
-        r = manager_get_job_from_dbus_path(m, dbus_message_get_path(message), &j);
-        if (r == -ENOMEM)
-                goto oom;
-        if (r == -ENOENT) {
-                DBusError e;
-
-                dbus_error_init(&e);
-                dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown job");
-                return bus_send_error_reply(connection, message, &e, r);
-        }
-        if (r < 0)
-                return bus_send_error_reply(connection, message, NULL, r);
+        assert(j);
 
-        return bus_job_message_dispatch(j, connection, message);
+        SELINUX_UNIT_ACCESS_CHECK(j->unit, bus, message, "stop");
+        job_finish_and_invalidate(j, JOB_CANCELED, true);
 
-oom:
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        return sd_bus_reply_method_return(bus, message, NULL);
 }
 
-const DBusObjectPathVTable bus_job_vtable = {
-        .message_function = bus_job_message_handler
+const sd_bus_vtable bus_job_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_METHOD("Cancel", NULL, NULL, method_cancel, 0),
+        SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), 0),
+        SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, 0),
+        SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), 0),
+        SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-static int job_send_message(Job *j, DBusMessage* (*new_message)(Job *j)) {
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
+static int foreach_client(Job *j, int (*send_message)(sd_bus *bus, const char *name, Job *j)) {
+        BusTrackedClient *one_destination = NULL;
+        Iterator i;
+        sd_bus *b;
+        unsigned n, m;
         int r;
 
         assert(j);
-        assert(new_message);
+        assert(send_message);
 
-        if (bus_has_subscriber(j->manager) || j->forgot_bus_clients) {
-                m = new_message(j);
-                if (!m)
-                        return -ENOMEM;
+        n = set_size(j->manager->subscribed);
+        m = set_size(j->subscribed);
 
-                r = bus_broadcast(j->manager, m);
-                if (r < 0)
-                        return r;
-
-        } else {
-                /* If nobody is subscribed, we just send the message
-                 * to the client(s) which created the job */
-                JobBusClient *cl;
-                assert(j->bus_client_list);
-
-                LIST_FOREACH(client, cl, j->bus_client_list) {
-                        assert(cl->bus);
+        if (n <= 0 && m <= 0)
+                return 0;
 
-                        m = new_message(j);
-                        if (!m)
-                                return -ENOMEM;
+        if (n == 1 && m == 0)
+                one_destination = set_first(j->manager->subscribed);
+        else if (n == 0 && m == 1)
+                one_destination = set_first(j->subscribed);
+        else
+                one_destination = NULL;
 
-                        if (!dbus_message_set_destination(m, cl->name))
-                                return -ENOMEM;
+        if (one_destination)
+                return send_message(one_destination->bus, isempty(one_destination->name) ? NULL : one_destination->name, j);
 
-                        if (!dbus_connection_send(cl->bus, m, NULL))
-                                return -ENOMEM;
-
-                        dbus_message_unref(m);
-                        m = NULL;
-                }
+        /* Send to everybody */
+        SET_FOREACH(b, j->manager->private_buses, i) {
+                r = send_message(b, NULL, j);
+                if (r < 0)
+                        return r;
         }
 
+        if (j->manager->api_bus)
+                return send_message(j->manager->api_bus, NULL, j);
+
         return 0;
 }
 
-static DBusMessage* new_change_signal_message(Job *j) {
+static int send_new_signal(sd_bus *bus, const char *destination, Job *j) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
         _cleanup_free_ char *p = NULL;
-        DBusMessage *m;
+        int r;
+
+        assert(bus);
+        assert(j);
 
         p = job_dbus_path(j);
         if (!p)
-                return NULL;
-
-        if (j->sent_dbus_new_signal) {
-                /* Send a properties changed signal */
-                m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Job", INVALIDATING_PROPERTIES);
-                if (!m)
-                        return NULL;
-
-        } else {
-                /* Send a new signal */
-
-                m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobNew");
-                if (!m)
-                        return NULL;
-
-                if (!dbus_message_append_args(m,
-                                              DBUS_TYPE_UINT32, &j->id,
-                                              DBUS_TYPE_OBJECT_PATH, &p,
-                                              DBUS_TYPE_STRING, &j->unit->id,
-                                              DBUS_TYPE_INVALID)) {
-                        dbus_message_unref(m);
-                        return NULL;
-                }
-        }
+                return -ENOMEM;
 
-        return m;
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "JobNew",
+                        &m);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, m, destination, NULL);
 }
 
-static DBusMessage* new_removed_signal_message(Job *j) {
+static int send_changed_signal(sd_bus *bus, const char *destination, Job *j) {
         _cleanup_free_ char *p = NULL;
-        DBusMessage *m;
-        const char *r;
+
+        assert(bus);
+        assert(j);
 
         p = job_dbus_path(j);
         if (!p)
-                return NULL;
-
-        m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "JobRemoved");
-        if (!m)
-                return NULL;
-
-        r = job_result_to_string(j->result);
-
-        if (!dbus_message_append_args(m,
-                                      DBUS_TYPE_UINT32, &j->id,
-                                      DBUS_TYPE_OBJECT_PATH, &p,
-                                      DBUS_TYPE_STRING, &j->unit->id,
-                                      DBUS_TYPE_STRING, &r,
-                                      DBUS_TYPE_INVALID)) {
-                dbus_message_unref(m);
-                return NULL;
-        }
+                return -ENOMEM;
 
-        return m;
+        return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL);
 }
 
 void bus_job_send_change_signal(Job *j) {
+        int r;
+
         assert(j);
 
         if (j->in_dbus_queue) {
@@ -323,36 +165,52 @@ void bus_job_send_change_signal(Job *j) {
                 j->in_dbus_queue = false;
         }
 
-        if (!bus_has_subscriber(j->manager) && !j->bus_client_list && !j->forgot_bus_clients) {
-                j->sent_dbus_new_signal = true;
-                return;
-        }
-
-        if (job_send_message(j, new_change_signal_message) < 0)
-                goto oom;
+        r = foreach_client(j, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal);
+        if (r < 0)
+                log_warning("Failed to send job change signal for %u/%s: %s", j->id, j->unit->id, strerror(-r));
 
         j->sent_dbus_new_signal = true;
+}
+
+static int send_removed_signal(sd_bus *bus, const char *destination, Job *j) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_free_ char *p = NULL;
+        int r;
+
+        assert(bus);
+        assert(j);
+
+        p = job_dbus_path(j);
+        if (!p)
+                return -ENOMEM;
 
-        return;
 
-oom:
-        log_error("Failed to allocate job change signal.");
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "JobRemoved",
+                        &m);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result));
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, m, destination, NULL);
 }
 
 void bus_job_send_removed_signal(Job *j) {
-        assert(j);
+        int r;
 
-        if (!bus_has_subscriber(j->manager) && !j->bus_client_list && !j->forgot_bus_clients)
-                return;
+        assert(j);
 
         if (!j->sent_dbus_new_signal)
                 bus_job_send_change_signal(j);
 
-        if (job_send_message(j, new_removed_signal_message) < 0)
-                goto oom;
-
-        return;
-
-oom:
-        log_error("Failed to allocate job remove signal.");
+        r = foreach_client(j, send_removed_signal);
+        if (r < 0)
+                log_warning("Failed to send job removal signal for %u/%s: %s", j->id, j->unit->id, strerror(-r));
+                return;
 }
index a1b928fb16ab4376c7bfc79b4d754b9775c67c34..d1d0f6ddf0127b8f461e9086c5c59b24c00a0731 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "job.h"
 
+extern const sd_bus_vtable bus_job_vtable[];
+
 void bus_job_send_change_signal(Job *j);
 void bus_job_send_removed_signal(Job *j);
-
-extern const DBusObjectPathVTable bus_job_vtable;
-
-extern const char bus_job_interface[];
index 811adb1b5acc14e8b1ef790cca56524e204ed24c..42488b1f54e97fbe85ec413908b2c5c9a4b00f06 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-#include <dbus/dbus.h>
-
+#include "bus-util.h"
+#include "kill.h"
 #include "dbus-kill.h"
-#include "dbus-common.h"
+#include "bus-util.h"
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_kill_append_mode, kill_mode, KillMode);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_kill_mode, kill_mode, KillMode);
 
-const BusProperty bus_kill_context_properties[] = {
-        { "KillMode",    bus_kill_append_mode,     "s", offsetof(KillContext, kill_mode)    },
-        { "KillSignal",  bus_property_append_int,  "i", offsetof(KillContext, kill_signal)  },
-        { "SendSIGKILL", bus_property_append_bool, "b", offsetof(KillContext, send_sigkill) },
-        { "SendSIGHUP",  bus_property_append_bool, "b", offsetof(KillContext, send_sighup)  },
-        {}
+const sd_bus_vtable bus_kill_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("KillMode", "s", property_get_kill_mode, offsetof(KillContext, kill_mode), 0),
+        SD_BUS_PROPERTY("KillSignal", "i", bus_property_get_int, offsetof(KillContext, kill_signal), 0),
+        SD_BUS_PROPERTY("SendSIGKILL", "b", bus_property_get_bool, offsetof(KillContext, send_sigkill), 0),
+        SD_BUS_PROPERTY("SendSIGHUP", "b", bus_property_get_bool,  offsetof(KillContext, send_sighup), 0),
+        SD_BUS_VTABLE_END
 };
 
 int bus_kill_context_set_transient_property(
                 Unit *u,
                 KillContext *c,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
+
+        int r;
 
         assert(u);
         assert(c);
         assert(name);
-        assert(i);
+        assert(message);
 
         if (streq(name, "KillMode")) {
                 const char *m;
                 KillMode k;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
-
-                dbus_message_iter_get_basic(i, &m);
+                r = sd_bus_message_read(message, "s", &m);
+                if (r < 0)
+                        return r;
 
                 k = kill_mode_from_string(m);
                 if (k < 0)
@@ -70,14 +71,13 @@ int bus_kill_context_set_transient_property(
                 return 1;
 
         } else if (streq(name, "SendSIGHUP")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-
-                        dbus_message_iter_get_basic(i, &b);
                         c->send_sighup = b;
 
                         unit_write_drop_in_private_format(u, mode, name, "SendSIGHUP=%s\n", yes_no(b));
@@ -86,14 +86,13 @@ int bus_kill_context_set_transient_property(
                 return 1;
 
         } else if (streq(name, "SendSIGKILL")) {
+                int b;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-
-                        dbus_message_iter_get_basic(i, &b);
                         c->send_sigkill = b;
 
                         unit_write_drop_in_private_format(u, mode, name, "SendSIGKILL=%s\n", yes_no(b));
index 7676d98e9137425901e136e1ef590b1507e3c078..7c15f3a90b60db16802ce5f1344703485a5f8844 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
+#include "unit.h"
+#include "kill.h"
 
-#include "manager.h"
-#include "dbus-common.h"
+extern const sd_bus_vtable bus_kill_vtable[];
 
-#define BUS_KILL_CONTEXT_INTERFACE                                      \
-        "  <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n"  \
-        "  <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n" \
-        "  <property name=\"SendSIGKILL\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"SendSIGHUP\" type=\"b\" access=\"read\"/>\n"
-
-extern const BusProperty bus_kill_context_properties[];
-
-int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
index 747bcfcb9167d617d10c10b5785e2f84e47faa84..2e4de2e4316bbe71dcd65b12e4ec781037d0b497 100644 (file)
 #include <errno.h>
 #include <unistd.h>
 
-#include "dbus.h"
 #include "log.h"
-#include "dbus-manager.h"
 #include "strv.h"
-#include "bus-errors.h"
 #include "build.h"
-#include "dbus-common.h"
 #include "install.h"
 #include "selinux-access.h"
 #include "watchdog.h"
 #include "hwclock.h"
 #include "path-util.h"
-#include "dbus-unit.h"
 #include "virt.h"
 #include "env-util.h"
+#include "dbus.h"
+#include "dbus-manager.h"
+#include "dbus-unit.h"
+#include "dbus-snapshot.h"
+#include "dbus-client-track.h"
+#include "dbus-execute.h"
+#include "bus-errors.h"
 
-#define BUS_MANAGER_INTERFACE_BEGIN                                     \
-        " <interface name=\"org.freedesktop.systemd1.Manager\">\n"
-
-#define BUS_MANAGER_INTERFACE_METHODS                                   \
-        "  <method name=\"GetUnit\">\n"                                 \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetUnitByPID\">\n"                            \
-        "   <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n"          \
-        "   <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"LoadUnit\">\n"                                \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"StartUnit\">\n"                               \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"StartUnitReplace\">\n"                        \
-        "   <arg name=\"old_unit\" type=\"s\" direction=\"in\"/>\n"     \
-        "   <arg name=\"new_unit\" type=\"s\" direction=\"in\"/>\n"     \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"StopUnit\">\n"                                \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadUnit\">\n"                              \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"RestartUnit\">\n"                             \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"TryRestartUnit\">\n"                          \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadOrRestartUnit\">\n"                     \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadOrTryRestartUnit\">\n"                  \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"KillUnit\">\n"                                \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"who\" type=\"s\" direction=\"in\"/>\n"          \
-        "   <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"ResetFailedUnit\">\n"                         \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetJob\">\n"                                  \
-        "   <arg name=\"id\" type=\"u\" direction=\"in\"/>\n"           \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"CancelJob\">\n"                               \
-        "   <arg name=\"id\" type=\"u\" direction=\"in\"/>\n"           \
-        "  </method>\n"                                                 \
-        "  <method name=\"ClearJobs\"/>\n"                              \
-        "  <method name=\"ResetFailed\"/>\n"                            \
-        "  <method name=\"ListUnits\">\n"                               \
-        "   <arg name=\"units\" type=\"a(ssssssouso)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"ListJobs\">\n"                                \
-        "   <arg name=\"jobs\" type=\"a(usssoo)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"Subscribe\"/>\n"                              \
-        "  <method name=\"Unsubscribe\"/>\n"                            \
-        "  <method name=\"Dump\">\n"                                    \
-        "   <arg name=\"dump\" type=\"s\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"CreateSnapshot\">\n"                          \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"cleanup\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"unit\" type=\"o\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"RemoveSnapshot\">\n"                          \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Reload\"/>\n"                                 \
-        "  <method name=\"Reexecute\"/>\n"                              \
-        "  <method name=\"Exit\"/>\n"                                   \
-        "  <method name=\"Reboot\"/>\n"                                 \
-        "  <method name=\"PowerOff\"/>\n"                               \
-        "  <method name=\"Halt\"/>\n"                                   \
-        "  <method name=\"KExec\"/>\n"                                  \
-        "  <method name=\"SwitchRoot\">\n"                              \
-        "   <arg name=\"new_root\" type=\"s\" direction=\"in\"/>\n"     \
-        "   <arg name=\"init\" type=\"s\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"SetEnvironment\">\n"                          \
-        "   <arg name=\"names\" type=\"as\" direction=\"in\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"UnsetEnvironment\">\n"                        \
-        "   <arg name=\"names\" type=\"as\" direction=\"in\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"UnsetAndSetEnvironment\">\n"                  \
-        "   <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"set\" type=\"as\" direction=\"in\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ListUnitFiles\">\n"                           \
-        "   <arg name=\"files\" type=\"a(ss)\" direction=\"out\"/>\n"   \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetUnitFileState\">\n"                        \
-        "   <arg name=\"file\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"state\" type=\"s\" direction=\"out\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"EnableUnitFiles\">\n"                         \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"DisableUnitFiles\">\n"                        \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReenableUnitFiles\">\n"                       \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"LinkUnitFiles\">\n"                           \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"PresetUnitFiles\">\n"                         \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"MaskUnitFiles\">\n"                           \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"force\" type=\"b\" direction=\"in\"/>\n"        \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"UnmaskUnitFiles\">\n"                         \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"SetDefaultTarget\">\n"                        \
-        "   <arg name=\"files\" type=\"as\" direction=\"in\"/>\n"       \
-        "   <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetDefaultTarget\">\n"                        \
-        "   <arg name=\"name\" type=\"s\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"SetUnitProperties\">\n"                       \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"StartTransientUnit\">\n"                      \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
-        "   <arg name=\"aux\" type=\"a(sa(sv))\" direction=\"in\"/>\n"  \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"
-
-#define BUS_MANAGER_INTERFACE_SIGNALS                                   \
-        "  <signal name=\"UnitNew\">\n"                                 \
-        "   <arg name=\"id\" type=\"s\"/>\n"                            \
-        "   <arg name=\"unit\" type=\"o\"/>\n"                          \
-        "  </signal>\n"                                                 \
-        "  <signal name=\"UnitRemoved\">\n"                             \
-        "   <arg name=\"id\" type=\"s\"/>\n"                            \
-        "   <arg name=\"unit\" type=\"o\"/>\n"                          \
-        "  </signal>\n"                                                 \
-        "  <signal name=\"JobNew\">\n"                                  \
-        "   <arg name=\"id\" type=\"u\"/>\n"                            \
-        "   <arg name=\"job\" type=\"o\"/>\n"                           \
-        "   <arg name=\"unit\" type=\"s\"/>\n"                          \
-        "  </signal>\n"                                                 \
-        "  <signal name=\"JobRemoved\">\n"                              \
-        "   <arg name=\"id\" type=\"u\"/>\n"                            \
-        "   <arg name=\"job\" type=\"o\"/>\n"                           \
-        "   <arg name=\"unit\" type=\"s\"/>\n"                          \
-        "   <arg name=\"result\" type=\"s\"/>\n"                        \
-        "  </signal>"                                                   \
-        "  <signal name=\"StartupFinished\">\n"                         \
-        "   <arg name=\"firmware\" type=\"t\"/>\n"                      \
-        "   <arg name=\"loader\" type=\"t\"/>\n"                        \
-        "   <arg name=\"kernel\" type=\"t\"/>\n"                        \
-        "   <arg name=\"initrd\" type=\"t\"/>\n"                        \
-        "   <arg name=\"userspace\" type=\"t\"/>\n"                     \
-        "   <arg name=\"total\" type=\"t\"/>\n"                         \
-        "  </signal>"                                                   \
-        "  <signal name=\"UnitFilesChanged\"/>\n"                       \
-        "  <signal name=\"Reloading\">\n"                               \
-        "   <arg name=\"active\" type=\"b\"/>\n"                        \
-        "  </signal>"
-
-#define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL                        \
-        "  <property name=\"Version\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"Features\" type=\"s\" access=\"read\"/>\n"  \
-        "  <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"FirmwareTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"FirmwareTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LoaderTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LoaderTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"KernelTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"KernelTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UserspaceTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UserspaceTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"FinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SecurityStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SecurityStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SecurityFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SecurityFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"GeneratorsStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"GeneratorsStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"GeneratorsFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"GeneratorsFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UnitsLoadStartTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UnitsLoadStartTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UnitsLoadFinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"UnitsLoadFinishTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n"  \
-        "  <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
-        "  <property name=\"NNames\" type=\"u\" access=\"read\"/>\n"    \
-        "  <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n"     \
-        "  <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"NFailedJobs\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Progress\" type=\"d\" access=\"read\"/>\n"  \
-        "  <property name=\"Environment\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ConfirmSpawn\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"ShowStatus\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"UnitPath\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"RuntimeWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
-        "  <property name=\"ShutdownWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
-        "  <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
-
-#define BUS_MANAGER_INTERFACE_END                                       \
-        " </interface>\n"
-
-#define BUS_MANAGER_INTERFACE                                           \
-        BUS_MANAGER_INTERFACE_BEGIN                                     \
-        BUS_MANAGER_INTERFACE_METHODS                                   \
-        BUS_MANAGER_INTERFACE_SIGNALS                                   \
-        BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL                        \
-        BUS_MANAGER_INTERFACE_END
-
-#define INTROSPECTION_BEGIN                                             \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_MANAGER_INTERFACE                                           \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE
-
-#define INTROSPECTION_END                                               \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_GENERIC_INTERFACES_LIST                  \
-        "org.freedesktop.systemd1.Manager\0"
-
-const char bus_manager_interface[] = BUS_MANAGER_INTERFACE;
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
-
-static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
-        const char *t;
-        Manager *m = data;
-        char buf[LINE_MAX] = "", *e = buf, *p = NULL;
+static int property_get_version(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        assert(bus);
+        assert(reply);
+
+        return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
+}
 
-        assert(i);
-        assert(property);
+static int property_get_features(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        assert(bus);
+        assert(reply);
+
+        return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
+}
+
+static int property_get_virtualization(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        const char *id = NULL;
+
+        assert(bus);
+        assert(reply);
+
+        detect_virtualization(&id);
+
+        return sd_bus_message_append(reply, "s", id);
+}
+
+static int property_get_tainted(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        char buf[LINE_MAX] = "", *e = buf;
+        _cleanup_free_ char *p = NULL;
+        Manager *m = userdata;
+
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (m->taint_usr)
@@ -343,8 +111,6 @@ static int bus_manager_append_tainted(DBusMessageIter *i, const char *property,
 
         if (readlink_malloc("/etc/mtab", &p) < 0)
                 e = stpcpy(e, "mtab-not-symlink:");
-        else
-                free(p);
 
         if (access("/proc/cgroups", F_OK) < 0)
                 e = stpcpy(e, "cgroups-missing:");
@@ -356,105 +122,140 @@ static int bus_manager_append_tainted(DBusMessageIter *i, const char *property,
         if (e != buf)
                 e[-1] = 0;
 
-        t = buf;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", buf);
 }
 
-static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
-        const char *t;
-
-        assert(i);
-        assert(property);
-
-        t = log_target_to_string(log_get_target());
+static int property_get_log_target(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
 
-        return 0;
+        return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
 }
 
-static int bus_manager_set_log_target(DBusMessageIter *i, const char *property, void *data) {
+static int property_set_log_target(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *value,
+                sd_bus_error *error,
+                void *userdata) {
+
         const char *t;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(value);
 
-        dbus_message_iter_get_basic(i, &t);
+        r = sd_bus_message_read(value, "s", &t);
+        if (r < 0)
+                return r;
 
         return log_set_target_from_string(t);
 }
 
-static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
+static int property_get_log_level(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
         _cleanup_free_ char *t = NULL;
         int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
 
         r = log_level_to_string_alloc(log_get_max_level(), &t);
         if (r < 0)
                 return r;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
-                r = -ENOMEM;
-
-        return r;
+        return sd_bus_message_append(reply, "s", t);
 }
 
-static int bus_manager_set_log_level(DBusMessageIter *i, const char *property, void *data) {
+static int property_set_log_level(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *value,
+                sd_bus_error *error,
+                void *userdata) {
+
         const char *t;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(value);
 
-        dbus_message_iter_get_basic(i, &t);
+        r = sd_bus_message_read(value, "s", &t);
+        if (r < 0)
+                return r;
 
         return log_set_max_level_from_string(t);
 }
 
-static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
-        Manager *m = data;
-        uint32_t u;
+static int property_get_n_names(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(m);
+        Manager *m = userdata;
 
-        u = hashmap_size(m->units);
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(m);
 
-        return 0;
+        return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
 }
 
-static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
-        Manager *m = data;
-        uint32_t u;
+static int property_get_n_jobs(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(m);
+        Manager *m = userdata;
 
-        u = hashmap_size(m->jobs);
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(m);
 
-        return 0;
+        return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
 }
 
-static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
+static int property_get_progress(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Manager *m = userdata;
         double d;
-        Manager *m = data;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (dual_timestamp_is_set(&m->finish_timestamp))
@@ -462,1416 +263,1375 @@ static int bus_manager_append_progress(DBusMessageIter *i, const char *property,
         else
                 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_DOUBLE, &d))
-                return -ENOMEM;
+        return sd_bus_message_append(reply, "d", d);
+}
+
+static int property_set_runtime_watchdog(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *value,
+                sd_bus_error *error,
+                void *userdata) {
 
-        return 0;
+        usec_t *t = userdata;
+        int r;
+
+        assert(bus);
+        assert(value);
+
+        assert_cc(sizeof(usec_t) == sizeof(uint64_t));
+
+        r = sd_bus_message_read(value, "t", t);
+        if (r < 0)
+                return r;
+
+        return watchdog_set_timeout(t);
 }
 
-static int bus_manager_append_virt(DBusMessageIter *i, const char *property, void *data) {
-        Manager *m = data;
-        const char *id = NULL;
+static int method_get_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(message);
         assert(m);
 
-        detect_virtualization(&id);
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        if (!id)
-                id = "";
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &id))
-                return -ENOMEM;
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
 
-        return 0;
-}
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "status");
 
-static DBusMessage *message_from_file_changes(
-                DBusMessage *m,
-                UnitFileChange *changes,
-                unsigned n_changes,
-                int carries_install_info) {
+        path = unit_dbus_path(u);
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-        DBusMessageIter iter, sub, sub2;
-        DBusMessage *reply;
-        unsigned i;
+        return sd_bus_reply_method_return(bus, message, "o", path);
+}
 
-        reply = dbus_message_new_method_return(m);
-        if (!reply)
-                return NULL;
+static int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        pid_t pid;
+        Unit *u;
+        int r;
 
-        dbus_message_iter_init_append(reply, &iter);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-        if (carries_install_info >= 0) {
-                dbus_bool_t b;
+        assert_cc(sizeof(pid_t) == sizeof(uint32_t));
 
-                b = !!carries_install_info;
-                if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
-                        goto oom;
+        r = sd_bus_message_read(message, "u", &pid);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        if (pid == 0) {
+                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                if (r < 0)
+                        return sd_bus_reply_method_errno(bus, message, r, NULL);
         }
 
-        if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
-                goto oom;
+        u = manager_get_unit_by_pid(m, pid);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_UNIT_FOR_PID, "PID %u does not belong to any loaded unit.", pid);
 
-        for (i = 0; i < n_changes; i++) {
-                const char *type, *path, *source;
-
-                type = unit_file_change_type_to_string(changes[i].type);
-                path = strempty(changes[i].path);
-                source = strempty(changes[i].source);
-
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        goto oom;
-        }
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "status");
+
+        path = unit_dbus_path(u);
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+        return sd_bus_reply_method_return(bus, message, "o", path);
+}
+
+static int method_load_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-        if (!dbus_message_iter_close_container(&iter, &sub))
-                goto oom;
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        return reply;
+        r = manager_load_unit(m, name, NULL, &error, &u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
+
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "status");
 
-oom:
-        dbus_message_unref(reply);
-        return NULL;
+        path = unit_dbus_path(u);
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+        return sd_bus_reply_method_return(bus, message, "o", path);
 }
 
-static int bus_manager_send_unit_files_changed(Manager *m) {
-        DBusMessage *s;
+static int method_start_unit_generic(sd_bus *bus, sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        const char *name;
+        Unit *u;
         int r;
 
-        s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
-        if (!s)
-                return -ENOMEM;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-        r = bus_broadcast(m, s);
-        dbus_message_unref(s);
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        return r;
+        r = manager_load_unit(m, name, NULL, &error, &u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
+
+        return bus_unit_method_start_generic(bus, message, u, job_type, reload_if_possible);
 }
 
-static int bus_manager_set_runtime_watchdog_usec(DBusMessageIter *i, const char *property, void *data) {
-        uint64_t *t = data;
+static int method_start_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_START, false);
+}
 
-        assert(i);
-        assert(property);
+static int method_stop_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_STOP, false);
+}
 
-        dbus_message_iter_get_basic(i, t);
+static int method_reload_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_RELOAD, false);
+}
 
-        return watchdog_set_timeout(t);
+static int method_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_RESTART, false);
 }
 
-static const char systemd_property_string[] =
-        PACKAGE_STRING "\0"
-        SYSTEMD_FEATURES;
+static int method_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, false);
+}
 
-static const BusProperty bus_systemd_properties[] = {
-        { "Version",       bus_property_append_string,    "s",  0                      },
-        { "Features",      bus_property_append_string,    "s",  sizeof(PACKAGE_STRING) },
-        { NULL, }
-};
+static int method_reload_or_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_RESTART, true);
+}
 
-static const BusProperty bus_manager_properties[] = {
-        { "Tainted",                     bus_manager_append_tainted,     "s",  0                                                },
-        { "FirmwareTimestamp",           bus_property_append_uint64,     "t",  offsetof(Manager, firmware_timestamp.realtime)   },
-        { "FirmwareTimestampMonotonic",  bus_property_append_uint64,     "t",  offsetof(Manager, firmware_timestamp.monotonic)  },
-        { "LoaderTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, loader_timestamp.realtime)     },
-        { "LoaderTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, loader_timestamp.monotonic)    },
-        { "KernelTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, kernel_timestamp.realtime)     },
-        { "KernelTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, kernel_timestamp.monotonic)    },
-        { "InitRDTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, initrd_timestamp.realtime)     },
-        { "InitRDTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, initrd_timestamp.monotonic)    },
-        { "UserspaceTimestamp",          bus_property_append_uint64,     "t",  offsetof(Manager, userspace_timestamp.realtime)  },
-        { "UserspaceTimestampMonotonic", bus_property_append_uint64,     "t",  offsetof(Manager, userspace_timestamp.monotonic) },
-        { "FinishTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, finish_timestamp.realtime)     },
-        { "FinishTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, finish_timestamp.monotonic)    },
-        { "SecurityStartTimestamp",             bus_property_append_uint64,     "t",  offsetof(Manager, security_start_timestamp.realtime)     },
-        { "SecurityStartTimestampMonotonic",    bus_property_append_uint64,     "t",  offsetof(Manager, security_start_timestamp.monotonic)    },
-        { "SecurityFinishTimestamp",            bus_property_append_uint64,     "t",  offsetof(Manager, security_finish_timestamp.realtime)    },
-        { "SecurityFinishTimestampMonotonic",   bus_property_append_uint64,     "t",  offsetof(Manager, security_finish_timestamp.monotonic)   },
-        { "GeneratorsStartTimestamp",           bus_property_append_uint64,     "t",  offsetof(Manager, generators_start_timestamp.realtime)   },
-        { "GeneratorsStartTimestampMonotonic",  bus_property_append_uint64,     "t",  offsetof(Manager, generators_start_timestamp.monotonic)  },
-        { "GeneratorsFinishTimestamp",          bus_property_append_uint64,     "t",  offsetof(Manager, generators_finish_timestamp.realtime)  },
-        { "GeneratorsFinishTimestampMonotonic", bus_property_append_uint64,     "t",  offsetof(Manager, generators_finish_timestamp.monotonic) },
-        { "UnitsLoadStartTimestamp",            bus_property_append_uint64,     "t",  offsetof(Manager, unitsload_start_timestamp.realtime)    },
-        { "UnitsLoadStartTimestampMonotonic",   bus_property_append_uint64,     "t",  offsetof(Manager, unitsload_start_timestamp.monotonic)   },
-        { "UnitsLoadFinishTimestamp",           bus_property_append_uint64,     "t",  offsetof(Manager, unitsload_finish_timestamp.realtime)   },
-        { "UnitsLoadFinishTimestampMonotonic",  bus_property_append_uint64,     "t",  offsetof(Manager, unitsload_finish_timestamp.monotonic)  },
-        { "LogLevel",                    bus_manager_append_log_level,   "s",  0,                                               false, bus_manager_set_log_level },
-        { "LogTarget",                   bus_manager_append_log_target,  "s",  0,                                               false, bus_manager_set_log_target },
-        { "NNames",                      bus_manager_append_n_names,     "u",  0                                                },
-        { "NJobs",                       bus_manager_append_n_jobs,      "u",  0                                                },
-        { "NInstalledJobs",              bus_property_append_uint32,     "u",  offsetof(Manager, n_installed_jobs)              },
-        { "NFailedJobs",                 bus_property_append_uint32,     "u",  offsetof(Manager, n_failed_jobs)                 },
-        { "Progress",                    bus_manager_append_progress,    "d",  0                                                },
-        { "Environment",                 bus_property_append_strv,       "as", offsetof(Manager, environment),                  true },
-        { "ConfirmSpawn",                bus_property_append_bool,       "b",  offsetof(Manager, confirm_spawn)                 },
-        { "ShowStatus",                  bus_property_append_bool,       "b",  offsetof(Manager, show_status)                   },
-        { "UnitPath",                    bus_property_append_strv,       "as", offsetof(Manager, lookup_paths.unit_path),       true },
-        { "DefaultStandardOutput",       bus_manager_append_exec_output, "s",  offsetof(Manager, default_std_output)            },
-        { "DefaultStandardError",        bus_manager_append_exec_output, "s",  offsetof(Manager, default_std_error)             },
-        { "RuntimeWatchdogUSec",         bus_property_append_usec,       "t",  offsetof(Manager, runtime_watchdog),             false, bus_manager_set_runtime_watchdog_usec },
-        { "ShutdownWatchdogUSec",        bus_property_append_usec,       "t",  offsetof(Manager, shutdown_watchdog),            false, bus_property_set_usec },
-        { "Virtualization",              bus_manager_append_virt,        "s",  0,                                               },
-        { NULL, }
-};
+static int method_reload_or_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, true);
+}
 
-static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        _cleanup_free_ char * path = NULL;
-        Manager *m = data;
+static int method_start_unit_replace(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *old_name;
+        Unit *u;
         int r;
-        DBusError error;
-        JobType job_type = _JOB_TYPE_INVALID;
-        bool reload_if_possible = false;
-        const char *member;
 
-        assert(connection);
+        assert(bus);
         assert(message);
         assert(m);
 
-        dbus_error_init(&error);
+        r = sd_bus_message_read(message, "s", &old_name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        member = dbus_message_get_member(message);
+        u = manager_get_unit(m, old_name);
+        if (!u || !u->job || u->job->type != JOB_START)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
 
-        if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
-                const char *name;
-                Unit *u;
+        return method_start_unit_generic(bus, message, m, JOB_START, false);
+}
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+static int method_kill_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = unit_dbus_path(u);
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitByPID")) {
-                Unit *u;
-                uint32_t pid;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_UINT32, &pid,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                u = manager_get_unit_by_pid(m, (pid_t) pid);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = unit_dbus_path(u);
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) {
-                const char *name;
-                Unit *u;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                r = manager_load_unit(m, name, NULL, &error, &u);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = unit_dbus_path(u);
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnit"))
-                job_type = JOB_START;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
-                job_type = JOB_START;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StopUnit"))
-                job_type = JOB_STOP;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadUnit"))
-                job_type = JOB_RELOAD;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RestartUnit"))
-                job_type = JOB_RESTART;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "TryRestartUnit"))
-                job_type = JOB_TRY_RESTART;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrRestartUnit")) {
-                reload_if_possible = true;
-                job_type = JOB_RESTART;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
-                reload_if_possible = true;
-                job_type = JOB_TRY_RESTART;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
-                const char *name, *swho;
-                int32_t signo;
-                Unit *u;
-                KillWho who;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_STRING, &swho,
-                                    DBUS_TYPE_INT32, &signo,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                if (isempty(swho))
-                        who = KILL_ALL;
-                else {
-                        who = kill_who_from_string(swho);
-                        if (who < 0)
-                                return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
 
-                if (signo <= 0 || signo >= _NSIG)
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        return bus_unit_method_kill(bus, message, u);
+}
 
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+static int method_reset_failed_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                r = unit_kill(u, who, signo, &error);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
-                uint32_t id;
-                Job *j;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_UINT32, &id,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                j = manager_get_job(m, id);
-                if (!j) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = job_dbus_path(j);
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CancelJob")) {
-                uint32_t id;
-                Job *j;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_UINT32, &id,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                j = manager_get_job(m, id);
-                if (!j) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
 
-                SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
-                job_finish_and_invalidate(j, JOB_CANCELED, true);
+        return bus_unit_method_reset_failed(bus, message, u);
+}
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+static int method_set_unit_properties(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reboot");
-                manager_clear_jobs(m);
+        return bus_unit_method_set_properties(bus, message, u);
+}
+
+static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        const char *name, *smode;
+        Manager *m = userdata;
+        JobMode mode;
+        UnitType t;
+        Unit *u;
+        int r;
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
+        r = sd_bus_message_read(message, "ss", &name, &smode);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        t = unit_name_to_type(name);
+        if (t < 0)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type.");
 
-                manager_reset_failed(m);
+        if (!unit_vtable[t]->can_transient)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        mode = job_mode_from_string(smode);
+        if (mode < 0)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
-                const char *name;
-                Unit *u;
+        r = manager_load_unit(m, name, NULL, &error, &u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "start");
 
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
-
-                unit_reset_failed(u);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
-                DBusMessageIter iter, sub;
-                Iterator i;
-                Unit *u;
-                const char *k;
-
-                SELINUX_ACCESS_CHECK(connection, message, "status");
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                dbus_message_iter_init_append(reply, &iter);
-
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssssouso)", &sub))
-                        goto oom;
-
-                HASHMAP_FOREACH_KEY(u, k, m->units, i) {
-                        char *u_path, *j_path;
-                        const char *description, *load_state, *active_state, *sub_state, *sjob_type, *following;
-                        DBusMessageIter sub2;
-                        uint32_t job_id;
-                        Unit *f;
-
-                        if (k != u->id)
-                                continue;
-
-                        if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
-                                goto oom;
-
-                        description = unit_description(u);
-                        load_state = unit_load_state_to_string(u->load_state);
-                        active_state = unit_active_state_to_string(unit_active_state(u));
-                        sub_state = unit_sub_state_to_string(u);
-
-                        f = unit_following(u);
-                        following = f ? f->id : "";
-
-                        u_path = unit_dbus_path(u);
-                        if (!u_path)
-                                goto oom;
-
-                        if (u->job) {
-                                job_id = (uint32_t) u->job->id;
-
-                                if (!(j_path = job_dbus_path(u->job))) {
-                                        free(u_path);
-                                        goto oom;
-                                }
-
-                                sjob_type = job_type_to_string(u->job->type);
-                        } else {
-                                job_id = 0;
-                                j_path = u_path;
-                                sjob_type = "";
-                        }
-
-                        if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->id) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &following) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sjob_type) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) {
-                                free(u_path);
-                                if (u->job)
-                                        free(j_path);
-                                goto oom;
-                        }
-
-                        free(u_path);
-                        if (u->job)
-                                free(j_path);
-
-                        if (!dbus_message_iter_close_container(&sub, &sub2))
-                                goto oom;
-                }
+        /* OK, the unit failed to load and is unreferenced, now let's
+         * fill in the transient data instead */
+        r = unit_make_transient(u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
+        /* Set our properties */
+        r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, &error);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) {
-                DBusMessageIter iter, sub;
-                Iterator i;
-                Job *j;
+        /* And load this stub fully */
+        r = unit_load(u);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        manager_dispatch_load_queue(m);
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        /* Finally, start it */
+        return bus_unit_queue_job(bus, message, u, JOB_START, mode, false);
+}
 
-                dbus_message_iter_init_append(reply, &iter);
+static int method_get_job(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        uint32_t id;
+        Job *j;
+        int r;
 
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(usssoo)", &sub))
-                        goto oom;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                HASHMAP_FOREACH(j, m->jobs, i) {
-                        char *u_path, *j_path;
-                        const char *state, *type;
-                        uint32_t id;
-                        DBusMessageIter sub2;
+        r = sd_bus_message_read(message, "u", &id);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                        if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
-                                goto oom;
+        j = manager_get_job(m, id);
+        if (!j)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
 
-                        id = (uint32_t) j->id;
-                        state = job_state_to_string(j->state);
-                        type = job_type_to_string(j->type);
+        SELINUX_UNIT_ACCESS_CHECK(j->unit, bus, message, "status");
 
-                        j_path = job_dbus_path(j);
-                        if (!j_path)
-                                goto oom;
+        path = job_dbus_path(j);
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                        u_path = unit_dbus_path(j->unit);
-                        if (!u_path) {
-                                free(j_path);
-                                goto oom;
-                        }
+        return sd_bus_reply_method_return(bus, message, "o", path);
+}
 
-                        if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->id) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) {
-                                free(j_path);
-                                free(u_path);
-                                goto oom;
-                        }
+static int method_cancel_job(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        uint32_t id;
+        Job *j;
+        int r;
 
-                        free(j_path);
-                        free(u_path);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                        if (!dbus_message_iter_close_container(&sub, &sub2))
-                                goto oom;
-                }
+        r = sd_bus_message_read(message, "u", &id);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
+        j = manager_get_job(m, id);
+        if (!j)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) {
-                char *client;
-                Set *s;
+        SELINUX_UNIT_ACCESS_CHECK(j->unit, bus, message, "stop");
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        job_finish_and_invalidate(j, JOB_CANCELED, true);
 
-                s = bus_acquire_subscribed(m, connection);
-                if (!s)
-                        goto oom;
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                client = strdup(bus_message_get_sender_with_fallback(message));
-                if (!client)
-                        goto oom;
+static int method_clear_jobs(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                r = set_consume(s, client);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        SELINUX_ACCESS_CHECK(bus, message, "reboot");
+        manager_clear_jobs(m);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
-                char *client;
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+static int method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
-                if (!client) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
+        manager_reset_failed(m);
 
-                free(client);
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        Manager *m = userdata;
+        const char *k;
+        Iterator i;
+        Unit *u;
+        int r;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
-                FILE *f;
-                char *dump = NULL;
-                size_t size;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        r = sd_bus_message_new_method_return(bus, message, &reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                f = open_memstream(&dump, &size);
-                if (!f)
-                        goto oom;
+        r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                manager_dump_units(m, f, NULL);
-                manager_dump_jobs(m, f, NULL);
+        HASHMAP_FOREACH_KEY(u, k, m->units, i) {
+                _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
+                Unit *following;
 
-                if (ferror(f)) {
-                        fclose(f);
-                        free(dump);
-                        goto oom;
-                }
+                if (k != u->id)
+                        continue;
 
-                fclose(f);
+                following = unit_following(u);
 
-                if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) {
-                        free(dump);
-                        goto oom;
+                unit_path = unit_dbus_path(u);
+                if (!unit_path)
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+                if (u->job) {
+                        job_path = job_dbus_path(u->job);
+                        if (!job_path)
+                                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
                 }
 
-                free(dump);
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) {
-                const char *name;
-                dbus_bool_t cleanup;
-                Snapshot *s;
+                r = sd_bus_message_append(
+                                reply, "(ssssssouso)",
+                                u->id,
+                                unit_description(u),
+                                unit_load_state_to_string(u->load_state),
+                                unit_active_state_to_string(unit_active_state(u)),
+                                unit_sub_state_to_string(u),
+                                following ? following->id : "",
+                                unit_path,
+                                u->job ? u->job->id : 0,
+                                u->job ? job_type_to_string(u->job->type) : "",
+                                job_path ? job_path : "/");
+                if (r < 0)
+                        return sd_bus_reply_method_errno(bus, message, r, NULL);
+        }
 
-                SELINUX_ACCESS_CHECK(connection, message, "start");
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_BOOLEAN, &cleanup,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        return sd_bus_send(bus, reply, NULL);
+}
 
-                if (isempty(name))
-                        name = NULL;
+static int method_list_jobs(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        Manager *m = userdata;
+        Iterator i;
+        Job *j;
+        int r;
 
-                r = snapshot_create(m, name, cleanup, &error, &s);
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "status");
+
+        r = sd_bus_message_new_method_return(bus, message, &reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        HASHMAP_FOREACH(j, m->jobs, i) {
+                _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
+
+                job_path = job_dbus_path(j);
+                if (!job_path)
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+                unit_path = unit_dbus_path(j->unit);
+                if (!unit_path)
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+                r = sd_bus_message_append(
+                                reply, "(usssoo)",
+                                j->id,
+                                job_state_to_string(j->state),
+                                job_type_to_string(j->type),
+                                job_path,
+                                unit_path);
                 if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                path = unit_dbus_path(UNIT(s));
-                if (!path)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_OBJECT_PATH, &path,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "RemoveSnapshot")) {
-                const char *name;
-                Unit *u;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+                        return sd_bus_reply_method_errno(bus, message, r, NULL);
+        }
 
-                if (u->type != UNIT_SNAPSHOT) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
-                snapshot_remove(SNAPSHOT(u));
+        return sd_bus_send(bus, reply, NULL);
+}
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        int r;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
-                _cleanup_free_ char *introspection = NULL;
-                FILE *f;
-                Iterator i;
-                Unit *u;
-                Job *j;
-                const char *k;
-                size_t size;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        r = bus_client_track(&m->subscribed, bus, sd_bus_message_get_sender(message));
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+        if (r == 0)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
 
-                /* We roll our own introspection code here, instead of
-                 * relying on bus_default_message_handler() because we
-                 * need to generate our introspection string
-                 * dynamically. */
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                f = open_memstream(&introspection, &size);
-                if (!f)
-                        goto oom;
+static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        int r;
 
-                fputs(INTROSPECTION_BEGIN, f);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                HASHMAP_FOREACH_KEY(u, k, m->units, i) {
-                        _cleanup_free_ char *p = NULL;
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                        if (k != u->id)
-                                continue;
+        r = bus_client_untrack(m->subscribed, bus, sd_bus_message_get_sender(message));
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+        if (r == 0)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
 
-                        p = bus_path_escape(k);
-                        if (!p) {
-                                fclose(f);
-                                goto oom;
-                        }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                        fprintf(f, "<node name=\"unit/%s\"/>", p);
-                }
+static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *dump = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        Manager *m = userdata;
+        size_t size;
 
-                HASHMAP_FOREACH(j, m->jobs, i)
-                        fprintf(f, "<node name=\"job/%lu\"/>", (unsigned long) j->id);
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                fputs(INTROSPECTION_END, f);
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                if (ferror(f)) {
-                        fclose(f);
-                        goto oom;
-                }
+        f = open_memstream(&dump, &size);
+        if (!f)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                fclose(f);
+        manager_dump_units(m, f, NULL);
+        manager_dump_jobs(m, f, NULL);
 
-                if (!introspection)
-                        goto oom;
+        fflush(f);
 
-                if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
-                        goto oom;
-                }
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
+        if (ferror(f))
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        return sd_bus_reply_method_return(bus, message, "s", dump);
+}
 
-                assert(!m->queued_message);
+static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_free_ char *path = NULL;
+        Manager *m = userdata;
+        const char *name;
+        int cleanup;
+        Snapshot *s;
+        int r;
 
-                /* Instead of sending the reply back right away, we
-                 * just remember that we need to and then send it
-                 * after the reload is finished. That way the caller
-                 * knows when the reload finished. */
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                m->queued_message = dbus_message_new_method_return(message);
-                if (!m->queued_message)
-                        goto oom;
+        SELINUX_ACCESS_CHECK(bus, message, "start");
 
-                m->queued_message_connection = connection;
-                m->exit_code = MANAGER_RELOAD;
+        r = sd_bus_message_read(message, "sb", &name, &cleanup);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
+        if (isempty(name))
+                name = NULL;
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        r = snapshot_create(m, name, cleanup, &error, &s);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                /* We don't send a reply back here, the client should
-                 * just wait for us disconnecting. */
+        path = unit_dbus_path(UNIT(s));
+        if (!path)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                m->exit_code = MANAGER_REEXECUTE;
+        return sd_bus_reply_method_return(bus, message, "o", path);
+}
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
+static int method_remove_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-                SELINUX_ACCESS_CHECK(connection, message, "halt");
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                if (m->running_as == SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        SELINUX_ACCESS_CHECK(bus, message, "start");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                m->exit_code = MANAGER_EXIT;
+        u = manager_get_unit(m, name);
+        if (!u)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
+        if (u->type != UNIT_SNAPSHOT)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reboot");
+        return bus_snapshot_method_remove(bus, message, u);
+}
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        int r;
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                m->exit_code = MANAGER_REBOOT;
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
+        /* Instead of sending the reply back right away, we just
+         * remember that we need to and then send it after the reload
+         * is finished. That way the caller knows when the reload
+         * finished. */
 
-                SELINUX_ACCESS_CHECK(connection, message, "halt");
+        assert(!m->queued_message);
+        r = sd_bus_message_new_method_return(bus, message, &m->queued_message);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        m->queued_message_bus = sd_bus_ref(bus);
+        m->exit_code = MANAGER_RELOAD;
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        return 1;
+}
 
-                m->exit_code = MANAGER_POWEROFF;
+static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "halt");
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        /* We don't send a reply back here, the client should
+         * just wait for us disconnecting. */
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        m->exit_code = MANAGER_REEXECUTE;
+        return 1;
+}
 
-                m->exit_code = MANAGER_HALT;
+static int method_exit(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reboot");
+        SELINUX_ACCESS_CHECK(bus, message, "halt");
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        if (m->running_as == SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        m->exit_code = MANAGER_EXIT;
 
-                m->exit_code = MANAGER_KEXEC;
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
-                const char *switch_root, *switch_root_init;
-                char *u, *v;
-                bool good;
+static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                SELINUX_ACCESS_CHECK(connection, message, "reboot");
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &switch_root,
-                                    DBUS_TYPE_STRING, &switch_root_init,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        SELINUX_ACCESS_CHECK(bus, message, "reboot");
 
-                if (path_equal(switch_root, "/") || !path_is_absolute(switch_root))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
 
-                if (!isempty(switch_root_init) && !path_is_absolute(switch_root_init))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        m->exit_code = MANAGER_REBOOT;
 
-                if (m->running_as != SYSTEMD_SYSTEM) {
-                        dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Switching root is only supported for system managers.");
-                        return bus_send_error_reply(connection, message, &error, -ENOTSUP);
-                }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                /* Safety check */
-                if (isempty(switch_root_init)) {
-                        good = path_is_os_tree(switch_root);
-                        if (!good)
-                                log_error("Not switching root: %s does not seem to be an OS tree. /etc/os-release is missing.", switch_root);
-                }
-                else {
-                        _cleanup_free_ char *p = NULL;
 
-                        p = strjoin(switch_root, "/", switch_root_init, NULL);
-                        if (!p)
-                                goto oom;
+static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                        good = access(p, X_OK) >= 0;
-                        if (!good)
-                                log_error("Not switching root: cannot execute new init %s", p);
-                }
-                if (!good)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                u = strdup(switch_root);
-                if (!u)
-                        goto oom;
-
-                if (!isempty(switch_root_init)) {
-                        v = strdup(switch_root_init);
-                        if (!v) {
-                                free(u);
-                                goto oom;
-                        }
-                } else
-                        v = NULL;
-
-                free(m->switch_root);
-                free(m->switch_root_init);
-                m->switch_root = u;
-                m->switch_root_init = v;
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                m->exit_code = MANAGER_SWITCH_ROOT;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
-                _cleanup_strv_free_ char **l = NULL;
-                char **e = NULL;
-
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
-
-                r = bus_parse_strv(message, &l);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-                if (!strv_env_is_valid(l))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                e = strv_env_merge(2, m->environment, l);
-                if (!e)
-                        goto oom;
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply) {
-                        strv_free(e);
-                        goto oom;
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                strv_free(m->environment);
-                m->environment = e;
+        SELINUX_ACCESS_CHECK(bus, message, "halt");
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
-                _cleanup_strv_free_ char **l = NULL;
-                char **e = NULL;
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        m->exit_code = MANAGER_POWEROFF;
 
-                r = bus_parse_strv(message, &l);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-                if (!strv_env_name_or_assignment_is_valid(l))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                e = strv_env_delete(m->environment, 1, l);
-                if (!e)
-                        goto oom;
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply) {
-                        strv_free(e);
-                        goto oom;
-                }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                strv_free(m->environment);
-                m->environment = e;
+static int method_halt(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
-                _cleanup_strv_free_ char **l_set = NULL, **l_unset = NULL, **e = NULL;
-                char **f = NULL;
-                DBusMessageIter iter;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "reload");
+        SELINUX_ACCESS_CHECK(bus, message, "halt");
 
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
 
-                r = bus_parse_strv_iter(&iter, &l_unset);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-                if (!strv_env_name_or_assignment_is_valid(l_unset))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        m->exit_code = MANAGER_HALT;
 
-                if (!dbus_message_iter_next(&iter))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                r = bus_parse_strv_iter(&iter, &l_set);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-                if (!strv_env_is_valid(l_set))
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                e = strv_env_delete(m->environment, 1, l_unset);
-                if (!e)
-                        goto oom;
-
-                f = strv_env_merge(2, e, l_set);
-                if (!f)
-                        goto oom;
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply) {
-                        strv_free(f);
-                        goto oom;
-                }
+static int method_kexec(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                strv_free(m->environment);
-                m->environment = f;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
-                DBusMessageIter iter, sub, sub2;
-                Hashmap *h;
-                Iterator i;
-                UnitFileList *item;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        SELINUX_ACCESS_CHECK(bus, message, "reboot");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
 
-                h = hashmap_new(string_hash_func, string_compare_func);
-                if (!h)
-                        goto oom;
+        m->exit_code = MANAGER_KEXEC;
 
-                r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
-                if (r < 0) {
-                        unit_file_list_free(h);
-                        return bus_send_error_reply(connection, message, NULL, r);
-                }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                dbus_message_iter_init_append(reply, &iter);
+static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        char *ri = NULL, *rt = NULL;
+        const char *root, *init;
+        Manager *m = userdata;
+        int r;
 
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
-                        unit_file_list_free(h);
-                        goto oom;
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                HASHMAP_FOREACH(item, h, i) {
-                        const char *state;
+        SELINUX_ACCESS_CHECK(bus, message, "reboot");
 
-                        state = unit_file_state_to_string(item->state);
-                        assert(state);
+        if (m->running_as != SYSTEMD_SYSTEM)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
 
-                        if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
-                            !dbus_message_iter_close_container(&sub, &sub2)) {
-                                unit_file_list_free(h);
-                                goto oom;
-                        }
-                }
+        r = sd_bus_message_read(message, "ss", &root, &init);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                unit_file_list_free(h);
-
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
-                const char *name;
-                UnitFileState state;
-                const char *s;
-
-                SELINUX_ACCESS_CHECK(connection, message, "status");
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                state = unit_file_get_state(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
-                if (state < 0)
-                        return bus_send_error_reply(connection, message, NULL, state);
-
-                s = unit_file_state_to_string(state);
-                assert(s);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                if (!dbus_message_append_args(
-                                    reply,
-                                    DBUS_TYPE_STRING, &s,
-                                    DBUS_TYPE_INVALID))
-                        goto oom;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetDefaultTarget")) {
-
-                char **l = NULL;
-                DBusMessageIter iter;
-                UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
-                UnitFileChange *changes = NULL;
-                unsigned n_changes = 0;
-                dbus_bool_t runtime, force;
-                int carries_install_info = -1;
-
-                SELINUX_ACCESS_CHECK(connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
-
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
-
-                r = bus_parse_strv_iter(&iter, &l);
-                if (r < 0) {
-                        if (r == -ENOMEM)
-                                goto oom;
+        if (path_equal(root, "/") || !path_is_absolute(root))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
 
-                        return bus_send_error_reply(connection, message, NULL, r);
-                }
+        /* Safety check */
+        if (isempty(init)) {
+                if (! path_is_os_tree(root))
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. /etc/os-release is missing.", root);
+        } else {
+                _cleanup_free_ char *p = NULL;
 
-                if (!dbus_message_iter_next(&iter) ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
-                        strv_free(l);
-                        return bus_send_error_reply(connection, message, NULL, -EIO);
-                }
+                if (!path_is_absolute(init))
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
 
-                if (streq(member, "EnableUnitFiles")) {
-                        r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
-                        carries_install_info = r;
-                } else if (streq(member, "ReenableUnitFiles")) {
-                        r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
-                        carries_install_info = r;
-                } else if (streq(member, "LinkUnitFiles"))
-                        r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
-                else if (streq(member, "PresetUnitFiles")) {
-                        r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
-                        carries_install_info = r;
-                } else if (streq(member, "MaskUnitFiles"))
-                        r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
-                else if (streq(member, "SetDefaultTarget"))
-                        r = unit_file_set_default(scope, NULL, l[0], &changes, &n_changes);
-                else
-                        assert_not_reached("Uh? Wrong method");
-
-                strv_free(l);
-                bus_manager_send_unit_files_changed(m);
+                p = strappend(root, init);
+                if (!p)
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
-                if (r < 0) {
-                        unit_file_changes_free(changes, n_changes);
-                        return bus_send_error_reply(connection, message, NULL, r);
+                if (access(p, X_OK) < 0)
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
+        }
+
+        rt = strdup(root);
+        if (!rt)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
+
+        if (!isempty(init)) {
+                ri = strdup(init);
+                if (!ri) {
+                        free(ri);
+                        return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
                 }
+        }
 
-                reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
-                unit_file_changes_free(changes, n_changes);
+        free(m->switch_root);
+        m->switch_root = rt;
 
-                if (!reply)
-                        goto oom;
+        free(m->switch_root_init);
+        m->switch_root_init = ri;
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
-                   dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                char **l = NULL;
-                DBusMessageIter iter;
-                UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
-                UnitFileChange *changes = NULL;
-                unsigned n_changes = 0;
-                dbus_bool_t runtime;
+static int method_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_strv_free_ char **plus = NULL;
+        Manager *m = userdata;
+        int r;
 
-                SELINUX_ACCESS_CHECK(connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
 
-                r = bus_parse_strv_iter(&iter, &l);
-                if (r < 0) {
-                        if (r == -ENOMEM)
-                                goto oom;
+        r = sd_bus_message_read_strv(message, &plus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+        if (!strv_env_is_valid(plus))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
 
-                        return bus_send_error_reply(connection, message, NULL, r);
-                }
+        r = manager_environment_add(m, NULL, plus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_iter_next(&iter) ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
-                        strv_free(l);
-                        return bus_send_error_reply(connection, message, NULL, -EIO);
-                }
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
+
+static int method_unset_environment(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_strv_free_ char **minus = NULL;
+        Manager *m = userdata;
+        int r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
 
-                if (streq(member, "DisableUnitFiles"))
-                        r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
-                else if (streq(member, "UnmaskUnitFiles"))
-                        r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
-                else
-                        assert_not_reached("Uh? Wrong method");
+        r = sd_bus_message_read_strv(message, &minus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        if (!strv_env_name_or_assignment_is_valid(minus))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
+
+        r = manager_environment_add(m, minus, NULL);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
+
+static int method_unset_and_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
+        Manager *m = userdata;
+        int r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "reload");
+
+        r = sd_bus_message_read_strv(message, &plus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        r = sd_bus_message_read_strv(message, &minus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        if (!strv_env_is_valid(plus))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
+        if (!strv_env_name_or_assignment_is_valid(minus))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
+
+        r = manager_environment_add(m, minus, plus);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
+
+static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        Manager *m = userdata;
+        UnitFileList *item;
+        Hashmap *h;
+        Iterator i;
+        int r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "status");
+
+        r = sd_bus_message_new_method_return(bus, message, &reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                strv_free(l);
-                bus_manager_send_unit_files_changed(m);
+        h = hashmap_new(string_hash_func, string_compare_func);
+        if (!h)
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
+        r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
+        if (r < 0) {
+                r = sd_bus_reply_method_errno(bus, message, r, NULL);
+                goto fail;
+        }
+
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0) {
+                r = sd_bus_reply_method_errno(bus, message, r, NULL);
+                goto fail;
+        }
+
+        HASHMAP_FOREACH(item, h, i) {
+
+                r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
                 if (r < 0) {
-                        unit_file_changes_free(changes, n_changes);
-                        return bus_send_error_reply(connection, message, NULL, r);
+                        r = sd_bus_reply_method_errno(bus, message, r, NULL);
+                        goto fail;
                 }
+        }
 
-                reply = message_from_file_changes(message, changes, n_changes, -1);
-                unit_file_changes_free(changes, n_changes);
+        unit_file_list_free(h);
 
-                if (!reply)
-                        goto oom;
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetDefaultTarget")) {
-                UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
-                _cleanup_free_ char *default_target = NULL;
+        return sd_bus_send(bus, reply, NULL);
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+fail:
+        unit_file_list_free(h);
+        return r;
+}
 
-                r = unit_file_get_default(scope, NULL, &default_target);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
+static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *name;
+        UnitFileState state;
+        UnitFileScope scope;
+        int r;
 
-                if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_target, DBUS_TYPE_INVALID)) {
-                        goto oom;
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitProperties")) {
-                DBusMessageIter iter;
-                dbus_bool_t runtime;
-                const char *name;
-                Unit *u;
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true) < 0 ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
 
-                u = manager_get_unit(m, name);
-                if (!u) {
-                        dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-                }
+        state = unit_file_get_state(scope, NULL, name);
+        if (state < 0)
+                return sd_bus_reply_method_errno(bus, message, state, NULL);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+        return sd_bus_reply_method_return(bus, message, "s", unit_file_state_to_string(state));
+}
 
-                r = bus_unit_set_properties(u, &iter, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, &error);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartTransientUnit")) {
-                const char *name, *smode;
-                DBusMessageIter iter;
-                JobMode mode;
-                UnitType t;
-                Unit *u;
-
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
-
-                if (bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true) < 0 ||
-                    bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &smode, true) < 0)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-
-                t = unit_name_to_type(name);
-                if (t < 0)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
-                if (!unit_vtable[t]->can_transient) {
-                        dbus_set_error(&error, DBUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t));
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *default_target = NULL;
+        Manager *m = userdata;
+        UnitFileScope scope;
+        int r;
 
-                mode = job_mode_from_string(smode);
-                if (mode < 0) {
-                        dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                r = manager_load_unit(m, name, NULL, NULL, &u);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+        SELINUX_ACCESS_CHECK(bus, message, "status");
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
 
-                if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0) {
-                        dbus_set_error(&error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
-                        return bus_send_error_reply(connection, message, &error, -EEXIST);
-                }
+        r = unit_file_get_default(scope, NULL, &default_target);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                /* OK, the unit failed to load and is unreferenced,
-                 * now let's fill in the transient data instead */
-                r = unit_make_transient(u);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+        return sd_bus_reply_method_return(bus, message, "s", default_target);
+}
 
-                /* Set our properties */
-                r = bus_unit_set_properties(u, &iter, UNIT_RUNTIME, false, &error);
+static int send_unit_files_changed(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+        int r;
+
+        assert(bus);
+
+        r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged", &message);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, message, destination, NULL);
+}
+
+static int reply_unit_file_changes_and_free(
+                Manager *m,
+                sd_bus *bus,
+                sd_bus_message *message,
+                int carries_install_info,
+                UnitFileChange *changes,
+                unsigned n_changes) {
+
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        unsigned i;
+        int r;
+
+        if (n_changes > 0)
+                bus_manager_foreach_client(m, send_unit_files_changed, NULL);
+
+        r = sd_bus_message_new_method_return(bus, message, &reply);
+        if (r < 0)
+                goto fail;
+
+        if (carries_install_info >= 0) {
+                r = sd_bus_message_append(reply, "b", carries_install_info);
                 if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+                        goto fail;
+        }
+
+        r = sd_bus_message_open_container(reply, 'a', "(sss)");
+        if (r < 0)
+                goto fail;
 
-                /* And load this stub fully */
-                r = unit_load(u);
+        for (i = 0; i < n_changes; i++) {
+                r = sd_bus_message_append(
+                                message, "(sss)",
+                                unit_file_change_type_to_string(changes[i].type),
+                                changes[i].path,
+                                changes[i].source);
                 if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+                        goto fail;
+        }
 
-                manager_dispatch_load_queue(m);
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                goto fail;
 
-                /* Finally, start it */
-                return bus_unit_queue_job(connection, message, u, JOB_START, mode, false);
+        return sd_bus_send(bus, message, NULL);
 
-        } else {
-                const BusBoundProperties bps[] = {
-                        { "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
-                        { "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
-                        { NULL, }
-                };
+fail:
+        unit_file_changes_free(changes, n_changes);
+        return sd_bus_reply_method_errno(bus, message, r, NULL);
+}
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+static int method_enable_unit_files_generic(
+                sd_bus *bus,
+                sd_bus_message *message,
+                Manager *m, const
+                char *verb,
+                int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
+                bool carries_install_info) {
+
+        _cleanup_strv_free_ char **l = NULL;
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        UnitFileScope scope;
+        int runtime, force, r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
-        }
+        SELINUX_ACCESS_CHECK(bus, message, verb);
 
-        if (job_type != _JOB_TYPE_INVALID) {
-                const char *name, *smode, *old_name = NULL;
-                JobMode mode;
-                Unit *u;
-                dbus_bool_t b;
-
-                if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
-                        b = dbus_message_get_args(
-                                        message,
-                                        &error,
-                                        DBUS_TYPE_STRING, &old_name,
-                                        DBUS_TYPE_STRING, &name,
-                                        DBUS_TYPE_STRING, &smode,
-                                        DBUS_TYPE_INVALID);
-                else
-                        b = dbus_message_get_args(
-                                        message,
-                                        &error,
-                                        DBUS_TYPE_STRING, &name,
-                                        DBUS_TYPE_STRING, &smode,
-                                        DBUS_TYPE_INVALID);
-                if (!b)
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                if (old_name) {
-                        u = manager_get_unit(m, old_name);
-                        if (!u || !u->job || u->job->type != JOB_START) {
-                                dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
-                                return bus_send_error_reply(connection, message, &error, -ENOENT);
-                        }
-                }
+        r = sd_bus_message_read_strv(message, &l);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                mode = job_mode_from_string(smode);
-                if (mode < 0) {
-                        dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+        r = sd_bus_message_read(message, "bb", &runtime, &force);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                r = manager_load_unit(m, name, NULL, &error, &u);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
 
-                return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
-        }
+        r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return reply_unit_file_changes_and_free(m, bus, message, carries_install_info ? r : -1, changes, n_changes);
+}
 
-        if (reply)
-                if (!bus_maybe_send_reply(connection, message, reply))
-                        goto oom;
+static int method_enable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_enable, true);
+}
 
-        return DBUS_HANDLER_RESULT_HANDLED;
+static int method_reenable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_reenable, true);
+}
+
+static int method_link_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_link, false);
+}
+
+static int method_preset_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_preset, true);
+}
+
+static int method_mask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_enable_unit_files_generic(bus, message, userdata, "disable", unit_file_mask, false);
+}
 
-oom:
-        dbus_error_free(&error);
+static int method_disable_unit_files_generic(
+                sd_bus *bus,
+                sd_bus_message *message,
+                Manager *m, const
+                char *verb,
+                int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes)) {
+
+        _cleanup_strv_free_ char **l = NULL;
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        UnitFileScope scope;
+        int r, runtime;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, verb);
+
+        r = sd_bus_message_read_strv(message, &l);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        r = sd_bus_message_read(message, "b", &runtime);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+
+        r = call(scope, runtime, NULL, l, &changes, &n_changes);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
+}
 
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+static int method_disable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_disable_unit_files_generic(bus, message, userdata, "disable", unit_file_disable);
 }
 
-const DBusObjectPathVTable bus_manager_vtable = {
-        .message_function = bus_manager_message_handler
+static int method_unmask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return method_disable_unit_files_generic(bus, message, userdata, "enable", unit_file_unmask);
+}
+
+static int method_set_default_target(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        Manager *m = userdata;
+        UnitFileScope scope;
+        const char *name;
+        int force, r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        SELINUX_ACCESS_CHECK(bus, message, "enable");
+
+        r = sd_bus_message_read(message, "sb", &name, &force);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+
+        r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
+}
+
+const sd_bus_vtable bus_manager_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+
+        SD_BUS_PROPERTY("Version", "s", property_get_version, 0, 0),
+        SD_BUS_PROPERTY("Features", "s", property_get_features, 0, 0),
+        SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, 0),
+        SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, firmware_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), 0),
+        SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
+        SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
+        SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
+        SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
+        SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
+        SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
+        SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
+        SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
+        SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), 0),
+        SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), 0),
+        SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), 0),
+        SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
+        SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
+        SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
+        SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
+
+        SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, 0),
+        SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, 0),
+        SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, 0),
+        SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, 0),
+        SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, 0),
+        SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, 0),
+        SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, 0),
+        SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, 0),
+        SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, 0),
+        SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, 0),
+        SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, 0),
+        SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, 0),
+        SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, 0),
+        SD_BUS_METHOD("SetUnitProperties", "sb", "a(sv)", method_set_unit_properties, 0),
+        SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, 0),
+        SD_BUS_METHOD("GetJob", "u", "o", method_get_job, 0),
+        SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, 0),
+        SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0),
+        SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0),
+        SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, 0),
+        SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, 0),
+        SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, 0),
+        SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, 0),
+        SD_BUS_METHOD("Dump", NULL, "s", method_dump, 0),
+        SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),
+        SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),
+        SD_BUS_METHOD("Reload", NULL, NULL, method_reload, 0),
+        SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, 0),
+        SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
+        SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, 0),
+        SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, 0),
+        SD_BUS_METHOD("Halt", NULL, NULL, method_halt, 0),
+        SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, 0),
+        SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, 0),
+        SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, 0),
+        SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, 0),
+        SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, 0),
+        SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, 0),
+        SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, 0),
+        SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, 0),
+        SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, 0),
+        SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0),
+        SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, 0),
+        SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, 0),
+        SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0),
+        SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0),
+        SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0),
+        SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, 0),
+
+        SD_BUS_SIGNAL("UnitNew", "so", 0),
+        SD_BUS_SIGNAL("UnitRemoved", "so", 0),
+        SD_BUS_SIGNAL("JobNew", "uos", 0),
+        SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
+        SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
+        SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
+        SD_BUS_SIGNAL("Reloading", "b", 0),
+
+        SD_BUS_VTABLE_END
 };
+
+int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata) {
+        Iterator i;
+        sd_bus *b;
+        unsigned n;
+        int r;
+
+        n = set_size(m->subscribed);
+        if (n <= 0)
+                return 0;
+        if (n == 1) {
+                BusTrackedClient *d;
+
+                assert_se(d = set_first(m->subscribed));
+                return send_message(d->bus, isempty(d->name) ? NULL : d->name, userdata);
+        }
+
+        /* Send to everybody */
+        SET_FOREACH(b, m->private_buses, i) {
+                r = send_message(b, NULL, userdata);
+                if (r < 0)
+                        return r;
+        }
+
+        if (m->api_bus)
+                return send_message(m->api_bus, NULL, userdata);
+
+        return 0;
+}
+
+static int send_finished(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+        usec_t *times = userdata;
+        int r;
+
+        assert(bus);
+        assert(times);
+
+        r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished", &message);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, message, destination, NULL);
+}
+
+int bus_manager_send_finished(
+                Manager *m,
+                usec_t firmware_usec,
+                usec_t loader_usec,
+                usec_t kernel_usec,
+                usec_t initrd_usec,
+                usec_t userspace_usec,
+                usec_t total_usec) {
+
+        assert(m);
+
+        return bus_manager_foreach_client(m, send_finished,
+                        (usec_t[6]) { firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec });
+}
+
+static int send_reloading(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
+        int r;
+
+        assert(bus);
+
+        r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading", &message);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
+        if (r < 0)
+                return r;
+
+        return sd_bus_send_to(bus, message, destination, NULL);
+}
+
+int bus_manager_send_reloading(Manager *m, bool active) {
+        assert(m);
+
+        return bus_manager_foreach_client(m, send_reloading, INT_TO_PTR(active));
+}
index f0dce5a2e947ee040de37cf0dc0aa07d3081ba34..ad451eb6fd62760e534fc798c1de6e3cf68b61cd 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
+#include "manager.h"
 
-extern const DBusObjectPathVTable bus_manager_vtable;
+extern const sd_bus_vtable bus_manager_vtable[];
 
-extern const char bus_manager_interface[];
+int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata);
+
+int bus_manager_send_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec);
+int bus_manager_send_reloading(Manager *m, bool active);
index 70b2d48330072f352a9a10104afd4601b30f31f4..2056eab11e744a90953c89b27966abfca11c6196 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "mount.h"
 #include "dbus-unit.h"
 #include "dbus-execute.h"
 #include "dbus-kill.h"
 #include "dbus-cgroup.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 #include "dbus-mount.h"
-
-#define BUS_MOUNT_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Mount\">\n"        \
-        "  <property name=\"Where\" type=\"s\" access=\"read\"/>\n"     \
-        "  <property name=\"What\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Options\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"Type\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecMount")                         \
-        BUS_EXEC_COMMAND_INTERFACE("ExecUnmount")                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecRemount")                       \
-        BUS_EXEC_CONTEXT_INTERFACE                                      \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_MOUNT_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Mount\0"
-
-const char bus_mount_interface[] = BUS_MOUNT_INTERFACE;
-
-const char bus_mount_invalidating_properties[] =
-        "What\0"
-        "Options\0"
-        "Type\0"
-        "ExecMount\0"
-        "ExecUnmount\0"
-        "ExecRemount\0"
-        "ControlPID\0"
-        "Result\0";
-
-static int bus_mount_append_what(DBusMessageIter *i, const char *property, void *data) {
-        Mount *m = data;
+#include "bus-util.h"
+
+static int property_get_what(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Mount *m = userdata;
         const char *d;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what)
@@ -89,18 +51,23 @@ static int bus_mount_append_what(DBusMessageIter *i, const char *property, void
         else
                 d = "";
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", d);
 }
 
-static int bus_mount_append_options(DBusMessageIter *i, const char *property, void *data) {
-        Mount *m = data;
+static int property_get_options(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Mount *m = userdata;
         const char *d;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.options)
@@ -110,18 +77,23 @@ static int bus_mount_append_options(DBusMessageIter *i, const char *property, vo
         else
                 d = "";
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", d);
 }
 
-static int bus_mount_append_type(DBusMessageIter *i, const char *property, void *data) {
-        Mount *m = data;
+static int property_get_type(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Mount *m = userdata;
         const char *d;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(m);
 
         if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype)
@@ -131,66 +103,50 @@ static int bus_mount_append_type(DBusMessageIter *i, const char *property, void
         else
                 d = "";
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", d);
 }
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_mount_append_mount_result, mount_result, MountResult);
-
-static const BusProperty bus_mount_properties[] = {
-        { "Where",         bus_property_append_string, "s", offsetof(Mount, where),    true },
-        { "What",          bus_mount_append_what,      "s", 0 },
-        { "Options",       bus_mount_append_options,   "s", 0 },
-        { "Type",          bus_mount_append_type,      "s", 0 },
-        { "TimeoutUSec",   bus_property_append_usec,   "t", offsetof(Mount, timeout_usec)   },
-        BUS_EXEC_COMMAND_PROPERTY("ExecMount",   offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]),   false),
-        BUS_EXEC_COMMAND_PROPERTY("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), false),
-        BUS_EXEC_COMMAND_PROPERTY("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), false),
-        { "ControlPID",    bus_property_append_pid,    "u", offsetof(Mount, control_pid)    },
-        { "DirectoryMode", bus_property_append_mode,   "u", offsetof(Mount, directory_mode) },
-        { "Result",        bus_mount_append_mount_result, "s", offsetof(Mount, result)      },
-        { NULL, }
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResult);
+
+const sd_bus_vtable bus_mount_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Mount, where), 0),
+        SD_BUS_PROPERTY("What", "s", property_get_what, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Options","s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Type", "s", property_get_type, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Mount, timeout_usec), 0),
+        SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Mount, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), 0),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Mount *m = MOUNT(u);
-
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",  bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Mount", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Mount", bus_mount_properties,          m },
-                { "org.freedesktop.systemd1.Mount", bus_exec_context_properties,   &m->exec_context },
-                { "org.freedesktop.systemd1.Mount", bus_kill_context_properties,   &m->kill_context },
-                { "org.freedesktop.systemd1.Mount", bus_cgroup_context_properties, &m->cgroup_context },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps );
-}
+const char * const bus_mount_changing_properties[] = {
+        "What",
+        "Options",
+        "Type",
+        "ControlPID",
+        "Result",
+        NULL
+};
 
 int bus_mount_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Mount *m = MOUNT(u);
-        int r;
 
+        assert(m);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &m->cgroup_context, name, i, mode, error);
-        if (r != 0)
-                return r;
-
-        return 0;
+        return bus_cgroup_set_property(u, &m->cgroup_context, name, message, mode, error);
 }
 
 int bus_mount_commit_properties(Unit *u) {
index f4ec8b1625b78da7f62c289a38dc726bc915ba23..4bb5d2ddee10cd27afd8f2966b073858f878a6c0 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_mount_vtable[];
+extern const char * const bus_mount_changing_properties[];
 
-int bus_mount_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_mount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_mount_commit_properties(Unit *u);
-
-extern const char bus_mount_interface[];
-extern const char bus_mount_invalidating_properties[];
index a523b8144627b500307e19b6985dedde5a15dd7c..a206f490208baa570b6e82851453e6ae571a5728 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "path.h"
 #include "dbus-unit.h"
 #include "dbus-path.h"
-#include "dbus-execute.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_PATH_INTERFACE                                              \
-        " <interface name=\"org.freedesktop.systemd1.Path\">\n"         \
-        "  <property name=\"Unit\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Paths\" type=\"a(ss)\" access=\"read\"/>\n" \
-        "  <property name=\"MakeDirectory\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_PATH_INTERFACE                                              \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Path\0"
-
-const char bus_path_interface[] = BUS_PATH_INTERFACE;
-
-const char bus_path_invalidating_properties[] =
-        "Result\0";
-
-static int bus_path_append_paths(DBusMessageIter *i, const char *property, void *data) {
-        Path *p = data;
-        DBusMessageIter sub, sub2;
+#include "bus-util.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, path_result, PathResult);
+
+static int property_get_paths(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Path *p = userdata;
         PathSpec *k;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(p);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &sub))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(spec, k, p->specs) {
-                const char *t = path_type_to_string(k->type);
-
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &t) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &k->path) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(ss)", path_type_to_string(k->type), k->path);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_path_append_unit(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data, *trigger;
-        const char *t;
+static int property_get_unit(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
+        Unit *p = userdata, *trigger;
 
-        trigger = UNIT_TRIGGER(u);
-        t = trigger ? trigger->id : "";
+        assert(bus);
+        assert(reply);
+        assert(p);
 
-        return dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t) ? 0 : -ENOMEM;
-}
+        trigger = UNIT_TRIGGER(p);
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_path_append_path_result, path_result, PathResult);
+        return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
+}
 
-static const BusProperty bus_path_properties[] = {
-        { "Unit",          bus_path_append_unit,      "s", 0 },
-        { "Paths",         bus_path_append_paths, "a(ss)", 0 },
-        { "MakeDirectory", bus_property_append_bool,  "b", offsetof(Path, make_directory) },
-        { "DirectoryMode", bus_property_append_mode,  "u", offsetof(Path, directory_mode) },
-        { "Result",        bus_path_append_path_result, "s", offsetof(Path, result) },
-        { NULL, }
+const sd_bus_vtable bus_path_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, 0),
+        SD_BUS_PROPERTY("Paths", "a(ss)", property_get_paths, 0, 0),
+        SD_BUS_PROPERTY("MakeDirectory", "b", bus_property_get_bool, offsetof(Path, make_directory), 0),
+        SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Path, directory_mode), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Path, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_path_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Path *p = PATH(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
-                { "org.freedesktop.systemd1.Path", bus_path_properties, p },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_path_changing_properties[] = {
+        "Result",
+        NULL
+};
index c945f7d588bdeff86a7dc4128d20810b4ceb4299..e9558f81b50b2cb6c008816a08ed60c1247cc9ea 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
 
-#include "unit.h"
+#include "sd-bus.h"
 
-DBusHandlerResult bus_path_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_path_interface[];
-
-extern const char bus_path_invalidating_properties[];
+extern const sd_bus_vtable bus_path_vtable[];
+extern const char* const bus_path_changing_properties[];
index c790d26cfec7de91f2dc0fb3fb65f95c932dc5d9..13ff49d62f47943d1052d31ac4a1843b132efe64 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "scope.h"
 #include "dbus-unit.h"
-#include "dbus-common.h"
 #include "dbus-cgroup.h"
 #include "dbus-kill.h"
-#include "selinux-access.h"
 #include "dbus-scope.h"
+#include "bus-util.h"
 
-#define BUS_SCOPE_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Scope\">\n"        \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        "  <property name=\"TimeoutStopUSec\" type=\"t\" access=\"read\"/>\n" \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SCOPE_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Scope\0"
-
-const char bus_scope_interface[] = BUS_SCOPE_INTERFACE;
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_scope_append_scope_result, scope_result, ScopeResult);
-
-static const BusProperty bus_scope_properties[] = {
-        { "TimeoutStopUSec",        bus_property_append_usec,      "t", offsetof(Scope, timeout_stop_usec) },
-        { "Result",                 bus_scope_append_scope_result, "s", offsetof(Scope, result)            },
-        {}
-};
-
-DBusHandlerResult bus_scope_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Scope *s = SCOPE(u);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult);
 
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",  bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Scope", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Scope", bus_scope_properties,          s },
-                { "org.freedesktop.systemd1.Scope", bus_cgroup_context_properties, &s->cgroup_context },
-                { "org.freedesktop.systemd1.Scope", bus_kill_context_properties,   &s->kill_context   },
-                {}
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
+const sd_bus_vtable bus_scope_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
+};
 
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_scope_changing_properties[] = {
+        "Result",
+        NULL
+};
 
 static int bus_scope_set_transient_property(
                 Scope *s,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         int r;
 
-        assert(name);
         assert(s);
-        assert(i);
+        assert(name);
+        assert(message);
 
         if (streq(name, "PIDs")) {
-                DBusMessageIter sub;
                 unsigned n = 0;
-
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_UINT32)
-                        return -EINVAL;
+                uint32_t pid;
 
                 r = set_ensure_allocated(&s->pids, trivial_hash_func, trivial_compare_func);
                 if (r < 0)
                         return r;
 
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32) {
-                        uint32_t pid;
+                r = sd_bus_message_enter_container(message, 'a', "u");
+                if (r < 0)
+                        return r;
 
-                        dbus_message_iter_get_basic(&sub, &pid);
+                while ((r = sd_bus_message_read(message, "u", &pid)) > 0) {
 
                         if (pid <= 1)
                                 return -EINVAL;
@@ -118,9 +77,14 @@ static int bus_scope_set_transient_property(
                                         return r;
                         }
 
-                        dbus_message_iter_next(&sub);
                         n++;
                 }
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_exit_container(message);
+                if (r < 0)
+                        return r;
 
                 if (n <= 0)
                         return -EINVAL;
@@ -129,17 +93,16 @@ static int bus_scope_set_transient_property(
 
         } else if (streq(name, "TimeoutStopUSec")) {
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
-                        return -EINVAL;
-
                 if (mode != UNIT_CHECK) {
-                        uint64_t t;
-
-                        dbus_message_iter_get_basic(i, &t);
-
-                        s->timeout_stop_usec = t;
-
-                        unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec=%lluus\n", (unsigned long long) t);
+                        r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
+                        if (r < 0)
+                                return r;
+
+                        unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec=%lluus\n", (unsigned long long) s->timeout_stop_usec);
+                } else {
+                        r = sd_bus_message_skip(message, "t");
+                        if (r < 0)
+                                return r;
                 }
 
                 return 1;
@@ -151,29 +114,29 @@ static int bus_scope_set_transient_property(
 int bus_scope_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Scope *s = SCOPE(u);
         int r;
 
+        assert(s);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
+        r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
         if (r != 0)
                 return r;
 
         if (u->load_state == UNIT_STUB) {
                 /* While we are created we still accept PIDs */
 
-                r = bus_scope_set_transient_property(s, name, i, mode, error);
+                r = bus_scope_set_transient_property(s, name, message, mode, error);
                 if (r != 0)
                         return r;
 
-                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, i, mode, error);
+                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
                 if (r != 0)
                         return r;
         }
index e6836f13f00cd73a4ef5901a04935371a9210398..30c5e1e0a79efdb740ebfa14385bbcd81ae489b4 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_scope_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_scope_vtable[];
+extern const char* const bus_scope_changing_properties[];
 
-int bus_scope_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_scope_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_scope_commit_properties(Unit *u);
-
-extern const char bus_scope_interface[];
index c888570c4b9f9653c14d169d58e24ebc714425ae..c4bfa2c38f42f7434ee3f6a2da749fab7b412858 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
 #include "strv.h"
 #include "path-util.h"
+#include "unit.h"
+#include "service.h"
 #include "dbus-unit.h"
 #include "dbus-execute.h"
 #include "dbus-kill.h"
 #include "dbus-cgroup.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 #include "dbus-service.h"
-
-#define BUS_SERVICE_INTERFACE                                           \
-        " <interface name=\"org.freedesktop.systemd1.Service\">\n"      \
-        "  <property name=\"Type\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Restart\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"PIDFile\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"NotifyAccess\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"RestartUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"TimeoutStartUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"TimeoutStopUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"WatchdogUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"WatchdogTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"WatchdogTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"StartLimitInterval\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"StartLimitBurst\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"StartLimitAction\" type=\"s\" access=\"readwrite\"/>\n" \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStartPre")                      \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStart")                         \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStartPost")                     \
-        BUS_EXEC_COMMAND_INTERFACE("ExecReload")                        \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStop")                          \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStopPost")                      \
-        BUS_EXEC_CONTEXT_INTERFACE                                      \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"PermissionsStartOnly\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"RootDirectoryStartOnly\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"RemainAfterExit\" type=\"b\" access=\"read\"/>\n" \
-        BUS_EXEC_STATUS_INTERFACE("ExecMain")                           \
-        "  <property name=\"MainPID\" type=\"u\" access=\"read\"/>\n"   \
-        "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"BusName\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"StatusText\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-       " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SERVICE_INTERFACE                                           \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Service\0"
-
-const char bus_service_interface[] = BUS_SERVICE_INTERFACE;
-
-const char bus_service_invalidating_properties[] =
-        "ExecStartPre\0"
-        "ExecStart\0"
-        "ExecStartPost\0"
-        "ExecReload\0"
-        "ExecStop\0"
-        "ExecStopPost\0"
-        "ExecMain\0"
-        "WatchdogTimestamp\0"
-        "WatchdogTimestampMonotonic\0"
-        "MainPID\0"
-        "ControlPID\0"
-        "StatusText\0"
-        "Result\0";
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_type, service_type, ServiceType);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_restart, service_restart, ServiceRestart);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_notify_access, notify_access, NotifyAccess);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_service_result, service_result, ServiceResult);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_start_limit_action, start_limit_action, StartLimitAction);
-static DEFINE_BUS_PROPERTY_SET_ENUM(bus_service_set_start_limit_action, start_limit_action, StartLimitAction);
-
-static const BusProperty bus_exec_main_status_properties[] = {
-        { "ExecMainStartTimestamp",         bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.realtime)  },
-        { "ExecMainStartTimestampMonotonic",bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.monotonic) },
-        { "ExecMainExitTimestamp",          bus_property_append_usec, "t", offsetof(ExecStatus, exit_timestamp.realtime)   },
-        { "ExecMainExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(ExecStatus, exit_timestamp.monotonic)  },
-        { "ExecMainPID",                    bus_property_append_pid,  "u", offsetof(ExecStatus, pid)                       },
-        { "ExecMainCode",                   bus_property_append_int,  "i", offsetof(ExecStatus, code)                      },
-        { "ExecMainStatus",                 bus_property_append_int,  "i", offsetof(ExecStatus, status)                    },
-        {}
+#include "bus-util.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_start_limit_action, start_limit_action, StartLimitAction);
+
+const sd_bus_vtable bus_service_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), 0),
+        SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), 0),
+        SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), 0),
+        SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), 0),
+        SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), 0),
+        SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), 0),
+        SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), 0),
+        SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
+        SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), 0),
+        SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), 0),
+        SD_BUS_PROPERTY("StartLimitAction", "s", property_get_start_limit_action, offsetof(Service, start_limit_action), 0),
+        SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), 0),
+        SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), 0),
+        SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), 0),
+        SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), 0),
+        SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), 0),
+        SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_EXEC_COMMAND_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), 0),
+        SD_BUS_VTABLE_END
 };
 
-static const BusProperty bus_service_properties[] = {
-        { "Type",                   bus_service_append_type,          "s", offsetof(Service, type)                         },
-        { "Restart",                bus_service_append_restart,       "s", offsetof(Service, restart)                      },
-        { "PIDFile",                bus_property_append_string,       "s", offsetof(Service, pid_file),               true },
-        { "NotifyAccess",           bus_service_append_notify_access, "s", offsetof(Service, notify_access)                },
-        { "RestartUSec",            bus_property_append_usec,         "t", offsetof(Service, restart_usec)                 },
-        { "TimeoutStartUSec",       bus_property_append_usec,         "t", offsetof(Service, timeout_start_usec)           },
-        { "TimeoutStopUSec",        bus_property_append_usec,         "t", offsetof(Service, timeout_stop_usec)            },
-        { "WatchdogUSec",           bus_property_append_usec,         "t", offsetof(Service, watchdog_usec)                },
-        { "WatchdogTimestamp",      bus_property_append_usec,         "t", offsetof(Service, watchdog_timestamp.realtime)  },
-        { "WatchdogTimestampMonotonic",bus_property_append_usec,      "t", offsetof(Service, watchdog_timestamp.monotonic) },
-        { "StartLimitInterval",     bus_property_append_usec,         "t", offsetof(Service, start_limit.interval)         },
-        { "StartLimitBurst",        bus_property_append_uint32,       "u", offsetof(Service, start_limit.burst)            },
-        { "StartLimitAction",       bus_service_append_start_limit_action,"s", offsetof(Service, start_limit_action), false, bus_service_set_start_limit_action},
-        BUS_EXEC_COMMAND_PROPERTY("ExecStartPre",  offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]),  true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStart",     offsetof(Service, exec_command[SERVICE_EXEC_START]),      true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecReload",    offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]),     true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStop",      offsetof(Service, exec_command[SERVICE_EXEC_STOP]),       true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStopPost",  offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]),  true ),
-        { "PermissionsStartOnly",   bus_property_append_bool,         "b", offsetof(Service, permissions_start_only)       },
-        { "RootDirectoryStartOnly", bus_property_append_bool,         "b", offsetof(Service, root_directory_start_only)    },
-        { "RemainAfterExit",        bus_property_append_bool,         "b", offsetof(Service, remain_after_exit)            },
-        { "GuessMainPID",           bus_property_append_bool,         "b", offsetof(Service, guess_main_pid)               },
-        { "MainPID",                bus_property_append_pid,          "u", offsetof(Service, main_pid)                     },
-        { "ControlPID",             bus_property_append_pid,          "u", offsetof(Service, control_pid)                  },
-        { "BusName",                bus_property_append_string,       "s", offsetof(Service, bus_name),               true },
-        { "StatusText",             bus_property_append_string,       "s", offsetof(Service, status_text),            true },
-        { "Result",                 bus_service_append_service_result,"s", offsetof(Service, result)                       },
-        {}
+const char* const bus_service_changing_properties[] = {
+        "ExecMainStartTimestamp",
+        "ExecMainStartTimestampMonotonic",
+        "ExecMainExitTimestamp",
+        "ExecMainExitTimestampMonotonic",
+        "ExecMainPID",
+        "ExecMainCode",
+        "ExecMainStatus",
+        "MainPID",
+        "ControlPID",
+        "StatusText",
+        "Result",
+        NULL
 };
 
-DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connection, DBusMessage *message) {
-        Service *s = SERVICE(u);
-
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",    bus_unit_properties,             u },
-                { "org.freedesktop.systemd1.Service", bus_unit_cgroup_properties,      u },
-                { "org.freedesktop.systemd1.Service", bus_service_properties,          s },
-                { "org.freedesktop.systemd1.Service", bus_exec_context_properties,     &s->exec_context },
-                { "org.freedesktop.systemd1.Service", bus_kill_context_properties,     &s->kill_context },
-                { "org.freedesktop.systemd1.Service", bus_cgroup_context_properties,   &s->cgroup_context },
-                { "org.freedesktop.systemd1.Service", bus_exec_main_status_properties, &s->main_exec_status },
-                {}
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
-
-        return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
-
 static int bus_service_set_transient_property(
                 Service *s,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         int r;
 
-        assert(name);
         assert(s);
-        assert(i);
+        assert(name);
+        assert(message);
 
         if (streq(name, "RemainAfterExit")) {
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
-                        return -EINVAL;
+                int b;
 
-                if (mode != UNIT_CHECK) {
-                        dbus_bool_t b;
-
-                        dbus_message_iter_get_basic(i, &b);
+                r = sd_bus_message_read(message, "b", &b);
+                if (r < 0)
+                        return r;
 
+                if (mode != UNIT_CHECK) {
                         s->remain_after_exit = b;
                         unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
                 }
@@ -196,38 +112,35 @@ static int bus_service_set_transient_property(
                 return 1;
 
         } else if (streq(name, "ExecStart")) {
-                DBusMessageIter sub;
                 unsigned n = 0;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT)
-                        return -EINVAL;
+                r = sd_bus_message_enter_container(message, 'a', "(sasb)");
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+                while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
                         _cleanup_strv_free_ char **argv = NULL;
-                        DBusMessageIter sub2;
-                        dbus_bool_t ignore;
                         const char *path;
+                        int b;
 
-                        dbus_message_iter_recurse(&sub, &sub2);
-
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
-                                return -EINVAL;
+                        r = sd_bus_message_read(message, "s", &path);
+                        if (r < 0)
+                                return r;
 
-                        if (!path_is_absolute(path)) {
-                                dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
-                                return -EINVAL;
-                        }
+                        if (!path_is_absolute(path))
+                                return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
 
-                        r = bus_parse_strv_iter(&sub2, &argv);
+                        r = sd_bus_message_read_strv(message, &argv);
                         if (r < 0)
                                 return r;
 
-                        dbus_message_iter_next(&sub2);
+                        r = sd_bus_message_read(message, "b", &b);
+                        if (r < 0)
+                                return r;
 
-                        if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) < 0)
-                                return -EINVAL;
+                        r = sd_bus_message_exit_container(message);
+                        if (r < 0)
+                                return r;
 
                         if (mode != UNIT_CHECK) {
                                 ExecCommand *c;
@@ -245,15 +158,16 @@ static int bus_service_set_transient_property(
                                 c->argv = argv;
                                 argv = NULL;
 
-                                c->ignore = ignore;
+                                c->ignore = b;
 
                                 path_kill_slashes(c->path);
                                 exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
                         }
 
                         n++;
-                        dbus_message_iter_next(&sub);
                 }
+                if (r < 0)
+                        return r;
 
                 if (mode != UNIT_CHECK) {
                         _cleanup_free_ char *buf = NULL;
@@ -298,29 +212,29 @@ static int bus_service_set_transient_property(
 int bus_service_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Service *s = SERVICE(u);
         int r;
 
+        assert(s);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
+        r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
         if (r != 0)
                 return r;
 
         if (u->transient && u->load_state == UNIT_STUB) {
                 /* This is a transient unit, let's load a little more */
 
-                r = bus_service_set_transient_property(s, name, i, mode, error);
+                r = bus_service_set_transient_property(s, name, message, mode, error);
                 if (r != 0)
                         return r;
 
-                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, i, mode, error);
+                r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
                 if (r != 0)
                         return r;
         }
index 9b9f13701cafa72bb93ce8219d2a447572920edd..5fa9b2f139d7fd1e5faac1b241589903ef5bab07 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_service_vtable[];
+extern const char* const bus_service_changing_properties[];
 
-int bus_service_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_service_commit_properties(Unit *u);
-
-extern const char bus_service_interface[];
-extern const char bus_service_invalidating_properties[];
index eeefcdbcd6a066adf8c4107ac2a11fe4d165a0a9..2a48ea455e0cfc3aed8f522a350eca67f566ad04 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "slice.h"
 #include "dbus-unit.h"
-#include "dbus-common.h"
 #include "dbus-cgroup.h"
-#include "selinux-access.h"
 #include "dbus-slice.h"
 
-#define BUS_SLICE_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Slice\">\n"        \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SLICE_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Slice\0"
-
-const char bus_slice_interface[] = BUS_SLICE_INTERFACE;
-
-DBusHandlerResult bus_slice_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Slice *s = SLICE(u);
-
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",  bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Slice", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Slice", bus_cgroup_context_properties, &s->cgroup_context },
-                {}
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const sd_bus_vtable bus_slice_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_VTABLE_END
+};
 
 int bus_slice_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Slice *s = SLICE(u);
-        int r;
 
         assert(name);
         assert(u);
-        assert(i);
-
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
-        if (r != 0)
-                return r;
 
-        return 0;
+        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
 }
 
 int bus_slice_commit_properties(Unit *u) {
index c5ac473763e46d0d4791eb9416a8855dfa1489e9..eadc3b1a9cb2d3998682d5dfb70726d8981f530b 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_slice_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_slice_vtable[];
 
-int bus_slice_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_slice_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_slice_commit_properties(Unit *u);
-
-extern const char bus_slice_interface[];
index 9978df60225fee863f259bbf2ddefb20a35497e9..a4ba588a1d88004145996ceed0ebd683b5764f5e 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include "selinux-access.h"
+#include "unit.h"
+#include "snapshot.h"
 #include "dbus-unit.h"
 #include "dbus-snapshot.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_SNAPSHOT_INTERFACE                                          \
-        " <interface name=\"org.freedesktop.systemd1.Snapshot\">\n"     \
-        "  <method name=\"Remove\"/>\n"                                 \
-        "  <property name=\"Cleanup\" type=\"b\" access=\"read\"/>\n"   \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SNAPSHOT_INTERFACE                                          \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Snapshot\0"
-
-const char bus_snapshot_interface[] = BUS_SNAPSHOT_INTERFACE;
-
-static const BusProperty bus_snapshot_properties[] = {
-        { "Cleanup", bus_property_append_bool, "b", offsetof(Snapshot, cleanup) },
-        { NULL, }
-};
 
-DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Snapshot *s = SNAPSHOT(u);
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+int bus_snapshot_method_remove(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Snapshot *s = userdata;
 
-        if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Snapshot", "Remove")) {
+        assert(bus);
+        assert(message);
+        assert(s);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, c, message, "stop");
+        SELINUX_UNIT_ACCESS_CHECK(UNIT(s), bus, message, "stop");
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        snapshot_remove(s);
 
-                snapshot_remove(SNAPSHOT(u));
-
-        } else {
-                const BusBoundProperties bps[] = {
-                        { "org.freedesktop.systemd1.Unit",     bus_unit_properties,     u },
-                        { "org.freedesktop.systemd1.Snapshot", bus_snapshot_properties, s },
-                        { NULL, }
-                };
-
-                SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-                return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-        }
-
-        if (!bus_maybe_send_reply(c, message, reply))
-                return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
-        return DBUS_HANDLER_RESULT_HANDLED;
+        return sd_bus_reply_method_return(bus, message, NULL);
 }
+
+const sd_bus_vtable bus_snapshot_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_METHOD("Remove", NULL, NULL, bus_snapshot_method_remove, 0),
+        SD_BUS_PROPERTY("Cleanup", "b", bus_property_get_bool, offsetof(Snapshot, cleanup), 0),
+        SD_BUS_VTABLE_END
+};
index 1208aafff637cf44d7b56100ca2e5257683c4546..f6f432240d05bae2a0109cbd89b5b8bdefde9faa 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
 
-#include "unit.h"
+extern const sd_bus_vtable bus_snapshot_vtable[];
 
-DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_snapshot_interface[];
+int bus_snapshot_method_remove(sd_bus *bus, sd_bus_message *message, void *userdata);
index 60a8d0501c4feeb44dbe962201c4f84e8e8352ee..e9fa24d1a3f6f0049c982b2d8b6d3f348c815725 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "socket.h"
 #include "dbus-unit.h"
 #include "dbus-execute.h"
 #include "dbus-kill.h"
 #include "dbus-cgroup.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 #include "dbus-socket.h"
+#include "bus-util.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
+
+static int property_get_listen(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-#define BUS_SOCKET_INTERFACE                                            \
-        " <interface name=\"org.freedesktop.systemd1.Socket\">\n"       \
-        "  <property name=\"BindIPv6Only\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Backlog\" type=\"u\" access=\"read\"/>\n"   \
-        "  <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStartPre")                      \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStartPost")                     \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStopPre")                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecStopPost")                      \
-        BUS_EXEC_CONTEXT_INTERFACE                                      \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"BindToDevice\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Accept\" type=\"b\" access=\"read\"/>\n"    \
-        "  <property name=\"KeepAlive\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Priority\" type=\"i\" access=\"read\"/>\n"  \
-        "  <property name=\"ReceiveBuffer\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"SendBuffer\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"IPTOS\" type=\"i\" access=\"read\"/>\n"     \
-        "  <property name=\"IPTTL\" type=\"i\" access=\"read\"/>\n"     \
-        "  <property name=\"PipeSize\" type=\"t\" access=\"read\"/>\n"  \
-        "  <property name=\"FreeBind\" type=\"b\" access=\"read\"/>\n"  \
-        "  <property name=\"Transparent\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Broadcast\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"PassCredentials\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"PassSecurity\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Mark\" type=\"i\" access=\"read\"/>\n"      \
-        "  <property name=\"MaxConnections\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"NAccepted\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"NConnections\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"MessageQueueMaxMessages\" type=\"x\" access=\"read\"/>\n" \
-        "  <property name=\"MessageQueueMessageSize\" type=\"x\" access=\"read\"/>\n" \
-        "  <property name=\"Listen\" type=\"a(ss)\" access=\"read\"/>\n"    \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        "  <property name=\"ReusePort\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"SmackLabel\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SmackLabelIPIn\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SmackLabelIPOut\" type=\"s\" access=\"read\"/>\n" \
-        " </interface>\n"                                               \
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SOCKET_INTERFACE                                            \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Socket\0"
-
-const char bus_socket_interface[] = BUS_SOCKET_INTERFACE;
-
-const char bus_socket_invalidating_properties[] =
-        "ExecStartPre\0"
-        "ExecStartPost\0"
-        "ExecStopPre\0"
-        "ExecStopPost\0"
-        "ControlPID\0"
-        "NAccepted\0"
-        "NConnections\0"
-        "Result\0";
-
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_socket_result, socket_result, SocketResult);
-
-static int bus_socket_append_listen(DBusMessageIter *i, const char *property, void *data) {
-
-        Socket *s = SOCKET(data);
+
+        Socket *s = SOCKET(userdata);
         SocketPort *p;
-        DBusMessageIter array, stru;
+        int r;
 
-        assert(data);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(s);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &array))
-                return log_oom();
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0)
+                return r;
 
         LIST_FOREACH(port, p, s->ports) {
-                const char *type = socket_port_type_to_string(p);
                 _cleanup_free_ char *address = NULL;
                 const char *a;
 
-                if (!dbus_message_iter_open_container(&array, DBUS_TYPE_STRUCT, NULL, &stru))
-                        return log_oom();
-
-                if (!dbus_message_iter_append_basic(&stru, DBUS_TYPE_STRING, &type))
-                        return log_oom();
-
                 switch (p->type) {
                         case SOCKET_SOCKET: {
-                                int r;
-
                                 r = socket_address_print(&p->address, &address);
-                                if (r) {
-                                        log_error("socket_address_print failed: %s", strerror(-r));
+                                if (r)
                                         return r;
-                                }
+
                                 a = address;
                                 break;
                         }
@@ -146,98 +74,80 @@ static int bus_socket_append_listen(DBusMessageIter *i, const char *property, vo
                                 break;
 
                         default:
-                                a = type;
+                                assert_not_reached("Unknown socket type");
                 }
 
-                if (!dbus_message_iter_append_basic(&stru, DBUS_TYPE_STRING, &a))
-                        return -ENOMEM;
-
-                if (!dbus_message_iter_close_container(&array, &stru))
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(ss)", socket_port_type_to_string(p), a);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &array))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static const BusProperty bus_socket_properties[] = {
-        { "BindIPv6Only",   bus_socket_append_bind_ipv6_only,  "s", offsetof(Socket, bind_ipv6_only)  },
-        { "Backlog",        bus_property_append_unsigned,      "u", offsetof(Socket, backlog)         },
-        { "TimeoutUSec",    bus_property_append_usec,          "t", offsetof(Socket, timeout_usec)    },
-        BUS_EXEC_COMMAND_PROPERTY("ExecStartPre",  offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]),  true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStopPre",   offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]),   true ),
-        BUS_EXEC_COMMAND_PROPERTY("ExecStopPost",  offsetof(Socket, exec_command[SOCKET_EXEC_STOP_POST]),  true ),
-        { "ControlPID",     bus_property_append_pid,           "u", offsetof(Socket, control_pid)     },
-        { "BindToDevice",   bus_property_append_string,        "s", offsetof(Socket, bind_to_device), true },
-        { "DirectoryMode",  bus_property_append_mode,          "u", offsetof(Socket, directory_mode)  },
-        { "SocketMode",     bus_property_append_mode,          "u", offsetof(Socket, socket_mode)     },
-        { "Accept",         bus_property_append_bool,          "b", offsetof(Socket, accept)          },
-        { "KeepAlive",      bus_property_append_bool,          "b", offsetof(Socket, keep_alive)      },
-        { "Priority",       bus_property_append_int,           "i", offsetof(Socket, priority)        },
-        { "ReceiveBuffer",  bus_property_append_size,          "t", offsetof(Socket, receive_buffer)  },
-        { "SendBuffer",     bus_property_append_size,          "t", offsetof(Socket, send_buffer)     },
-        { "IPTOS",          bus_property_append_int,           "i", offsetof(Socket, ip_tos)          },
-        { "IPTTL",          bus_property_append_int,           "i", offsetof(Socket, ip_ttl)          },
-        { "PipeSize",       bus_property_append_size,          "t", offsetof(Socket, pipe_size)       },
-        { "FreeBind",       bus_property_append_bool,          "b", offsetof(Socket, free_bind)       },
-        { "Transparent",    bus_property_append_bool,          "b", offsetof(Socket, transparent)     },
-        { "Broadcast",      bus_property_append_bool,          "b", offsetof(Socket, broadcast)       },
-        { "PassCredentials",bus_property_append_bool,          "b", offsetof(Socket, pass_cred)       },
-        { "PassSecurity",   bus_property_append_bool,          "b", offsetof(Socket, pass_sec)        },
-        { "Listen",         bus_socket_append_listen,      "a(ss)", 0,                                },
-        { "Mark",           bus_property_append_int,           "i", offsetof(Socket, mark)            },
-        { "MaxConnections", bus_property_append_unsigned,      "u", offsetof(Socket, max_connections) },
-        { "NConnections",   bus_property_append_unsigned,      "u", offsetof(Socket, n_connections)   },
-        { "NAccepted",      bus_property_append_unsigned,      "u", offsetof(Socket, n_accepted)      },
-        { "MessageQueueMaxMessages", bus_property_append_long, "x", offsetof(Socket, mq_maxmsg)       },
-        { "MessageQueueMessageSize", bus_property_append_long, "x", offsetof(Socket, mq_msgsize)      },
-        { "Result",         bus_socket_append_socket_result,   "s", offsetof(Socket, result)          },
-        { "ReusePort",      bus_property_append_bool,          "b", offsetof(Socket, reuseport)       },
-        { "SmackLabel",     bus_property_append_string,        "s", offsetof(Socket, smack),          true },
-        { "SmackLabelIPIn", bus_property_append_string,        "s", offsetof(Socket, smack_ip_in),    true },
-        { "SmackLabelIPOut",bus_property_append_string,        "s", offsetof(Socket, smack_ip_out),   true },
-        {}
+const sd_bus_vtable bus_socket_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("BindIPv6Only", "s", property_get_bind_ipv6_only, offsetof(Socket, bind_ipv6_only), 0),
+        SD_BUS_PROPERTY("Backlog", "u", bus_property_get_unsigned, offsetof(Socket, backlog), 0),
+        SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Socket, timeout_usec), 0),
+        SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Socket, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("BindToDevice", "s", NULL, offsetof(Socket, bind_to_device), 0),
+        SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Socket, directory_mode), 0),
+        SD_BUS_PROPERTY("SocketMode", "u", bus_property_get_mode, offsetof(Socket, socket_mode), 0),
+        SD_BUS_PROPERTY("Accept", "b", bus_property_get_bool, offsetof(Socket, accept), 0),
+        SD_BUS_PROPERTY("KeepAlive", "b", bus_property_get_bool, offsetof(Socket, keep_alive), 0),
+        SD_BUS_PROPERTY("Priority", "i", bus_property_get_int, offsetof(Socket, priority), 0),
+        SD_BUS_PROPERTY("ReceiveBuffer", "t", bus_property_get_size, offsetof(Socket, receive_buffer), 0),
+        SD_BUS_PROPERTY("SendBuffer", "t", bus_property_get_size, offsetof(Socket, send_buffer), 0),
+        SD_BUS_PROPERTY("IPTOS", "i", bus_property_get_int, offsetof(Socket, ip_tos), 0),
+        SD_BUS_PROPERTY("IPTTL", "i", bus_property_get_int, offsetof(Socket, ip_ttl), 0),
+        SD_BUS_PROPERTY("PipeSize", "t", bus_property_get_size, offsetof(Socket, pipe_size), 0),
+        SD_BUS_PROPERTY("FreeBind", "b", bus_property_get_bool, offsetof(Socket, free_bind), 0),
+        SD_BUS_PROPERTY("Transparent", "b", bus_property_get_bool, offsetof(Socket, transparent), 0),
+        SD_BUS_PROPERTY("Broadcast", "b", bus_property_get_bool, offsetof(Socket, broadcast), 0),
+        SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), 0),
+        SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), 0),
+        SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, 0),
+        SD_BUS_PROPERTY("Mark", "i", bus_property_get_int, offsetof(Socket, mark), 0),
+        SD_BUS_PROPERTY("MaxConnections", "u", bus_property_get_unsigned, offsetof(Socket, max_connections), 0),
+        SD_BUS_PROPERTY("NConnections", "u", bus_property_get_unsigned, offsetof(Socket, n_connections), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("NAccepted", "u", bus_property_get_unsigned, offsetof(Socket, n_accepted), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("MessageQueueMaxMessages", "x", bus_property_get_long, offsetof(Socket, mq_maxmsg), 0),
+        SD_BUS_PROPERTY("MessageQueueMessageSize", "x", bus_property_get_long, offsetof(Socket, mq_msgsize), 0),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("ReusePort", "b",  bus_property_get_bool, offsetof(Socket, reuse_port), 0),
+        SD_BUS_PROPERTY("SmackLabel", "s", NULL, offsetof(Socket, smack), 0),
+        SD_BUS_PROPERTY("SmackLabelIPIn", "s", NULL, offsetof(Socket, smack_ip_in), 0),
+        SD_BUS_PROPERTY("SmackLabelIPOut", "s", NULL, offsetof(Socket, smack_ip_out), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecStopPost", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_POST]), 0),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Socket *s = SOCKET(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",   bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Socket", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Socket", bus_socket_properties,         s },
-                { "org.freedesktop.systemd1.Socket", bus_exec_context_properties,   &s->exec_context },
-                { "org.freedesktop.systemd1.Socket", bus_kill_context_properties,   &s->kill_context },
-                { "org.freedesktop.systemd1.Socket", bus_cgroup_context_properties, &s->cgroup_context },
-                {}
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_socket_changing_properties[] = {
+        "ControlPID",
+        "NAccepted",
+        "NConnections",
+        "Result",
+        NULL
+};
 
 int bus_socket_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Socket *s = SOCKET(u);
-        int r;
 
+        assert(s);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
-        if (r != 0)
-                return r;
-
-        return 0;
+        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
 }
 
 int bus_socket_commit_properties(Unit *u) {
index eb035c1a9440de02e37ee123addbdabd4469e9c4..8808fa235502245895e8d07f115094b6074423b5 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_socket_vtable[];
+extern const char* const bus_socket_changing_properties[];
 
-int bus_socket_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_socket_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_socket_commit_properties(Unit *u);
-
-extern const char bus_socket_interface[];
-extern const char bus_socket_invalidating_properties[];
index 0da86bd6fae447ae27195885b7ddc1d6762c90f1..15292cd192930d05f4cdd53d1d7c87316cb2a665 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "swap.h"
 #include "dbus-unit.h"
 #include "dbus-execute.h"
 #include "dbus-kill.h"
 #include "dbus-cgroup.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
 #include "dbus-swap.h"
-
-#define BUS_SWAP_INTERFACE                                              \
-        " <interface name=\"org.freedesktop.systemd1.Swap\">\n"         \
-        "  <property name=\"What\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Priority\" type=\"i\" access=\"read\"/>\n"  \
-        "  <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
-        BUS_UNIT_CGROUP_INTERFACE                                       \
-        BUS_EXEC_COMMAND_INTERFACE("ExecActivate")                      \
-        BUS_EXEC_COMMAND_INTERFACE("ExecDeactivate")                    \
-        BUS_EXEC_CONTEXT_INTERFACE                                      \
-        BUS_KILL_CONTEXT_INTERFACE                                      \
-        BUS_CGROUP_CONTEXT_INTERFACE                                    \
-        "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_SWAP_INTERFACE                                              \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Swap\0"
-
-const char bus_swap_interface[] = BUS_SWAP_INTERFACE;
-
-const char bus_swap_invalidating_properties[] =
-        "What\0"
-        "Priority\0"
-        "ExecActivate\0"
-        "ExecDeactivate\0"
-        "ControlPID\0"
-        "Result\0";
-
-static int bus_swap_append_priority(DBusMessageIter *i, const char *property, void *data) {
-        Swap *s = data;
-        dbus_int32_t j;
-
-        assert(i);
-        assert(property);
+#include "bus-util.h"
+
+static int property_get_priority(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Swap *s = SWAP(userdata);
+        int p;
+
+        assert(bus);
+        assert(reply);
         assert(s);
 
         if (s->from_proc_swaps)
-                j = s->parameters_proc_swaps.priority;
+                p = s->parameters_proc_swaps.priority;
         else if (s->from_fragment)
-                j = s->parameters_fragment.priority;
+                p = s->parameters_fragment.priority;
         else
-                j = -1;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &j))
-                return -ENOMEM;
+                p = -1;
 
-        return 0;
+        return sd_bus_message_append(reply, "i", p);
 }
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_swap_append_swap_result, swap_result, SwapResult);
-
-static const BusProperty bus_swap_properties[] = {
-        { "What",       bus_property_append_string, "s", offsetof(Swap, what),  true },
-        { "Priority",   bus_swap_append_priority,   "i", 0 },
-        { "TimeoutUSec",bus_property_append_usec,   "t", offsetof(Swap, timeout_usec)},
-        BUS_EXEC_COMMAND_PROPERTY("ExecActivate",   offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]),   false),
-        BUS_EXEC_COMMAND_PROPERTY("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), false),
-        { "ControlPID", bus_property_append_pid,    "u", offsetof(Swap, control_pid) },
-        { "Result",     bus_swap_append_swap_result,"s", offsetof(Swap, result)      },
-        { NULL, }
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, swap_result, SwapResult);
+
+const sd_bus_vtable bus_swap_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("What", "s", NULL, offsetof(Swap, what), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Priority", "i", property_get_priority, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Swap, timeout_usec), 0),
+        SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Swap, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_EXEC_COMMAND_VTABLE("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), 0),
+        BUS_EXEC_COMMAND_VTABLE("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), 0),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Swap *s = SWAP(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit", bus_unit_properties,           u },
-                { "org.freedesktop.systemd1.Swap", bus_unit_cgroup_properties,    u },
-                { "org.freedesktop.systemd1.Swap", bus_swap_properties,           s },
-                { "org.freedesktop.systemd1.Swap", bus_exec_context_properties,   &s->exec_context },
-                { "org.freedesktop.systemd1.Swap", bus_kill_context_properties,   &s->kill_context },
-                { "org.freedesktop.systemd1.Swap", bus_cgroup_context_properties, &s->cgroup_context },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_swap_changing_properties[] = {
+        "What",
+        "Priority",
+        "ControlPID",
+        "Result",
+        NULL
+};
 
 int bus_swap_set_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         Swap *s = SWAP(u);
-        int r;
 
+        assert(s);
         assert(name);
-        assert(u);
-        assert(i);
+        assert(message);
 
-        r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
-        if (r != 0)
-                return r;
-
-        return 0;
+        return bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
 }
 
 int bus_swap_commit_properties(Unit *u) {
index 9b586a1ad2436a1f305deba1f807fbd724beb355..5d357377cd5c5b91980a2312d62cae88d3133006 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
+#include "sd-bus.h"
 #include "unit.h"
 
-DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
+extern const sd_bus_vtable bus_swap_vtable[];
+extern const char* const bus_swap_changing_properties[];
 
-int bus_swap_set_property(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+int bus_swap_set_property(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 int bus_swap_commit_properties(Unit *u);
-
-extern const char bus_swap_interface[];
-extern const char bus_swap_invalidating_properties[];
index f143d897fa93e7593b754b789e140d3b9265990f..205d1c4a88a383c41207be70aac54999532f5984 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "target.h"
 #include "dbus-unit.h"
 #include "dbus-target.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_TARGET_INTERFACE                                            \
-        " <interface name=\"org.freedesktop.systemd1.Target\">\n"       \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_TARGET_INTERFACE                                            \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Target\0"
-
-const char bus_target_interface[] = BUS_TARGET_INTERFACE;
-
-DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit", bus_unit_properties, u },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
 
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const sd_bus_vtable bus_target_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_VTABLE_END
+};
index a8a0304c75bbbac077edc7a27f9deb3104af40ed..6be9c9f7084d0c4c976d14950070962e629f4bda 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
 
-#include "unit.h"
-
-DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_target_interface[];
+extern const sd_bus_vtable bus_target_vtable[];
index c6f1dd9b7f72bd804cd84c87d844cca174ff62f1..113c63faa0dca857b70903424df492465fc33789 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
+#include "unit.h"
+#include "timer.h"
 #include "dbus-unit.h"
 #include "dbus-timer.h"
-#include "dbus-execute.h"
-#include "dbus-common.h"
-#include "selinux-access.h"
-
-#define BUS_TIMER_INTERFACE                                             \
-        " <interface name=\"org.freedesktop.systemd1.Timer\">\n"        \
-        "  <property name=\"Unit\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"TimersMonotonic\" type=\"a(stt)\" access=\"read\"/>\n" \
-        "  <property name=\"TimersCalendar\" type=\"a(sst)\" access=\"read\"/>\n" \
-        "  <property name=\"NextElapseUSecRealtime\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"NextElapseUSecMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_UNIT_INTERFACE                                              \
-        BUS_TIMER_INTERFACE                                             \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_UNIT_INTERFACES_LIST                     \
-        "org.freedesktop.systemd1.Timer\0"
-
-const char bus_timer_interface[] = BUS_TIMER_INTERFACE;
-
-const char bus_timer_invalidating_properties[] =
-        "TimersMonotonic\0"
-        "TimersRealtime\0"
-        "NextElapseUSecRealtime\0"
-        "NextElapseUSecMonotonic\0"
-        "Result\0";
-
-static int bus_timer_append_monotonic_timers(DBusMessageIter *i, const char *property, void *data) {
-        Timer *p = data;
-        DBusMessageIter sub, sub2;
-        TimerValue *k;
-
-        assert(i);
-        assert(property);
-        assert(p);
-
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(stt)", &sub))
-                return -ENOMEM;
-
-        LIST_FOREACH(value, k, p->values) {
+#include "bus-util.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
+
+static int property_get_monotonic_timers(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Timer *t = userdata;
+        TimerValue *v;
+        int r;
+
+        assert(bus);
+        assert(reply);
+        assert(t);
+
+        r = sd_bus_message_open_container(reply, 'a', "(stt)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(value, v, t->values) {
                 _cleanup_free_ char *buf = NULL;
-                const char *t;
+                const char *s;
                 size_t l;
-                bool b;
 
-                if (k->base == TIMER_CALENDAR)
+                if (v->base == TIMER_CALENDAR)
                         continue;
 
-                t = timer_base_to_string(k->base);
-                assert(endswith(t, "Sec"));
+                s = timer_base_to_string(v->base);
+                assert(endswith(s, "Sec"));
 
                 /* s/Sec/USec/ */
-                l = strlen(t);
+                l = strlen(s);
                 buf = new(char, l+2);
                 if (!buf)
                         return -ENOMEM;
 
-                memcpy(buf, t, l-3);
+                memcpy(buf, s, l-3);
                 memcpy(buf+l-3, "USec", 5);
 
-                b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->value) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
-                        dbus_message_iter_close_container(&sub, &sub2);
-
-                if (!b)
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(stt)", buf, v->value, v->next_elapse);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_timer_append_calendar_timers(DBusMessageIter *i, const char *property, void *data) {
-        Timer *p = data;
-        DBusMessageIter sub, sub2;
-        TimerValue *k;
+static int property_get_calendar_timers(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(p);
+        Timer *t = userdata;
+        TimerValue *v;
+        int r;
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sst)", &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(t);
 
-        LIST_FOREACH(value, k, p->values) {
+        r = sd_bus_message_open_container(reply, 'a', "(sst)");
+        if (r < 0)
+                return r;
+
+        LIST_FOREACH(value, v, t->values) {
                 _cleanup_free_ char *buf = NULL;
-                const char *t;
-                bool b;
-                int j;
 
-                if (k->base != TIMER_CALENDAR)
+                if (v->base != TIMER_CALENDAR)
                         continue;
 
-                t = timer_base_to_string(k->base);
-                j = calendar_spec_to_string(k->calendar_spec, &buf);
-                if (j < 0)
-                        return j;
-
-                b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &t) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
-                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
-                        dbus_message_iter_close_container(&sub, &sub2);
+                r = calendar_spec_to_string(v->calendar_spec, &buf);
+                if (r < 0)
+                        return r;
 
-                if (!b)
-                        return -ENOMEM;
+                r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse);
+                if (r < 0)
+                        return r;
         }
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_timer_append_unit(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data, *trigger;
-        const char *t;
+static int property_get_unit(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Unit *u = userdata, *trigger;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
         trigger = UNIT_TRIGGER(u);
-        t = trigger ? trigger->id : "";
 
-        return dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t) ? 0 : -ENOMEM;
+        return sd_bus_message_append(reply, "s", trigger ? trigger->id : "");
 }
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_timer_append_timer_result, timer_result, TimerResult);
-
-static const BusProperty bus_timer_properties[] = {
-        { "Unit",                    bus_timer_append_unit,             "s",      0 },
-        { "TimersMonotonic",         bus_timer_append_monotonic_timers, "a(stt)", 0 },
-        { "TimersCalendar",          bus_timer_append_calendar_timers,  "a(sst)", 0 },
-        { "NextElapseUSecMonotonic", bus_property_append_usec,          "t",      offsetof(Timer, next_elapse_monotonic) },
-        { "NextElapseUSecRealtime",  bus_property_append_usec,          "t",      offsetof(Timer, next_elapse_realtime) },
-        { "Result",                  bus_timer_append_timer_result,     "s",      offsetof(Timer, result) },
-        { NULL, }
+const sd_bus_vtable bus_timer_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Unit", "s", property_get_unit, 0, 0),
+        SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, 0),
+        SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, 0),
+        SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_monotonic), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_VTABLE_END
 };
 
-DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
-        Timer *t = TIMER(u);
-        const BusBoundProperties bps[] = {
-                { "org.freedesktop.systemd1.Unit",  bus_unit_properties,  u },
-                { "org.freedesktop.systemd1.Timer", bus_timer_properties, t },
-                { NULL, }
-        };
-
-        SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
-
-        return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
-}
+const char* const bus_timer_changing_properties[] = {
+        "NextElapseUSecRealtime",
+        "NextElapseUSecMonotonic",
+        "Result",
+        NULL
+};
index 9ac30501d14c3cb28bdb317d9450cca4e78f89c2..ddd311c626ca2ab7663e5782cc61c5feaf979302 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
 
-#include "unit.h"
-
-DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMessage *message);
-
-extern const char bus_timer_interface[];
-extern const char bus_timer_invalidating_properties[];
+extern const sd_bus_vtable bus_timer_vtable[];
+extern const char* const bus_timer_changing_properties[];
index 032915d14ea4d0bbccb552058dc44a5c3fd4cb3c..49054781c0161c4fabc26c7235868eb1e822052a 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <errno.h>
-
-#include "dbus.h"
+#include "sd-bus.h"
 #include "log.h"
-#include "dbus-unit.h"
-#include "bus-errors.h"
-#include "dbus-common.h"
 #include "selinux-access.h"
 #include "cgroup-util.h"
 #include "strv.h"
 #include "path-util.h"
 #include "fileio.h"
+#include "dbus-unit.h"
+#include "dbus-manager.h"
+#include "bus-errors.h"
+#include "dbus-client-track.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
+
+static int property_get_names(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Unit *u = userdata;
+        Iterator i;
+        const char *t;
+        int r;
 
-const char bus_unit_interface[] = BUS_UNIT_INTERFACE;
-
-#define INVALIDATING_PROPERTIES                 \
-        "LoadState\0"                           \
-        "ActiveState\0"                         \
-        "SubState\0"                            \
-        "InactiveExitTimestamp\0"               \
-        "ActiveEnterTimestamp\0"                \
-        "ActiveExitTimestamp\0"                 \
-        "InactiveEnterTimestamp\0"              \
-        "Job\0"                                 \
-        "NeedDaemonReload\0"
-
-static int bus_unit_append_names(DBusMessageIter *i, const char *property, void *data) {
-        char *t;
-        Iterator j;
-        DBusMessageIter sub;
-        Unit *u = data;
-
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        SET_FOREACH(t, u->names, j)
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &t))
-                        return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "s");
+        if (r < 0)
+                return r;
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        SET_FOREACH(t, u->names, i) {
+                r = sd_bus_message_append(reply, "s", t);
+                if (r < 0)
+                        return r;
+        }
 
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_unit_append_following(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data, *f;
-        const char *d;
+static int property_get_following(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Unit *u = userdata, *f;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
         f = unit_following(u);
-        d = f ? f->id : "";
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", f ? f->id : "");
 }
 
-static int bus_unit_append_slice(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *d;
-
-        assert(i);
-        assert(property);
-        assert(u);
-
-        d = strempty(unit_slice_name(u));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
+static int property_get_dependencies(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        return 0;
-}
-
-static int bus_unit_append_dependencies(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u;
+        Set *s = *(Set**) userdata;
         Iterator j;
-        DBusMessageIter sub;
-        Set *s = data;
+        Unit *u;
+        int r;
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
 
-        SET_FOREACH(u, s, j)
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &u->id))
-                        return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "s");
+        if (r < 0)
+                return r;
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        SET_FOREACH(u, s, j) {
+                r = sd_bus_message_append(reply, "s", u->id);
+                if (r < 0)
+                        return r;
+        }
 
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_unit_append_description(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *d;
+static int property_get_description(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
-
-        d = unit_description(u);
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "s", unit_description(u));
 }
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_unit_append_load_state, unit_load_state, UnitLoadState);
+static int property_get_active_state(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-static int bus_unit_append_active_state(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *state;
+        Unit *u = userdata;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
-        state = unit_active_state_to_string(unit_active_state(u));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
 }
 
-static int bus_unit_append_sub_state(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *state;
-
-        assert(i);
-        assert(property);
-        assert(u);
+static int property_get_sub_state(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        state = unit_sub_state_to_string(u);
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
 }
 
-static int bus_unit_append_file_state(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *state;
+static int property_get_unit_file_state(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
+        Unit *u = userdata;
 
-        state = strempty(unit_file_state_to_string(unit_get_unit_file_state(u)));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
 }
 
-static int bus_unit_append_can_start(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
-
-        assert(i);
-        assert(property);
-        assert(u);
+static int property_get_can_start(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        b = unit_can_start(u) &&
-                !u->refuse_manual_start;
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
 }
 
-static int bus_unit_append_can_stop(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
+static int property_get_can_stop(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Unit *u = userdata;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
         /* On the lower levels we assume that every unit we can start
          * we can also stop */
 
-        b = unit_can_start(u) &&
-                !u->refuse_manual_stop;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_stop);
 }
 
-static int bus_unit_append_can_reload(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
+static int property_get_can_reload(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
-
-        b = unit_can_reload(u);
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_can_reload(u));
 }
 
-static int bus_unit_append_can_isolate(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
+static int property_get_can_isolate(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
-
-        b = unit_can_isolate(u) &&
-                !u->refuse_manual_start;
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
 }
 
-static int bus_unit_append_job(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        DBusMessageIter sub;
+static int property_get_job(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
         _cleanup_free_ char *p = NULL;
+        Unit *u = userdata;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(u);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
-                return -ENOMEM;
-
-        if (u->job) {
+        if (!u->job)
+                return sd_bus_message_append(reply, "(uo)", 0, "/");
 
-                p = job_dbus_path(u->job);
-                if (!p)
-                        return -ENOMEM;
-
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &u->job->id) ||
-                    !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p))
-                        return -ENOMEM;
-        } else {
-                uint32_t id = 0;
+        p = job_dbus_path(u->job);
+        if (!p)
+                return -ENOMEM;
 
-                /* No job, so let's fill in some placeholder
-                 * data. Since we need to fill in a valid path we
-                 * simple point to ourselves. */
+        return sd_bus_message_append(reply, "(uo)", u->job->id, p);
+}
 
-                p = unit_dbus_path(u);
-                if (!p)
-                        return -ENOMEM;
+static int property_get_need_daemon_reload(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &id) ||
-                    !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p))
-                        return -ENOMEM;
-        }
+        Unit *u = userdata;
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        return 0;
+        return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
 }
 
-static int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        dbus_bool_t b;
+static int property_get_conditions(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        assert(i);
-        assert(property);
-        assert(u);
+        Unit *u = userdata;
+        Condition *c;
+        int r;
 
-        b = unit_need_daemon_reload(u);
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
-                return -ENOMEM;
+        r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
+        if (r < 0)
+                return r;
 
-        return 0;
-}
+        LIST_FOREACH(conditions, c, u->conditions) {
+                r = sd_bus_message_append(reply, "sbbsi", condition_type_to_string(c->type), c->trigger, c->negate, c->parameter, c->state);
+                if (r < 0)
+                        return r;
 
-static int bus_property_append_condition(DBusMessageIter *i, const char *property, void *data) {
-        Condition **cp = data;
-        Condition *c;
-        const char *name, *param;
-        dbus_bool_t trigger, negate;
-        dbus_int32_t state;
-        DBusMessageIter sub;
-
-        assert(i);
-        assert(property);
-        assert(cp);
-
-        c = *cp;
-        assert(c);
-
-        name = condition_type_to_string(c->type);
-        param = c->parameter;
-        trigger = c->trigger;
-        negate = c->negate;
-        state = c->state;
-
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &name) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &trigger) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &negate) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &param) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &state) ||
-            !dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        }
 
-        return 0;
+        return sd_bus_message_close_container(reply);
 }
 
-static int bus_property_append_condition_list(DBusMessageIter *i, const char *property, void *data) {
-        Condition **first = data, *c;
-        DBusMessageIter sub;
-
-        assert(i);
-        assert(data);
+static int property_get_load_error(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sbbsi)", &sub))
-                return -ENOMEM;
+        _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
+        Unit *u = userdata;
 
-        LIST_FOREACH(conditions, c, *first)
-                bus_property_append_condition(&sub, property, &c);
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        if (u->load_error != 0)
+                sd_bus_error_set_errno(&e, u->load_error);
 
-        return 0;
+        return sd_bus_message_append(reply, "(ss)", e.name, e.message);
 }
 
-static int bus_unit_append_load_error(DBusMessageIter *i, const char *property, void *data) {
-        Unit *u = data;
-        const char *name, *message;
-        DBusMessageIter sub;
+int bus_unit_method_start_generic(sd_bus *bus, sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible) {
+        const char *smode;
+        JobMode mode;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(message);
         assert(u);
+        assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
 
-        if (u->load_error != 0) {
-                name = bus_errno_to_dbus(u->load_error);
-                message = strempty(strerror(-u->load_error));
-        } else
-                name = message = "";
+        r = sd_bus_message_read(message, "s", &smode);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &name) ||
-            !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &message) ||
-            !dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        mode = job_mode_from_string(smode);
+        if (mode < 0)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
 
-        return 0;
+        return bus_unit_queue_job(bus, message, u, job_type, mode, reload_if_possible);
 }
 
-static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *connection, DBusMessage *message) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        DBusError error;
-        JobType job_type = _JOB_TYPE_INVALID;
-        bool reload_if_possible = false;
-        int r;
+static int method_start(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_START, false);
+}
 
-        dbus_error_init(&error);
-
-        if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Start"))
-                job_type = JOB_START;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Stop"))
-                job_type = JOB_STOP;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Reload"))
-                job_type = JOB_RELOAD;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Restart"))
-                job_type = JOB_RESTART;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "TryRestart"))
-                job_type = JOB_TRY_RESTART;
-        else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrRestart")) {
-                reload_if_possible = true;
-                job_type = JOB_RESTART;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrTryRestart")) {
-                reload_if_possible = true;
-                job_type = JOB_TRY_RESTART;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Kill")) {
-                const char *swho;
-                int32_t signo;
-                KillWho who;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &swho,
-                                    DBUS_TYPE_INT32, &signo,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                if (isempty(swho))
-                        who = KILL_ALL;
-                else {
-                        who = kill_who_from_string(swho);
-                        if (who < 0)
-                                return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+static int method_stop(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_STOP, false);
+}
+
+static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_RELOAD, false);
+}
 
-                if (signo <= 0 || signo >= _NSIG)
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+static int method_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, false);
+}
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
+static int method_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, false);
+}
 
-                r = unit_kill(u, who, signo, &error);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
+static int method_reload_or_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, true);
+}
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+static int method_reload_or_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, true);
+}
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ResetFailed")) {
+int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        Unit *u = userdata;
+        const char *swho;
+        int32_t signo;
+        KillWho who;
+        int r;
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
+        assert(bus);
+        assert(message);
+        assert(u);
 
-                unit_reset_failed(u);
+        r = sd_bus_message_read(message, "si", &swho, &signo);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        if (isempty(swho))
+                who = KILL_ALL;
+        else {
+                who = kill_who_from_string(swho);
+                if (who < 0)
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
+        }
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "SetProperties")) {
-                DBusMessageIter iter;
-                dbus_bool_t runtime;
+        if (signo <= 0 || signo >= _NSIG)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
 
-                if (!dbus_message_iter_init(message, &iter))
-                        goto oom;
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "stop");
 
-                if (bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0)
-                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
+        r = unit_kill(u, who, signo, &error);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                r = bus_unit_set_properties(u, &iter, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, &error);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, &error, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else if (UNIT_VTABLE(u)->bus_message_handler)
-                return UNIT_VTABLE(u)->bus_message_handler(u, connection, message);
-        else
-                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-        if (job_type != _JOB_TYPE_INVALID) {
-                const char *smode;
-                JobMode mode;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &smode,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                mode = job_mode_from_string(smode);
-                if (mode < 0) {
-                        dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Unit *u = userdata;
 
-                return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
-        }
+        assert(bus);
+        assert(message);
+        assert(u);
 
-        if (reply)
-                if (!bus_maybe_send_reply(connection, message, reply))
-                        goto oom;
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "reload");
 
-        return DBUS_HANDLER_RESULT_HANDLED;
+        unit_reset_failed(u);
 
-oom:
-        dbus_error_free(&error);
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        return sd_bus_reply_method_return(bus, message, NULL);
 }
 
-static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DBusMessage  *message, void *data) {
-        Manager *m = data;
-        Unit *u;
-        int r;
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        DBusError error;
+int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        Unit *u = userdata;
+        int runtime, r;
 
-        assert(connection);
+        assert(bus);
         assert(message);
-        assert(m);
-
-        dbus_error_init(&error);
+        assert(u);
 
-        if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/unit")) {
-                /* Be nice to gdbus and return introspection data for our mid-level paths */
+        r = sd_bus_message_read(message, "b", &runtime);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                SELINUX_ACCESS_CHECK(connection, message, "status");
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message, "start");
 
-                if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
-                        char *introspection = NULL;
-                        FILE *f;
-                        Iterator i;
-                        const char *k;
-                        size_t size;
+        r = sd_bus_message_enter_container(message, 'a', "(sv)");
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                        reply = dbus_message_new_method_return(message);
-                        if (!reply)
-                                goto oom;
+        r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, &error);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-                        /* We roll our own introspection code here, instead of
-                         * relying on bus_default_message_handler() because we
-                         * need to generate our introspection string
-                         * dynamically. */
+        r = sd_bus_message_exit_container(message);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                        f = open_memstream(&introspection, &size);
-                        if (!f)
-                                goto oom;
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                        fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
-                              "<node>\n", f);
+const sd_bus_vtable bus_unit_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+
+        SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), 0),
+        SD_BUS_PROPERTY("Names", "as", property_get_names, 0, 0),
+        SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
+        SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), 0),
+        SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), 0),
+        SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), 0),
+        SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), 0),
+        SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), 0),
+        SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), 0),
+        SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), 0),
+        SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), 0),
+        SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), 0),
+        SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), 0),
+        SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), 0),
+        SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), 0),
+        SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), 0),
+        SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), 0),
+        SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), 0),
+        SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), 0),
+        SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), 0),
+        SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), 0),
+        SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), 0),
+        SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), 0),
+        SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), 0),
+        SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), 0),
+        SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), 0),
+        SD_BUS_PROPERTY("Description", "s", property_get_description, 0, 0),
+        SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), 0),
+        SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), 0),
+        SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), 0),
+        SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), 0),
+        SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
+        BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, 0),
+        SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, 0),
+        SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, 0),
+        SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, 0),
+        SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), 0),
+        SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), 0),
+        SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), 0),
+        SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), 0),
+        SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), 0),
+        SD_BUS_PROPERTY("OnFailureIsolate", "b", bus_property_get_bool, offsetof(Unit, on_failure_isolate), 0),
+        SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), 0),
+        SD_BUS_PROPERTY("IgnoreOnSnapshot", "b", bus_property_get_bool, offsetof(Unit, ignore_on_snapshot), 0),
+        SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, 0),
+        SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), 0),
+        SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, 0, 0),
+        SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, 0),
+        SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), 0),
+
+        SD_BUS_METHOD("Start", "s", "o", method_start, 0),
+        SD_BUS_METHOD("Stop", "s", "o", method_stop, 0),
+        SD_BUS_METHOD("Reload", "s", "o", method_reload, 0),
+        SD_BUS_METHOD("Restart", "s", "o", method_restart, 0),
+        SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, 0),
+        SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, 0),
+        SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, 0),
+        SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, 0),
+        SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, 0),
+        SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, 0),
+
+        SD_BUS_VTABLE_END
+};
 
-                        fputs(BUS_INTROSPECTABLE_INTERFACE, f);
-                        fputs(BUS_PEER_INTERFACE, f);
+static int property_get_slice(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-                        HASHMAP_FOREACH_KEY(u, k, m->units, i) {
-                                char *p;
+        Unit *u = userdata;
 
-                                if (k != u->id)
-                                        continue;
+        assert(bus);
+        assert(reply);
+        assert(u);
 
-                                p = bus_path_escape(k);
-                                if (!p) {
-                                        fclose(f);
-                                        free(introspection);
-                                        goto oom;
-                                }
+        return sd_bus_message_append(reply, "s", unit_slice_name(u));
+}
 
-                                fprintf(f, "<node name=\"%s\"/>", p);
-                                free(p);
-                        }
+const sd_bus_vtable bus_unit_cgroup_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
+        SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Unit, cgroup_path), 0),
+        SD_BUS_VTABLE_END
+};
 
-                        fputs("</node>\n", f);
+static int send_new_signal(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_free_ char *p = NULL;
+        Unit *u = userdata;
+        int r;
 
-                        if (ferror(f)) {
-                                fclose(f);
-                                free(introspection);
-                                goto oom;
-                        }
+        assert(bus);
+        assert(u);
 
-                        fclose(f);
+        p = unit_dbus_path(u);
+        if (!u)
+                return -ENOMEM;
 
-                        if (!introspection)
-                                goto oom;
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "UnitNew",
+                        &m);
+        if (r < 0)
+                return r;
 
-                        if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
-                                free(introspection);
-                                goto oom;
-                        }
+        r = sd_bus_message_append(m, "so", u->id, p);
+        if (r < 0)
+                return r;
 
-                        free(introspection);
+        return sd_bus_send_to(bus, m, destination, NULL);
+}
 
-                        if (!bus_maybe_send_reply(connection, message, reply))
-                                goto oom;
+static int send_changed_signal(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_free_ char *p = NULL;
+        Unit *u = userdata;
+        int r;
 
-                        return DBUS_HANDLER_RESULT_HANDLED;
-                }
+        assert(bus);
+        assert(u);
 
-                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-        }
+        p = unit_dbus_path(u);
+        if (!u)
+                return -ENOMEM;
 
-        r = manager_load_unit_from_dbus_path(m, dbus_message_get_path(message), &error, &u);
-        if (r == -ENOMEM)
-                goto oom;
-        if (r < 0)
-                return bus_send_error_reply(connection, message, &error, r);
+        /* Send a properties changed signal. First for the specific
+         * type, then for the generic unit. The clients may rely on
+         * this order to get atomic behavior if needed. */
 
-        return bus_unit_message_dispatch(u, connection, message);
+        if (UNIT_VTABLE(u)->bus_changing_properties) {
 
-oom:
-        dbus_error_free(&error);
+                r = sd_bus_emit_properties_changed_strv(
+                                bus, p,
+                                UNIT_VTABLE(u)->bus_interface,
+                                (char**) UNIT_VTABLE(u)->bus_changing_properties);
+                if (r < 0)
+                        return r;
+        }
 
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        return sd_bus_emit_properties_changed(
+                        bus, p,
+                        "org.freedesktop.systemd1.Unit",
+                        "ActiveState",
+                        "SubState",
+                        "InactiveExitTimestamp",
+                        "ActiveEnterTimestamp",
+                        "ActiveExitTimestamp",
+                        "InactiveEnterTimestamp",
+                        "Job",
+                        "ConditionResult",
+                        "ConditionTimestamp",
+                        NULL);
 }
 
-const DBusObjectPathVTable bus_unit_vtable = {
-        .message_function = bus_unit_message_handler
-};
-
 void bus_unit_send_change_signal(Unit *u) {
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
-        _cleanup_free_ char *p = NULL;
         int r;
 
         assert(u);
@@ -634,141 +670,77 @@ void bus_unit_send_change_signal(Unit *u) {
         if (!u->id)
                 return;
 
-        if (!bus_has_subscriber(u->manager)) {
-                u->sent_dbus_new_signal = true;
-                return;
-        }
-
-        p = unit_dbus_path(u);
-        if (!p) {
-                log_oom();
-                return;
-        }
-
-        if (u->sent_dbus_new_signal) {
-                /* Send a properties changed signal. First for the
-                 * specific type, then for the generic unit. The
-                 * clients may rely on this order to get atomic
-                 * behavior if needed. */
-
-                if (UNIT_VTABLE(u)->bus_invalidating_properties) {
-
-                        m = bus_properties_changed_new(p,
-                                                       UNIT_VTABLE(u)->bus_interface,
-                                                       UNIT_VTABLE(u)->bus_invalidating_properties);
-                        if (!m) {
-                                log_oom();
-                                return;
-                        }
-
-                        r = bus_broadcast(u->manager, m);
-                        if (r < 0) {
-                                log_error("Failed to broadcast change message: %s", strerror(-r));
-                                return;
-                        }
+        r = bus_manager_foreach_client(u->manager, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
+        if (r < 0)
+                log_warning("Failed to send unit change signal for %s: %s", u->id, strerror(-r));
 
-                        dbus_message_unref(m);
-                }
+        u->sent_dbus_new_signal = true;
+}
 
-                m = bus_properties_changed_new(p, "org.freedesktop.systemd1.Unit",
-                                               INVALIDATING_PROPERTIES);
-                if (!m) {
-                        log_oom();
-                        return;
-                }
+static int send_removed_signal(sd_bus *bus, const char *destination, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_free_ char *p = NULL;
+        Unit *u = userdata;
+        int r;
 
-        } else {
-                /* Send a new signal */
+        assert(bus);
+        assert(u);
 
-                m = dbus_message_new_signal("/org/freedesktop/systemd1",
-                                            "org.freedesktop.systemd1.Manager",
-                                            "UnitNew");
-                if (!m) {
-                        log_oom();
-                        return;
-                }
+        p = unit_dbus_path(u);
+        if (!u)
+                return -ENOMEM;
 
-                if (!dbus_message_append_args(m,
-                                              DBUS_TYPE_STRING, &u->id,
-                                              DBUS_TYPE_OBJECT_PATH, &p,
-                                              DBUS_TYPE_INVALID)) {
-                        log_oom();
-                        return;
-                }
-        }
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "UnitRemoved",
+                        &m);
+        if (r < 0)
+                return r;
 
-        r = bus_broadcast(u->manager, m);
-        if (r < 0) {
-                log_error("Failed to broadcast UnitNew/PropertiesChanged message.");
-                return;
-        }
+        r = sd_bus_message_append(m, "so", u->id, p);
+        if (r < 0)
+                return r;
 
-        u->sent_dbus_new_signal = true;
+        return sd_bus_send_to(bus, m, destination, NULL);
 }
 
 void bus_unit_send_removed_signal(Unit *u) {
-        _cleanup_free_ char *p = NULL;
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
+        int r;
 
         assert(u);
 
-        if (!bus_has_subscriber(u->manager))
-                return;
-
         if (!u->sent_dbus_new_signal)
                 bus_unit_send_change_signal(u);
 
         if (!u->id)
                 return;
 
-        p = unit_dbus_path(u);
-        if (!p)
-                goto oom;
-
-        m = dbus_message_new_signal("/org/freedesktop/systemd1",
-                                    "org.freedesktop.systemd1.Manager",
-                                    "UnitRemoved");
-        if (!m)
-                goto oom;
-
-        if (!dbus_message_append_args(m,
-                                      DBUS_TYPE_STRING, &u->id,
-                                      DBUS_TYPE_OBJECT_PATH, &p,
-                                      DBUS_TYPE_INVALID))
-                goto oom;
-
-        if (bus_broadcast(u->manager, m) < 0)
-                goto oom;
-
-        return;
-
-oom:
-        log_oom();
+        r = bus_manager_foreach_client(u->manager, send_removed_signal, u);
+        if (r < 0)
+                log_warning("Failed to send unit change signal for %s: %s", u->id, strerror(-r));
 }
 
-DBusHandlerResult bus_unit_queue_job(
-                DBusConnection *connection,
-                DBusMessage *message,
+int bus_unit_queue_job(
+                sd_bus *bus,
+                sd_bus_message *message,
                 Unit *u,
                 JobType type,
                 JobMode mode,
                 bool reload_if_possible) {
 
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *path = NULL;
         Job *j;
-        JobBusClient *cl;
-        DBusError error;
         int r;
 
-        assert(connection);
+        assert(bus);
         assert(message);
         assert(u);
         assert(type >= 0 && type < _JOB_TYPE_MAX);
         assert(mode >= 0 && mode < _JOB_MODE_MAX);
 
-        dbus_error_init(&error);
-
         if (reload_if_possible && unit_can_reload(u)) {
                 if (type == JOB_RESTART)
                         type = JOB_RELOAD_OR_START;
@@ -776,85 +748,61 @@ DBusHandlerResult bus_unit_queue_job(
                         type = JOB_RELOAD;
         }
 
-        SELINUX_UNIT_ACCESS_CHECK(u, connection, message,
+        SELINUX_UNIT_ACCESS_CHECK(u, bus, message,
                                   (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
                                   type == JOB_STOP ? "stop" : "reload");
 
-        if (type == JOB_STOP && (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) && unit_active_state(u) == UNIT_INACTIVE) {
-                dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
-                return bus_send_error_reply(connection, message, &error, -EPERM);
-        }
+        if (type == JOB_STOP &&
+            (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
+            unit_active_state(u) == UNIT_INACTIVE)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
 
         if ((type == JOB_START && u->refuse_manual_start) ||
             (type == JOB_STOP && u->refuse_manual_stop) ||
-            ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop))) {
-                dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY,
-                               "Operation refused, unit %s may be requested by dependency only.", u->id);
-                return bus_send_error_reply(connection, message, &error, -EPERM);
-        }
+            ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)))
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
 
         r = manager_add_job(u->manager, type, u, mode, true, &error, &j);
         if (r < 0)
-                return bus_send_error_reply(connection, message, &error, r);
-
-        cl = job_bus_client_new(connection, bus_message_get_sender_with_fallback(message));
-        if (!cl)
-                goto oom;
-
-        LIST_PREPEND(client, j->bus_client_list, cl);
+                return sd_bus_reply_method_errno(bus, message, r, &error);
 
-        reply = dbus_message_new_method_return(message);
-        if (!reply)
-                goto oom;
+        r = bus_client_track(&j->subscribed, bus, sd_bus_message_get_sender(message));
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
         path = job_dbus_path(j);
         if (!path)
-                goto oom;
-
-        if (!dbus_message_append_args(
-                            reply,
-                            DBUS_TYPE_OBJECT_PATH, &path,
-                            DBUS_TYPE_INVALID))
-                goto oom;
-
-        if (!bus_maybe_send_reply(connection, message, reply))
-                goto oom;
-
-        return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
-        dbus_error_free(&error);
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        return sd_bus_reply_method_return(bus, message, "o", path);
 }
 
 static int bus_unit_set_transient_property(
                 Unit *u,
                 const char *name,
-                DBusMessageIter *i,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         int r;
 
         assert(u);
         assert(name);
-        assert(i);
+        assert(message);
 
         if (streq(name, "Description")) {
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
-
-                if (mode != UNIT_CHECK) {
-                        const char *description;
+                const char *d;
 
-                        dbus_message_iter_get_basic(i, &description);
+                r = sd_bus_message_read(message, "s", &d);
+                if (r < 0)
+                        return r;
 
-                        r = unit_set_description(u, description);
+                if (mode != UNIT_CHECK) {
+                        r = unit_set_description(u, d);
                         if (r < 0)
                                 return r;
 
-                        unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", description);
+                        unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", d);
                 }
 
                 return 1;
@@ -862,10 +810,12 @@ static int bus_unit_set_transient_property(
         } else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
                 const char *s;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
+                r = sd_bus_message_read(message, "s", &s);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_get_basic(i, &s);
+                if (!unit_name_is_valid(s, false) || !endswith(s, ".slice"))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid slice name %s", s);
 
                 if (isempty(s)) {
                         if (mode != UNIT_CHECK) {
@@ -905,24 +855,19 @@ static int bus_unit_set_transient_property(
                    streq(name, "PartOf")) {
 
                 UnitDependency d;
-                DBusMessageIter sub;
+                const char *other;
 
                 d = unit_dependency_from_string(name);
                 if (d < 0)
                         return -EINVAL;
 
-                if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
-                    dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRING)
-                        return -EINVAL;
-
-                dbus_message_iter_recurse(i, &sub);
-                while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
-                        const char *other;
-
-                        dbus_message_iter_get_basic(&sub, &other);
+                r = sd_bus_message_enter_container(message, 'a', "s");
+                if (r < 0)
+                        return r;
 
+                while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
                         if (!unit_name_is_valid(other, false))
-                                return -EINVAL;
+                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
 
                         if (mode != UNIT_CHECK) {
                                 _cleanup_free_ char *label = NULL;
@@ -938,8 +883,9 @@ static int bus_unit_set_transient_property(
                                 unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other);
                         }
 
-                        dbus_message_iter_next(&sub);
                 }
+                if (r < 0)
+                        return r;
 
                 return 1;
         }
@@ -949,18 +895,17 @@ static int bus_unit_set_transient_property(
 
 int bus_unit_set_properties(
                 Unit *u,
-                DBusMessageIter *iter,
+                sd_bus_message *message,
                 UnitSetPropertiesMode mode,
                 bool commit,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         bool for_real = false;
-        DBusMessageIter sub;
         unsigned n = 0;
         int r;
 
         assert(u);
-        assert(iter);
+        assert(message);
 
         if (u->transient)
                 mode &= UNIT_RUNTIME;
@@ -970,52 +915,54 @@ int bus_unit_set_properties(
          * it. This is to implement transaction-like behaviour without
          * actually providing full transactions. */
 
-        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
-            dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRUCT)
-                return -EINVAL;
+        r = sd_bus_message_enter_container(message, 'a', "(sv)");
+        if (r < 0)
+                return r;
 
-        dbus_message_iter_recurse(iter, &sub);
         for (;;) {
-                DBusMessageIter sub2, sub3;
                 const char *name;
 
-                if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_INVALID) {
-
+                r = sd_bus_message_enter_container(message, 'r', "sv");
+                if (r < 0)
+                        return r;
+                if (r == 0) {
                         if (for_real || mode == UNIT_CHECK)
                                 break;
 
                         /* Reached EOF. Let's try again, and this time for realz... */
-                        dbus_message_iter_recurse(iter, &sub);
+                        r = sd_bus_message_rewind(message, false);
+                        if (r < 0)
+                                return r;
                         for_real = true;
                         continue;
                 }
 
-                if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT)
-                        return -EINVAL;
-
-                dbus_message_iter_recurse(&sub, &sub2);
+                r = sd_bus_message_read(message, "s", &name);
+                if (r < 0)
+                        return r;
 
-                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
-                    dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT)
-                        return -EINVAL;
+                if (!UNIT_VTABLE(u)->bus_set_property)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
 
-                if (!UNIT_VTABLE(u)->bus_set_property) {
-                        dbus_set_error(error, DBUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
-                        return -ENOENT;
-                }
+                r = sd_bus_message_enter_container(message, 'v', NULL);
+                if (r < 0)
+                        return r;
 
-                dbus_message_iter_recurse(&sub2, &sub3);
-                r = UNIT_VTABLE(u)->bus_set_property(u, name, &sub3, for_real ? mode : UNIT_CHECK, error);
+                r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
                 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
-                        r = bus_unit_set_transient_property(u, name, &sub3, for_real ? mode : UNIT_CHECK, error);
+                        r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
+
+                r = sd_bus_message_exit_container(message);
                 if (r < 0)
                         return r;
-                if (r == 0) {
-                        dbus_set_error(error, DBUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
-                        return -ENOENT;
-                }
 
-                dbus_message_iter_next(&sub);
+                r = sd_bus_message_exit_container(message);
+                if (r < 0)
+                        return r;
 
                 n += for_real;
         }
@@ -1025,76 +972,3 @@ int bus_unit_set_properties(
 
         return n;
 }
-
-const BusProperty bus_unit_properties[] = {
-        { "Id",                              bus_property_append_string,                "s", offsetof(Unit, id),                                         true },
-        { "Names",                           bus_unit_append_names,                    "as", 0                                                                },
-        { "Following",                       bus_unit_append_following,                 "s", 0                                                                },
-        { "Requires",                        bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUIRES]),                true },
-        { "RequiresOverridable",             bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]),    true },
-        { "Requisite",                       bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUISITE]),               true },
-        { "RequisiteOverridable",            bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]),   true },
-        { "Wants",                           bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_WANTS]),                   true },
-        { "BindsTo",                         bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_BINDS_TO]),                true },
-        { "PartOf",                          bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_PART_OF]),                 true },
-        { "RequiredBy",                      bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]),             true },
-        { "RequiredByOverridable",           bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
-        { "WantedBy",                        bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]),               true },
-        { "BoundBy",                         bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]),                true },
-        { "ConsistsOf",                      bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_CONSISTS_OF]),             true },
-        { "Conflicts",                       bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]),               true },
-        { "ConflictedBy",                    bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]),           true },
-        { "Before",                          bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_BEFORE]),                  true },
-        { "After",                           bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_AFTER]),                   true },
-        { "OnFailure",                       bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]),              true },
-        { "Triggers",                        bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]),                true },
-        { "TriggeredBy",                     bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]),            true },
-        { "PropagatesReloadTo",              bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]),    true },
-        { "ReloadPropagatedFrom",            bus_unit_append_dependencies,             "as", offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]),  true },
-        { "RequiresMountsFor",               bus_property_append_strv,                 "as", offsetof(Unit, requires_mounts_for),                        true },
-        { "Documentation",                   bus_property_append_strv,                 "as", offsetof(Unit, documentation),                              true },
-        { "Description",                     bus_unit_append_description,               "s", 0                                                                },
-        { "LoadState",                       bus_unit_append_load_state,                "s", offsetof(Unit, load_state)                                       },
-        { "ActiveState",                     bus_unit_append_active_state,              "s", 0                                                                },
-        { "SubState",                        bus_unit_append_sub_state,                 "s", 0                                                                },
-        { "FragmentPath",                    bus_property_append_string,                "s", offsetof(Unit, fragment_path),                              true },
-        { "SourcePath",                      bus_property_append_string,                "s", offsetof(Unit, source_path),                                true },
-        { "DropInPaths",                     bus_property_append_strv,                 "as", offsetof(Unit, dropin_paths),                               true },
-        { "UnitFileState",                   bus_unit_append_file_state,                "s", 0                                                                },
-        { "InactiveExitTimestamp",           bus_property_append_usec,                  "t", offsetof(Unit, inactive_exit_timestamp.realtime)                 },
-        { "InactiveExitTimestampMonotonic",  bus_property_append_usec,                  "t", offsetof(Unit, inactive_exit_timestamp.monotonic)                },
-        { "ActiveEnterTimestamp",            bus_property_append_usec,                  "t", offsetof(Unit, active_enter_timestamp.realtime)                  },
-        { "ActiveEnterTimestampMonotonic",   bus_property_append_usec,                  "t", offsetof(Unit, active_enter_timestamp.monotonic)                 },
-        { "ActiveExitTimestamp",             bus_property_append_usec,                  "t", offsetof(Unit, active_exit_timestamp.realtime)                   },
-        { "ActiveExitTimestampMonotonic",    bus_property_append_usec,                  "t", offsetof(Unit, active_exit_timestamp.monotonic)                  },
-        { "InactiveEnterTimestamp",          bus_property_append_usec,                  "t", offsetof(Unit, inactive_enter_timestamp.realtime)                },
-        { "InactiveEnterTimestampMonotonic", bus_property_append_usec,                  "t", offsetof(Unit, inactive_enter_timestamp.monotonic)               },
-        { "CanStart",                        bus_unit_append_can_start,                 "b", 0                                                                },
-        { "CanStop",                         bus_unit_append_can_stop,                  "b", 0                                                                },
-        { "CanReload",                       bus_unit_append_can_reload,                "b", 0                                                                },
-        { "CanIsolate",                      bus_unit_append_can_isolate,               "b", 0                                                                },
-        { "Job",                             bus_unit_append_job,                    "(uo)", 0                                                                },
-        { "StopWhenUnneeded",                bus_property_append_bool,                  "b", offsetof(Unit, stop_when_unneeded)                               },
-        { "RefuseManualStart",               bus_property_append_bool,                  "b", offsetof(Unit, refuse_manual_start)                              },
-        { "RefuseManualStop",                bus_property_append_bool,                  "b", offsetof(Unit, refuse_manual_stop)                               },
-        { "AllowIsolate",                    bus_property_append_bool,                  "b", offsetof(Unit, allow_isolate)                                    },
-        { "DefaultDependencies",             bus_property_append_bool,                  "b", offsetof(Unit, default_dependencies)                             },
-        { "OnFailureIsolate",                bus_property_append_bool,                  "b", offsetof(Unit, on_failure_isolate)                               },
-        { "IgnoreOnIsolate",                 bus_property_append_bool,                  "b", offsetof(Unit, ignore_on_isolate)                                },
-        { "IgnoreOnSnapshot",                bus_property_append_bool,                  "b", offsetof(Unit, ignore_on_snapshot)                               },
-        { "NeedDaemonReload",                bus_unit_append_need_daemon_reload,        "b", 0                                                                },
-        { "JobTimeoutUSec",                  bus_property_append_usec,                  "t", offsetof(Unit, job_timeout)                                      },
-        { "ConditionTimestamp",              bus_property_append_usec,                  "t", offsetof(Unit, condition_timestamp.realtime)                     },
-        { "ConditionTimestampMonotonic",     bus_property_append_usec,                  "t", offsetof(Unit, condition_timestamp.monotonic)                    },
-        { "ConditionResult",                 bus_property_append_bool,                  "b", offsetof(Unit, condition_result)                                 },
-        { "Conditions",                      bus_property_append_condition_list, "a(sbbsi)", offsetof(Unit, conditions)                                       },
-        { "LoadError",                       bus_unit_append_load_error,             "(ss)", 0                                                                },
-        { "Transient",                       bus_property_append_bool,                  "b", offsetof(Unit, transient)                                        },
-        {}
-};
-
-const BusProperty bus_unit_cgroup_properties[] = {
-        { "Slice",                bus_unit_append_slice,              "s", 0 },
-        { "ControlGroup",         bus_property_append_string,         "s", offsetof(Unit, cgroup_path),                                true },
-        {}
-};
index 3064cd552a37385f1ce16e4bbd70070ab5685b42..859de102b61fcfe6a4bfd5156de606e4cb360d01 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
+#include "sd-bus.h"
+#include "unit.h"
 
-#include "manager.h"
-#include "dbus-common.h"
-
-#define BUS_UNIT_INTERFACE \
-        " <interface name=\"org.freedesktop.systemd1.Unit\">\n"         \
-        "  <method name=\"Start\">\n"                                   \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Stop\">\n"                                    \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Reload\">\n"                                  \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Restart\">\n"                                 \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"TryRestart\">\n"                              \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadOrRestart\">\n"                         \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"ReloadOrTryRestart\">\n"                      \
-        "   <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"job\" type=\"o\" direction=\"out\"/>\n"         \
-        "  </method>\n"                                                 \
-        "  <method name=\"Kill\">\n"                                    \
-        "   <arg name=\"who\" type=\"s\" direction=\"in\"/>\n"          \
-        "   <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"ResetFailed\"/>\n"                            \
-        "  <method name=\"SetProperties\">\n"                           \
-        "   <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n"      \
-        "   <arg name=\"properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <property name=\"Id\" type=\"s\" access=\"read\"/>\n"        \
-        "  <property name=\"Names\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"Following\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"Requires\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"RequiresOverridable\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Requisite\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"RequisiteOverridable\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Wants\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"BindsTo\" type=\"as\" access=\"read\"/>\n"  \
-        "  <property name=\"PartOf\" type=\"as\" access=\"read\"/>\n"   \
-        "  <property name=\"RequiredBy\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"RequiredByOverridable\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"WantedBy\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"BoundBy\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ConsistsOf\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Conflicts\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ConflictedBy\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Before\" type=\"as\" access=\"read\"/>\n"   \
-        "  <property name=\"After\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"OnFailure\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"Triggers\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"TriggeredBy\" type=\"as\" access=\"read\"/>\n"    \
-        "  <property name=\"PropagatesReloadTo\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"ReloadPropagatedFrom\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"RequiresMountsFor\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Description\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SourcePath\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"DropInPaths\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"Documentation\" type=\"as\" access=\"read\"/>\n" \
-        "  <property name=\"LoadState\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveState\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"SubState\" type=\"s\" access=\"read\"/>\n"  \
-        "  <property name=\"FragmentPath\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"UnitFileState\" type=\"s\" access=\"read\"/>\n" \
-        "  <property name=\"InactiveExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InactiveExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveEnterTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveEnterTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveExitTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ActiveExitTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InactiveEnterTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"InactiveEnterTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"CanStart\" type=\"b\" access=\"read\"/>\n"  \
-        "  <property name=\"CanStop\" type=\"b\" access=\"read\"/>\n"   \
-        "  <property name=\"CanReload\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"CanIsolate\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Job\" type=\"(uo)\" access=\"read\"/>\n"    \
-        "  <property name=\"StopWhenUnneeded\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"RefuseManualStart\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"RefuseManualStop\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"AllowIsolate\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"DefaultDependencies\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"OnFailureIsolate\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"IgnoreOnIsolate\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"IgnoreOnSnapshot\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"NeedDaemonReload\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"JobTimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ConditionTimestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ConditionTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"ConditionResult\" type=\"b\" access=\"read\"/>\n" \
-        "  <property name=\"Conditions\" type=\"a(sbbsi)\" access=\"read\"/>\n" \
-        "  <property name=\"LoadError\" type=\"(ss)\" access=\"read\"/>\n" \
-        "  <property name=\"Transient\" type=\"b\" access=\"read\"/>\n" \
-        " </interface>\n"
-
-#define BUS_UNIT_CGROUP_INTERFACE                                       \
-        "  <property name=\"Slice\" type=\"s\" access=\"read\"/>\n"     \
-        "  <property name=\"ControlGroup\" type=\"s\" access=\"read\"/>\n"
-
-#define BUS_UNIT_INTERFACES_LIST                \
-        BUS_GENERIC_INTERFACES_LIST             \
-        "org.freedesktop.systemd1.Unit\0"
-
-extern const BusProperty bus_unit_properties[];
-extern const BusProperty bus_unit_cgroup_properties[];
+extern const sd_bus_vtable bus_unit_vtable[];
+extern const sd_bus_vtable bus_unit_cgroup_vtable[];
 
 void bus_unit_send_change_signal(Unit *u);
 void bus_unit_send_removed_signal(Unit *u);
 
-DBusHandlerResult bus_unit_queue_job(DBusConnection *connection, DBusMessage *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible);
-
-int bus_unit_set_properties(Unit *u, DBusMessageIter *i, UnitSetPropertiesMode mode, bool commit, DBusError *error);
-
-extern const DBusObjectPathVTable bus_unit_vtable;
+int bus_unit_method_start_generic(sd_bus *bus, sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible);
+int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata);
+int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata);
 
-extern const char bus_unit_interface[];
+int bus_unit_queue_job(sd_bus *bus, sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible);
+int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error);
+int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata);
index b0ae3e1ae7fd5975d796b1123cd460cfb4b9bedd..35d185a601a950be0100350422ead136c264836b 100644 (file)
@@ -23,9 +23,8 @@
 #include <sys/timerfd.h>
 #include <errno.h>
 #include <unistd.h>
-#include <dbus/dbus.h>
 
-#include "dbus.h"
+#include "sd-bus.h"
 #include "log.h"
 #include "strv.h"
 #include "mkdir.h"
 #include "dbus-unit.h"
 #include "dbus-job.h"
 #include "dbus-manager.h"
-#include "dbus-service.h"
-#include "dbus-socket.h"
-#include "dbus-target.h"
-#include "dbus-device.h"
-#include "dbus-mount.h"
-#include "dbus-automount.h"
-#include "dbus-snapshot.h"
-#include "dbus-swap.h"
-#include "dbus-timer.h"
-#include "dbus-path.h"
-#include "bus-errors.h"
+#include "dbus-execute.h"
+#include "dbus-kill.h"
+#include "dbus-cgroup.h"
 #include "special.h"
-#include "dbus-common.h"
+#include "dbus.h"
+#include "bus-util.h"
+#include "bus-error.h"
+#include "bus-errors.h"
+#include "strxcpyx.h"
+#include "dbus-client-track.h"
 
 #define CONNECTIONS_MAX 512
 
-/* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
-#define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
-/* Only used as a fallback */
-#define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
-
-static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
-static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
-
-const char *const bus_interface_table[] = {
-        "org.freedesktop.DBus.Properties",     bus_properties_interface,
-        "org.freedesktop.DBus.Introspectable", bus_introspectable_interface,
-        "org.freedesktop.systemd1.Manager",    bus_manager_interface,
-        "org.freedesktop.systemd1.Job",        bus_job_interface,
-        "org.freedesktop.systemd1.Unit",       bus_unit_interface,
-        "org.freedesktop.systemd1.Service",    bus_service_interface,
-        "org.freedesktop.systemd1.Socket",     bus_socket_interface,
-        "org.freedesktop.systemd1.Target",     bus_target_interface,
-        "org.freedesktop.systemd1.Device",     bus_device_interface,
-        "org.freedesktop.systemd1.Mount",      bus_mount_interface,
-        "org.freedesktop.systemd1.Automount",  bus_automount_interface,
-        "org.freedesktop.systemd1.Snapshot",   bus_snapshot_interface,
-        "org.freedesktop.systemd1.Swap",       bus_swap_interface,
-        "org.freedesktop.systemd1.Timer",      bus_timer_interface,
-        "org.freedesktop.systemd1.Path",       bus_path_interface,
-        NULL
-};
-
-static void bus_done_api(Manager *m);
-static void bus_done_system(Manager *m);
-static void bus_done_private(Manager *m);
-static void shutdown_connection(Manager *m, DBusConnection *c);
-
-static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data)  {
-        Manager *m = data;
+static void destroy_bus(Manager *m, sd_bus **bus);
+
+int bus_send_queued_message(Manager *m) {
+        int r;
 
-        assert(bus);
         assert(m);
 
-        /* We maintain two sets, one for those connections where we
-         * requested a dispatch, and another where we didn't. And then,
-         * we move the connections between the two sets. */
+        if (!m->queued_message)
+                return 0;
 
-        if (status == DBUS_DISPATCH_COMPLETE)
-                set_move_one(m->bus_connections, m->bus_connections_for_dispatch, bus);
-        else
-                set_move_one(m->bus_connections_for_dispatch, m->bus_connections, bus);
-}
+        assert(m->queued_message_bus);
 
-void bus_watch_event(Manager *m, Watch *w, int events) {
-        assert(m);
-        assert(w);
+        /* If we cannot get rid of this message we won't dispatch any
+         * D-Bus messages, so that we won't end up wanting to queue
+         * another message. */
 
-        /* This is called by the event loop whenever there is
-         * something happening on D-Bus' file handles. */
+        r = sd_bus_send(m->queued_message_bus, m->queued_message, NULL);
+        if (r < 0)
+                log_warning("Failed to send queued message: %s", strerror(-r));
 
-        if (!dbus_watch_get_enabled(w->data.bus_watch))
-                return;
+        m->queued_message = sd_bus_message_unref(m->queued_message);
+        m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
 
-        dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
+        return 0;
 }
 
-static dbus_bool_t bus_add_watch(DBusWatch *bus_watch, void *data) {
-        Manager *m = data;
-        Watch *w;
-        struct epoll_event ev;
+static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        const char *cgroup;
+        int r;
 
-        assert(bus_watch);
+        assert(bus);
+        assert(message);
         assert(m);
 
-        if (!(w = new0(Watch, 1)))
-                return FALSE;
-
-        w->fd = dbus_watch_get_unix_fd(bus_watch);
-        w->type = WATCH_DBUS_WATCH;
-        w->data.bus_watch = bus_watch;
+        r = sd_bus_message_read(message, "s", &cgroup);
+        if (r < 0) {
+                bus_log_parse_error(r);
+                return 0;
+        }
 
-        zero(ev);
-        ev.events = bus_flags_to_events(bus_watch);
-        ev.data.ptr = w;
+        manager_notify_cgroup_empty(m, cgroup);
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
+        if (m->running_as == SYSTEMD_SYSTEM && m->system_bus) {
+                /* If we are running as system manager, forward the
+                 * message to the system bus */
 
-                if (errno != EEXIST) {
-                        free(w);
-                        return FALSE;
-                }
+                r = sd_bus_send(m->system_bus, message, NULL);
+                if (r < 0)
+                        log_warning("Failed to forward Released message: %s", strerror(-r));
+        }
 
-                /* Hmm, bloody D-Bus creates multiple watches on the
-                 * same fd. epoll() does not like that. As a dirty
-                 * hack we simply dup() the fd and hence get a second
-                 * one we can safely add to the epoll(). */
+        return 0;
+}
 
-                if ((w->fd = dup(w->fd)) < 0) {
-                        free(w);
-                        return FALSE;
-                }
+static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
 
-                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
-                        close_nointr_nofail(w->fd);
-                        free(w);
-                        return FALSE;
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                w->fd_is_dupped = true;
+        if (bus == m->api_bus)
+                destroy_bus(m, &m->api_bus);
+        if (bus == m->system_bus)
+                destroy_bus(m, &m->system_bus);
+        if (set_remove(m->private_buses, bus)) {
+                log_debug("Got disconnect on private connection.");
+                destroy_bus(m, &bus);
         }
 
-        dbus_watch_set_data(bus_watch, w, NULL);
-
-        return TRUE;
+        return 0;
 }
 
-static void bus_remove_watch(DBusWatch *bus_watch, void *data) {
-        Manager *m = data;
-        Watch *w;
+static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        const char *name, *old_owner, *new_owner;
+        Manager *m = userdata;
+        int r;
 
-        assert(bus_watch);
+        assert(bus);
+        assert(message);
         assert(m);
 
-        w = dbus_watch_get_data(bus_watch);
-        if (!w)
-                return;
-
-        assert(w->type == WATCH_DBUS_WATCH);
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
+        r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner);
+        if (r < 0) {
+                bus_log_parse_error(r);
+                return 0;
+        }
 
-        if (w->fd_is_dupped)
-                close_nointr_nofail(w->fd);
+        manager_dispatch_bus_name_owner_changed(
+                        m, name,
+                        isempty(old_owner) ? NULL : old_owner,
+                        isempty(new_owner) ? NULL : new_owner);
 
-        free(w);
+        return 0;
 }
 
-static void bus_toggle_watch(DBusWatch *bus_watch, void *data) {
-        Manager *m = data;
-        Watch *w;
-        struct epoll_event ev;
+static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        Manager *m = userdata;
+        const char *name;
+        Unit *u;
+        int r;
 
-        assert(bus_watch);
+        assert(bus);
+        assert(message);
         assert(m);
 
-        w = dbus_watch_get_data(bus_watch);
-        if (!w)
-                return;
-
-        assert(w->type == WATCH_DBUS_WATCH);
-
-        zero(ev);
-        ev.events = bus_flags_to_events(bus_watch);
-        ev.data.ptr = w;
-
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_MOD, w->fd, &ev) == 0);
-}
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0) {
+                bus_log_parse_error(r);
+                return 0;
+        }
 
-static int bus_timeout_arm(Manager *m, Watch *w) {
-        struct itimerspec its = {};
+        if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
+            manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
+                r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
+                goto failed;
+        }
 
-        assert(m);
-        assert(w);
+        r = manager_load_unit(m, name, NULL, &error, &u);
+        if (r < 0)
+                goto failed;
 
-        if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
-                timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
-                its.it_interval = its.it_value;
+        if (u->refuse_manual_start) {
+                r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %u may be requested by dependency only.", u->id);
+                goto failed;
         }
 
-        if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
-                return -errno;
+        r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
+        if (r < 0)
+                goto failed;
 
+        /* Successfully queued, that's it for us */
         return 0;
-}
 
-void bus_timeout_event(Manager *m, Watch *w, int events) {
-        assert(m);
-        assert(w);
+failed:
+        if (!sd_bus_error_is_set(&error))
+                sd_bus_error_set_errno(&error, r);
 
-        /* This is called by the event loop whenever there is
-         * something happening on D-Bus' file handles. */
+        log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
 
-        if (!(dbus_timeout_get_enabled(w->data.bus_timeout)))
-                return;
+        r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure", &reply);
+        if (r < 0) {
+                bus_log_create_error(r);
+                return 0;
+        }
+
+        r = sd_bus_message_append(reply, "sss", error.name, error.message);
+        if (r < 0) {
+                bus_log_create_error(r);
+                return 0;
+        }
+
+        r = sd_bus_send_to(bus, reply, "org.freedesktop.DBus", NULL);
+        if (r < 0) {
+                log_error("Failed to respond with to bus activation request: %s", strerror(-r));
+                return r;
+        }
 
-        dbus_timeout_handle(w->data.bus_timeout);
+        return 0;
 }
 
-static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
-        Manager *m = data;
-        Watch *w;
-        struct epoll_event ev;
+static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        Job *j;
+        int r;
 
-        assert(timeout);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        if (!(w = new0(Watch, 1)))
-                return FALSE;
-
-        if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
-                goto fail;
+        r = manager_get_job_from_dbus_path(m, path, &j);
+        if (r < 0)
+                return 0;
 
-        w->type = WATCH_DBUS_TIMEOUT;
-        w->data.bus_timeout = timeout;
+        *found = j;
+        return 1;
+}
 
-        if (bus_timeout_arm(m, w) < 0)
-                goto fail;
+static Unit *find_unit(Manager *m, sd_bus *bus, const char *path) {
+        Unit *u;
+        int r;
 
-        zero(ev);
-        ev.events = EPOLLIN;
-        ev.data.ptr = w;
+        assert(m);
+        assert(bus);
+        assert(path);
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
-                goto fail;
+        if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
+                sd_bus_message *message;
+                pid_t pid;
 
-        dbus_timeout_set_data(timeout, w, NULL);
+                message = sd_bus_get_current(bus);
+                if (!message)
+                        return NULL;
 
-        return TRUE;
+                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
+                if (r < 0)
+                        return NULL;
 
-fail:
-        if (w->fd >= 0)
-                close_nointr_nofail(w->fd);
+                u = manager_get_unit_by_pid(m, pid);
+        } else {
+                r = manager_load_unit_from_dbus_path(m, path, NULL, &u);
+                if (r < 0)
+                        return NULL;
+        }
 
-        free(w);
-        return FALSE;
+        return u;
 }
 
-static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
-        Manager *m = data;
-        Watch *w;
+static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        Unit *u;
 
-        assert(timeout);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        w = dbus_timeout_get_data(timeout);
-        if (!w)
-                return;
-
-        assert(w->type == WATCH_DBUS_TIMEOUT);
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
-        close_nointr_nofail(w->fd);
-        free(w);
+        *found = u;
+        return 1;
 }
 
-static void bus_toggle_timeout(DBusTimeout *timeout, void *data) {
-        Manager *m = data;
-        Watch *w;
-        int r;
+static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        Unit *u;
 
-        assert(timeout);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        w = dbus_timeout_get_data(timeout);
-        if (!w)
-                return;
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-        assert(w->type == WATCH_DBUS_TIMEOUT);
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-        if ((r = bus_timeout_arm(m, w)) < 0)
-                log_error("Failed to rearm timer: %s", strerror(-r));
+        *found = u;
+        return 1;
 }
 
-static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
-        Manager *m = data;
-        DBusError error;
-        DBusMessage *reply = NULL;
+static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        Unit *u;
 
-        assert(connection);
-        assert(message);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        dbus_error_init(&error);
-
-        if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
-            dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
-                log_debug("Got D-Bus request: %s.%s() on %s",
-                          dbus_message_get_interface(message),
-                          dbus_message_get_member(message),
-                          dbus_message_get_path(message));
-
-        if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
-                log_debug("API D-Bus connection terminated.");
-                bus_done_api(m);
-
-        } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
-                const char *name, *old_owner, *new_owner;
-
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_STRING, &name,
-                                           DBUS_TYPE_STRING, &old_owner,
-                                           DBUS_TYPE_STRING, &new_owner,
-                                           DBUS_TYPE_INVALID))
-                        log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
-                else  {
-                        if (set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) name))
-                                log_debug("Subscription client vanished: %s (left: %u)", name, set_size(BUS_CONNECTION_SUBSCRIBED(m, connection)));
-
-                        if (old_owner[0] == 0)
-                                old_owner = NULL;
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-                        if (new_owner[0] == 0)
-                                new_owner = NULL;
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-                        manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner);
-                }
-        } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
-                const char *name;
-
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_STRING, &name,
-                                           DBUS_TYPE_INVALID))
-                        log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
-                else  {
-                        int r;
-                        Unit *u;
-
-                        log_debug("Got D-Bus activation request for %s", name);
-
-                        if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
-                            manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
-                                r = -EADDRNOTAVAIL;
-                                dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
-                        } else {
-                                r = manager_load_unit(m, name, NULL, &error, &u);
-
-                                if (r >= 0 && u->refuse_manual_start)
-                                        r = -EPERM;
-
-                                if (r >= 0)
-                                        r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
-                        }
+        if (!unit_get_cgroup_context(u))
+                return 0;
 
-                        if (r < 0) {
-                                const char *id, *text;
+        *found = u;
+        return 1;
+}
 
-                                log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
+static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        CGroupContext *c;
+        Unit *u;
 
-                                if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
-                                        goto oom;
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
+        assert(m);
 
-                                id = error.name ? error.name : bus_errno_to_dbus(r);
-                                text = bus_error(&error, r);
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-                                if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
-                                    !dbus_message_append_args(reply,
-                                                              DBUS_TYPE_STRING, &name,
-                                                              DBUS_TYPE_STRING, &id,
-                                                              DBUS_TYPE_STRING, &text,
-                                                              DBUS_TYPE_INVALID))
-                                        goto oom;
-                        }
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-                        /* On success we don't do anything, the service will be spawned now */
-                }
-        }
+        c = unit_get_cgroup_context(u);
+        if (!c)
+                return 0;
 
-        dbus_error_free(&error);
+        *found = c;
+        return 1;
+}
 
-        if (reply) {
-                if (!bus_maybe_send_reply(connection, message, reply))
-                        goto oom;
+static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        ExecContext *c;
+        Unit *u;
 
-                dbus_message_unref(reply);
-        }
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
+        assert(m);
 
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-oom:
-        if (reply)
-                dbus_message_unref(reply);
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-        dbus_error_free(&error);
+        c = unit_get_exec_context(u);
+        if (!c)
+                return 0;
 
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        *found = c;
+        return 1;
 }
 
-static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
-        Manager *m = data;
-        DBusError error;
+static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        Manager *m = userdata;
+        KillContext *c;
+        Unit *u;
 
-        assert(connection);
-        assert(message);
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
         assert(m);
 
-        dbus_error_init(&error);
-
-        if (m->api_bus != m->system_bus &&
-            (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
-             dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL))
-                log_debug("Got D-Bus request on system bus: %s.%s() on %s",
-                          dbus_message_get_interface(message),
-                          dbus_message_get_member(message),
-                          dbus_message_get_path(message));
+        u = find_unit(m, bus, path);
+        if (!u)
+                return 0;
 
-        if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
-                log_debug("System D-Bus connection terminated.");
-                bus_done_system(m);
+        if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface))
+                return 0;
 
-        } else if (m->running_as != SYSTEMD_SYSTEM &&
-                   dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
+        c = unit_get_kill_context(u);
+        if (!c)
+                return 0;
 
-                const char *cgroup;
+        *found = c;
+        return 1;
+}
 
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_STRING, &cgroup,
-                                           DBUS_TYPE_INVALID))
-                        log_error("Failed to parse Released message: %s", bus_error_message(&error));
-                else
-                        manager_notify_cgroup_empty(m, cgroup);
-        }
+static int bus_job_enumerate(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
+        _cleanup_free_ char **l = NULL;
+        Manager *m = userdata;
+        unsigned k = 0;
+        Iterator i;
+        Job *j;
 
-        dbus_error_free(&error);
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
+        l = new0(char*, hashmap_size(m->jobs)+1);
+        if (!l)
+                return -ENOMEM;
 
-static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
-        Manager *m = data;
-        DBusError error;
+        HASHMAP_FOREACH(j, m->jobs, i) {
+                l[k] = job_dbus_path(j);
+                if (!l[k])
+                        return -ENOMEM;
 
-        assert(connection);
-        assert(message);
-        assert(m);
+                k++;
+        }
 
-        dbus_error_init(&error);
+        assert(hashmap_size(m->jobs) == k);
 
-        if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
-            dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
-                log_debug("Got D-Bus request: %s.%s() on %s",
-                          dbus_message_get_interface(message),
-                          dbus_message_get_member(message),
-                          dbus_message_get_path(message));
+        *nodes = l;
+        l = NULL;
 
-        if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
-                shutdown_connection(m, connection);
-        else if (m->running_as == SYSTEMD_SYSTEM &&
-                 dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
+        return k;
+}
 
-                const char *cgroup;
+static int bus_unit_enumerate(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
+        _cleanup_free_ char **l = NULL;
+        Manager *m = userdata;
+        unsigned k = 0;
+        Iterator i;
+        Unit *u;
 
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_STRING, &cgroup,
-                                           DBUS_TYPE_INVALID))
-                        log_error("Failed to parse Released message: %s", bus_error_message(&error));
-                else
-                        manager_notify_cgroup_empty(m, cgroup);
+        l = new0(char*, hashmap_size(m->units)+1);
+        if (!l)
+                return -ENOMEM;
 
-                /* Forward the message to the system bus, so that user
-                 * instances are notified as well */
+        HASHMAP_FOREACH(u, m->units, i) {
+                l[k] = unit_dbus_path(u);
+                if (!l[k])
+                        return -ENOMEM;
 
-                if (m->system_bus)
-                        dbus_connection_send(m->system_bus, message, NULL);
+                k++;
         }
 
-        dbus_error_free(&error);
+        *nodes = l;
+        l = NULL;
 
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        return k;
 }
 
-unsigned bus_dispatch(Manager *m) {
-        DBusConnection *c;
+static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
+        UnitType t;
+        int r;
 
         assert(m);
+        assert(bus);
 
-        if (m->queued_message) {
-                /* If we cannot get rid of this message we won't
-                 * dispatch any D-Bus messages, so that we won't end
-                 * up wanting to queue another message. */
-
-                if (m->queued_message_connection)
-                        if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
-                                return 0;
-
-                dbus_message_unref(m->queued_message);
-                m->queued_message = NULL;
-                m->queued_message_connection = NULL;
+        r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
+        if (r < 0) {
+                log_error("Failed to register Manager vtable: %s", strerror(-r));
+                return r;
         }
 
-        if ((c = set_first(m->bus_connections_for_dispatch))) {
-                if (dbus_connection_dispatch(c) == DBUS_DISPATCH_COMPLETE)
-                        set_move_one(m->bus_connections, m->bus_connections_for_dispatch, c);
-
-                return 1;
+        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
+        if (r < 0) {
+                log_error("Failed to register Job vtable: %s", strerror(-r));
+                return r;
         }
 
-        return 0;
-}
-
-static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
-        DBusMessage *reply;
-        DBusError error;
-
-        dbus_error_init(&error);
-
-        assert_se(reply = dbus_pending_call_steal_reply(pending));
+        r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
+        if (r < 0) {
+                log_error("Failed to add job enumerator: %s", strerror(-r));
+                return r;
+        }
 
-        switch (dbus_message_get_type(reply)) {
+        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
+        if (r < 0) {
+                log_error("Failed to register Unit vtable: %s", strerror(-r));
+                return r;
+        }
 
-        case DBUS_MESSAGE_TYPE_ERROR:
+        r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
+        if (r < 0) {
+                log_error("Failed to add job enumerator: %s", strerror(-r));
+                return r;
+        }
 
-                assert_se(dbus_set_error_from_message(&error, reply));
-                log_warning("RequestName() failed: %s", bus_error_message(&error));
-                break;
+        for (t = 0; t < _UNIT_TYPE_MAX; t++) {
+                r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
+                if (r < 0)  {
+                        log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                        return r;
+                }
 
-        case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
-                uint32_t r;
+                if (unit_vtable[t]->cgroup_context_offset > 0) {
+                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
+                        if (r < 0) {
+                                log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                                return r;
+                        }
 
-                if (!dbus_message_get_args(reply,
-                                           &error,
-                                           DBUS_TYPE_UINT32, &r,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
-                        break;
+                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
+                        if (r < 0) {
+                                log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                                return r;
+                        }
                 }
 
-                if (r == 1)
-                        log_debug("Successfully acquired name.");
-                else
-                        log_error("Name already owned.");
-
-                break;
-        }
+                if (unit_vtable[t]->exec_context_offset > 0) {
+                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
+                        if (r < 0) {
+                                log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                                return r;
+                        }
+                }
 
-        default:
-                assert_not_reached("Invalid reply message");
+                if (unit_vtable[t]->kill_context_offset > 0) {
+                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
+                        if (r < 0) {
+                                log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
+                                return r;
+                        }
+                }
         }
 
-        dbus_message_unref(reply);
-        dbus_error_free(&error);
+        return 0;
 }
 
-static int request_name(Manager *m) {
-        const char *name = "org.freedesktop.systemd1";
-        /* Allow replacing of our name, to ease implementation of
-         * reexecution, where we keep the old connection open until
-         * after the new connection is set up and the name installed
-         * to allow clients to synchronously wait for reexecution to
-         * finish */
-        uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
-        DBusMessage *message = NULL;
-        DBusPendingCall *pending = NULL;
-
-        if (!(message = dbus_message_new_method_call(
-                              DBUS_SERVICE_DBUS,
-                              DBUS_PATH_DBUS,
-                              DBUS_INTERFACE_DBUS,
-                              "RequestName")))
-                goto oom;
-
-        if (!dbus_message_append_args(
-                            message,
-                            DBUS_TYPE_STRING, &name,
-                            DBUS_TYPE_UINT32, &flags,
-                            DBUS_TYPE_INVALID))
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
-                goto oom;
-
-        if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
-                goto oom;
-
-        dbus_message_unref(message);
-        dbus_pending_call_unref(pending);
+static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
+        int r;
 
-        /* We simple ask for the name and don't wait for it. Sooner or
-         * later we'll have it. */
+        assert(m);
+        assert(bus);
 
-        return 0;
+        r = sd_bus_add_match(
+                        bus,
+                        "type='signal',"
+                        "path='/org/freedesktop/DBus/Local',"
+                        "interface='org.freedesktop.DBus.Local',"
+                        "member='Disconnected'",
+                        signal_disconnected, m);
 
-oom:
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
+        if (r < 0) {
+                log_error("Failed to register match for Disconnected message: %s", strerror(-r));
+                return r;
         }
 
-        if (message)
-                dbus_message_unref(message);
-
-        return -ENOMEM;
+        return 0;
 }
 
-static void query_name_list_pending_cb(DBusPendingCall *pending, void *userdata) {
-        DBusMessage *reply;
-        DBusError error;
+static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        _cleanup_bus_unref_ sd_bus *bus = NULL;
+        _cleanup_close_ int nfd = -1;
         Manager *m = userdata;
+        sd_id128_t id;
+        int r;
 
+        assert(s);
         assert(m);
 
-        dbus_error_init(&error);
+        nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+        if (nfd < 0) {
+                log_warning("Failed to accept private connection, ignoring: %m");
+                return 0;
+        }
 
-        assert_se(reply = dbus_pending_call_steal_reply(pending));
+        if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
+                log_warning("Too many concurrent connections, refusing");
+                return 0;
+        }
 
-        switch (dbus_message_get_type(reply)) {
+        r = set_ensure_allocated(&m->private_buses, trivial_hash_func, trivial_compare_func);
+        if (r < 0) {
+                log_oom();
+                return 0;
+        }
 
-        case DBUS_MESSAGE_TYPE_ERROR:
+        r = sd_bus_new(&bus);
+        if (r < 0) {
+                log_warning("Failed to allocate new private connection bus: %s", strerror(-r));
+                return 0;
+        }
 
-                assert_se(dbus_set_error_from_message(&error, reply));
-                log_warning("ListNames() failed: %s", bus_error_message(&error));
-                break;
+        r = sd_bus_set_fd(bus, nfd, nfd);
+        if (r < 0) {
+                log_warning("Failed to set fd on new connection bus: %s", strerror(-r));
+                return 0;
+        }
 
-        case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
-                int r;
-                char **l;
+        nfd = -1;
 
-                if ((r = bus_parse_strv(reply, &l)) < 0)
-                        log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
-                else {
-                        char **t;
+        r = bus_check_peercred(bus);
+        if (r < 0) {
+                log_warning("Incoming private connection from unprivileged client, refusing: %s", strerror(-r));
+                return 0;
+        }
 
-                        STRV_FOREACH(t, l)
-                                /* This is a bit hacky, we say the
-                                 * owner of the name is the name
-                                 * itself, because we don't want the
-                                 * extra traffic to figure out the
-                                 * real owner. */
-                                manager_dispatch_bus_name_owner_changed(m, *t, NULL, *t);
+        assert_se(sd_id128_randomize(&id) >= 0);
 
-                        strv_free(l);
-                }
+        r = sd_bus_set_server(bus, 1, id);
+        if (r < 0) {
+                log_warning("Failed to enable server support for new connection bus: %s", strerror(-r));
+                return 0;
+        }
 
-                break;
+        r = sd_bus_start(bus);
+        if (r < 0) {
+                log_warning("Failed to start new connection bus: %s", strerror(-r));
+                return 0;
         }
 
-        default:
-                assert_not_reached("Invalid reply message");
+        r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
+        if (r < 0) {
+                log_warning("Failed to attach new connection bus to event loop: %s", strerror(-r));
+                return 0;
         }
 
-        dbus_message_unref(reply);
-        dbus_error_free(&error);
-}
+        if (m->running_as == SYSTEMD_SYSTEM) {
+                /* When we run as system instance we get the Released
+                 * signal via a direct connection */
+
+                r = sd_bus_add_match(
+                                bus,
+                                "type='signal',"
+                                "interface='org.freedesktop.systemd1.Agent',"
+                                "member='Released',"
+                                "path='/org/freedesktop/systemd1/agent'",
+                                signal_agent_released, m);
+
+                if (r < 0) {
+                        log_warning("Failed to register Released match on new connection bus: %s", strerror(-r));
+                        return 0;
+                }
+        }
 
-static int query_name_list(Manager *m) {
-        DBusMessage *message = NULL;
-        DBusPendingCall *pending = NULL;
+        r = bus_setup_disconnected_match(m, bus);
+        if (r < 0)
+                return 0;
 
-        /* Asks for the currently installed bus names */
+        r = bus_setup_api_vtables(m, bus);
+        if (r < 0) {
+                log_warning("Failed to set up API vtables on new connection bus: %s", strerror(-r));
+                return 0;
+        }
 
-        if (!(message = dbus_message_new_method_call(
-                              DBUS_SERVICE_DBUS,
-                              DBUS_PATH_DBUS,
-                              DBUS_INTERFACE_DBUS,
-                              "ListNames")))
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
-                goto oom;
-
-        if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
-                goto oom;
-
-        dbus_message_unref(message);
-        dbus_pending_call_unref(pending);
-
-        /* We simple ask for the list and don't wait for it. Sooner or
-         * later we'll get it. */
-
-        return 0;
-
-oom:
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
+        r = set_put(m->private_buses, bus);
+        if (r < 0) {
+                log_warning("Failed to add new conenction bus to set: %s", strerror(-r));
+                return 0;
         }
 
-        if (message)
-                dbus_message_unref(message);
+        bus = NULL;
 
-        return -ENOMEM;
-}
+        log_debug("Accepted new private connection.");
 
-static int bus_setup_loop(Manager *m, DBusConnection *bus) {
-        assert(m);
-        assert(bus);
-
-        dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
-        if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
-            !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
-                return log_oom();
-
-        if (set_put(m->bus_connections_for_dispatch, bus) < 0)
-                return log_oom();
-
-        dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
         return 0;
 }
 
-static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
-        return uid == 0 || uid == geteuid();
-}
-
-static void bus_new_connection(
-                DBusServer *server,
-                DBusConnection *new_connection,
-                void *data) {
-
-        Manager *m = data;
+static int bus_list_names(Manager *m, sd_bus *bus) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        const char *name;
+        int r;
 
         assert(m);
+        assert(bus);
 
-        if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
-                log_error("Too many concurrent connections.");
-                return;
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/org/freedesktop/DBus",
+                        "org.freedesktop.DBus",
+                        "ListNames",
+                        &error, &reply,
+                        NULL);
+        if (r < 0) {
+                log_error("Failed to get initial list of names: %s", bus_error_message(&error, r));
+                return r;
         }
 
-        dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
-
-        if (bus_setup_loop(m, new_connection) < 0)
-                return;
+        r = sd_bus_message_enter_container(reply, 'a', "s");
+        if (r < 0)
+                return bus_log_parse_error(r);
 
-        if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
-            !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
-            !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
-            !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
-                log_oom();
-                return;
-        }
+        /* This is a bit hacky, we say the owner of the name is the
+         * name itself, because we don't want the extra traffic to
+         * figure out the real owner. */
+        while ((r = sd_bus_message_read(reply, "s", &name)) > 0)
+                manager_dispatch_bus_name_owner_changed(m, name, NULL, name);
+        if (r < 0)
+                return bus_log_parse_error(r);
 
-        log_debug("Accepted connection on private bus.");
+        r = sd_bus_message_exit_container(reply);
+        if (r < 0)
+                return bus_log_parse_error(r);
 
-        dbus_connection_ref(new_connection);
+        return 0;
 }
 
-static int init_registered_system_bus(Manager *m) {
-        char *id = NULL;
+static int bus_setup_api(Manager *m, sd_bus *bus) {
+        int r;
 
-        if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
-                return log_oom();
+        assert(m);
+        assert(bus);
 
-        if (m->running_as != SYSTEMD_SYSTEM) {
-                DBusError error;
+        r = bus_setup_api_vtables(m, bus);
+        if (r < 0)
+                return r;
 
-                dbus_error_init(&error);
+        r = sd_bus_add_match(
+                        bus,
+                        "type='signal',"
+                        "sender='org.freedesktop.DBus',"
+                        "path='/org/freedesktop/DBus',"
+                        "interface='org.freedesktop.DBus',"
+                        "member='NameOwnerChanged'",
+                        signal_name_owner_changed, m);
+        if (r < 0)
+                log_warning("Failed to subscribe to NameOwnerChanged signal: %s", strerror(-r));
+
+        r = sd_bus_add_match(
+                        bus,
+                        "type='signal',"
+                        "sender='org.freedesktop.DBus',"
+                        "path='/org/freedesktop/DBus',"
+                        "interface='org.freedesktop.systemd1.Activator',"
+                        "member='ActivationRequest'",
+                        signal_activation_request, m);
+        if (r < 0)
+                log_warning("Failed to subscribe to activation signal: %s", strerror(-r));
 
-                dbus_bus_add_match(m->system_bus,
-                                   "type='signal',"
-                                   "interface='org.freedesktop.systemd1.Agent',"
-                                   "member='Released',"
-                                   "path='/org/freedesktop/systemd1/agent'",
-                                   &error);
+        /* Allow replacing of our name, to ease implementation of
+         * reexecution, where we keep the old connection open until
+         * after the new connection is set up and the name installed
+         * to allow clients to synchronously wait for reexecution to
+         * finish */
+        r = sd_bus_request_name(bus,"org.freedesktop.systemd1", SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING);
+        if (r < 0) {
+                log_error("Failed to register name: %s", strerror(-r));
+                return r;
+        }
 
-                if (dbus_error_is_set(&error)) {
-                        log_error("Failed to register match: %s", bus_error_message(&error));
-                        dbus_error_free(&error);
-                        return -1;
-                }
+        if (r != SD_BUS_NAME_PRIMARY_OWNER) {
+                log_error("Failed to acquire name.");
+                return -EEXIST;
         }
 
-        log_debug("Successfully connected to system D-Bus bus %s as %s",
-                 strnull((id = dbus_connection_get_server_id(m->system_bus))),
-                 strnull(dbus_bus_get_unique_name(m->system_bus)));
-        dbus_free(id);
+        bus_list_names(m, bus);
 
+        log_debug("Successfully connected to API bus.");
         return 0;
 }
 
-static int init_registered_api_bus(Manager *m) {
+static int bus_init_api(Manager *m) {
+        _cleanup_bus_unref_ sd_bus *bus = NULL;
         int r;
 
-        if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
-            !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
-            !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
-            !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
-                return log_oom();
-
-        /* Get NameOwnerChange messages */
-        dbus_bus_add_match(m->api_bus,
-                           "type='signal',"
-                           "sender='"DBUS_SERVICE_DBUS"',"
-                           "interface='"DBUS_INTERFACE_DBUS"',"
-                           "member='NameOwnerChanged',"
-                           "path='"DBUS_PATH_DBUS"'",
-                           NULL);
-
-        /* Get activation requests */
-        dbus_bus_add_match(m->api_bus,
-                           "type='signal',"
-                           "sender='"DBUS_SERVICE_DBUS"',"
-                           "interface='org.freedesktop.systemd1.Activator',"
-                           "member='ActivationRequest',"
-                           "path='"DBUS_PATH_DBUS"'",
-                           NULL);
-
-        r = request_name(m);
-        if (r < 0)
-                return r;
-
-        r = query_name_list(m);
-        if (r < 0)
-                return r;
-
-        if (m->running_as == SYSTEMD_USER) {
-                char *id = NULL;
-
-                log_debug("Successfully connected to API D-Bus bus %s as %s",
-                         strnull((id = dbus_connection_get_server_id(m->api_bus))),
-                         strnull(dbus_bus_get_unique_name(m->api_bus)));
-                dbus_free(id);
-        } else
-                log_debug("Successfully initialized API on the system bus");
+        if (m->api_bus)
+                return 0;
 
-        return 0;
-}
+        /* The API and system bus is the same if we are running in system mode */
+        if (m->running_as == SYSTEMD_SYSTEM && m->system_bus)
+                bus = sd_bus_ref(m->system_bus);
+        else {
+                if (m->running_as == SYSTEMD_SYSTEM)
+                        r = sd_bus_open_system(&bus);
+                else
+                        r = sd_bus_open_user(&bus);
 
-static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
-        Manager *m = userdata;
-        DBusConnection **conn;
-        DBusMessage *reply;
-        DBusError error;
-        const char *name;
-        int r = 0;
-
-        dbus_error_init(&error);
-
-        conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
-        assert(conn == &m->system_bus || conn == &m->api_bus);
-
-        reply = dbus_pending_call_steal_reply(pending);
-
-        switch (dbus_message_get_type(reply)) {
-        case DBUS_MESSAGE_TYPE_ERROR:
-                assert_se(dbus_set_error_from_message(&error, reply));
-                log_warning("Failed to register to bus: %s", bus_error_message(&error));
-                r = -1;
-                break;
-        case DBUS_MESSAGE_TYPE_METHOD_RETURN:
-                if (!dbus_message_get_args(reply, &error,
-                                           DBUS_TYPE_STRING, &name,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
-                        r = -1;
-                        break;
+                if (r < 0) {
+                        log_debug("Failed to connect to API bus, retrying later...");
+                        return 0;
                 }
 
-                log_debug("Received name %s in reply to Hello", name);
-                if (!dbus_bus_set_unique_name(*conn, name)) {
-                        log_error("Failed to set unique name");
-                        r = -1;
-                        break;
+                r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
+                if (r < 0) {
+                        log_error("Failed to attach API bus to event loop: %s", strerror(-r));
+                        return 0;
                 }
 
-                if (conn == &m->system_bus) {
-                        r = init_registered_system_bus(m);
-                        if (r == 0 && m->running_as == SYSTEMD_SYSTEM)
-                                r = init_registered_api_bus(m);
-                } else
-                        r = init_registered_api_bus(m);
-
-                break;
-        default:
-                assert_not_reached("Invalid reply message");
+                r = bus_setup_disconnected_match(m, bus);
+                if (r < 0)
+                        return 0;
         }
 
-        dbus_message_unref(reply);
-        dbus_error_free(&error);
-
+        r = bus_setup_api(m, bus);
         if (r < 0) {
-                if (conn == &m->system_bus) {
-                        log_debug("Failed setting up the system bus");
-                        bus_done_system(m);
-                } else {
-                        log_debug("Failed setting up the API bus");
-                        bus_done_api(m);
-                }
+                log_error("Failed to set up API bus: %s", strerror(-r));
+                return 0;
         }
-}
 
-static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
-        DBusMessage *message = NULL;
-        DBusPendingCall *pending = NULL;
-
-        message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
-                                               DBUS_PATH_DBUS,
-                                               DBUS_INTERFACE_DBUS,
-                                               "Hello");
-        if (!message)
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
-                goto oom;
-
-        if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
-                goto oom;
-
-        if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
-                goto oom;
-
-        dbus_message_unref(message);
-        dbus_pending_call_unref(pending);
+        m->api_bus = bus;
+        bus = NULL;
 
         return 0;
-oom:
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
-        }
-
-        if (message)
-                dbus_message_unref(message);
-
-        return -ENOMEM;
 }
 
-static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
-        const char *address;
-        DBusConnection *connection;
-        DBusError error;
-
-        switch (type) {
-        case DBUS_BUS_SYSTEM:
-                address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
-                if (!address || !address[0])
-                        address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
-                break;
-        case DBUS_BUS_SESSION:
-                address = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
-                if (!address || !address[0])
-                        address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
-                break;
-        default:
-                assert_not_reached("Invalid bus type");
-        }
+static int bus_setup_system(Manager *m, sd_bus *bus) {
+        int r;
 
-        dbus_error_init(&error);
+        assert(m);
+        assert(bus);
 
-        connection = dbus_connection_open_private(address, &error);
-        if (!connection) {
-                log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
-                goto fail;
-        }
+        if (m->running_as == SYSTEMD_SYSTEM)
+                return 0;
 
-        return connection;
+        /* If we are a user instance we get the Released message via
+         * the system bus */
+        r = sd_bus_add_match(
+                        bus,
+                        "type='signal',"
+                        "interface='org.freedesktop.systemd1.Agent',"
+                        "member='Released',"
+                        "path='/org/freedesktop/systemd1/agent'",
+                        signal_agent_released, m);
 
-fail:
-        dbus_error_free(&error);
-        return NULL;
+        if (r < 0)
+                log_warning("Failed to register Released match on system bus: %s", strerror(-r));
+
+        log_debug("Successfully connected to system bus.");
+        return 0;
 }
 
 static int bus_init_system(Manager *m) {
+        _cleanup_bus_unref_ sd_bus *bus = NULL;
         int r;
 
         if (m->system_bus)
                 return 0;
 
-        m->system_bus = manager_bus_connect_private(m, DBUS_BUS_SYSTEM);
-        if (!m->system_bus) {
-                log_debug("Failed to connect to system D-Bus, retrying later");
-                r = 0;
-                goto fail;
+        /* The API and system bus is the same if we are running in system mode */
+        if (m->running_as == SYSTEMD_SYSTEM && m->api_bus) {
+                m->system_bus = sd_bus_ref(m->api_bus);
+                return 0;
         }
 
-        r = bus_setup_loop(m, m->system_bus);
-        if (r < 0)
-                goto fail;
+        r = sd_bus_open_system(&bus);
+        if (r < 0) {
+                log_debug("Failed to connect to system bus, retrying later...");
+                return 0;
+        }
 
-        r = manager_bus_async_register(m, &m->system_bus);
+        r = bus_setup_disconnected_match(m, bus);
         if (r < 0)
-                goto fail;
-
-        return 0;
-fail:
-        bus_done_system(m);
-
-        return r;
-}
-
-static int bus_init_api(Manager *m) {
-        int r;
-
-        if (m->api_bus)
                 return 0;
 
-        if (m->running_as == SYSTEMD_SYSTEM) {
-                m->api_bus = m->system_bus;
-                /* In this mode there is no distinct connection to the API bus,
-                 * the API is published on the system bus.
-                 * bus_register_cb() is aware of that and will init the API
-                 * when the system bus gets registered.
-                 * No need to setup anything here. */
+        r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
+        if (r < 0) {
+                log_error("Failed to attach system bus to event loop: %s", strerror(-r));
                 return 0;
         }
 
-        m->api_bus = manager_bus_connect_private(m, DBUS_BUS_SESSION);
-        if (!m->api_bus) {
-                log_debug("Failed to connect to API D-Bus, retrying later");
-                r = 0;
-                goto fail;
+        r = bus_setup_system(m, bus);
+        if (r < 0) {
+                log_error("Fauiled to set up system bus: %s", strerror(-r));
+                return 0;
         }
 
-        r = bus_setup_loop(m, m->api_bus);
-        if (r < 0)
-                goto fail;
-
-        r = manager_bus_async_register(m, &m->api_bus);
-        if (r < 0)
-                goto fail;
+        m->system_bus = bus;
+        bus = NULL;
 
         return 0;
-fail:
-        bus_done_api(m);
-
-        return r;
 }
 
 static int bus_init_private(Manager *m) {
-        DBusError error;
-        int r;
-        static const char *const external_only[] = {
-                "EXTERNAL",
-                NULL
+        _cleanup_close_ int fd = -1;
+        union sockaddr_union sa = {
+                .un.sun_family = AF_UNIX
         };
+        sd_event_source *s;
+        socklen_t salen;
+        int r;
 
         assert(m);
 
-        dbus_error_init(&error);
-
-        if (m->private_bus)
+        if (m->private_listen_fd >= 0)
                 return 0;
 
         if (m->running_as == SYSTEMD_SYSTEM) {
@@ -1069,90 +885,72 @@ static int bus_init_private(Manager *m) {
                 if (getpid() != 1)
                         return 0;
 
-                unlink("/run/systemd/private");
-                m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error);
+                strcpy(sa.un.sun_path, "/run/systemd/private");
+                salen = offsetof(union sockaddr_union, un.sun_path) + sizeof("/run/systemd/private") - 1;
         } else {
+                size_t left = sizeof(sa.un.sun_path);
+                char *p = sa.un.sun_path;
                 const char *e;
-                char *p;
-                char *escaped;
 
                 e = secure_getenv("XDG_RUNTIME_DIR");
-                if (!e)
-                        return 0;
-
-                if (asprintf(&p, "%s/systemd/private", e) < 0) {
-                        r = log_oom();
-                        goto fail;
+                if (!e) {
+                        log_error("Failed to determine XDG_RUNTIME_DIR");
+                        return -EHOSTDOWN;
                 }
 
-                mkdir_parents_label(p, 0755);
-                unlink(p);
-                free(p);
+                left = strpcpy(&p, left, e);
+                left = strpcpy(&p, left, "/systemd/private");
 
-                escaped = dbus_address_escape_value(e);
-                if (!escaped) {
-                        r = log_oom();
-                        goto fail;
-                }
-                if (asprintf(&p, "unix:path=%s/systemd/private", escaped) < 0) {
-                        dbus_free(escaped);
-                        r = log_oom();
-                        goto fail;
-                }
-                dbus_free(escaped);
+                salen = sizeof(sa.un) - left;
 
-                m->private_bus = dbus_server_listen(p, &error);
-                free(p);
+                mkdir_parents_label(sa.un.sun_path, 0755);
         }
 
-        if (!m->private_bus) {
-                log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
-                r = -EIO;
-                goto fail;
+        unlink(sa.un.sun_path);
+
+        fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0) {
+                log_error("Failed to allocate private socket: %m");
+                return -errno;
         }
 
-        if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
-            !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
-            !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
-                r = log_oom();
-                goto fail;
+        r = bind(fd, &sa.sa, salen);
+        if (r < 0) {
+                log_error("Failed to bind private socket: %m");
+                return -errno;
         }
 
-        dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
+        r = listen(fd, SOMAXCONN);
+        if (r < 0) {
+                log_error("Failed to make private socket listening: %m");
+                return -errno;
+        }
 
-        log_debug("Successfully created private D-Bus server.");
+        r = sd_event_add_io(m->event, fd, EPOLLIN, bus_on_connection, m, &s);
+        if (r < 0) {
+                log_error("Failed to allocate event source: %s", strerror(-r));
+                return r;
+        }
 
-        return 0;
+        m->private_listen_fd = fd;
+        m->private_listen_event_source = s;
+        fd = -1;
 
-fail:
-        bus_done_private(m);
-        dbus_error_free(&error);
+        log_debug("Successfully created private D-Bus server.");
 
-        return r;
+        return 0;
 }
 
 int bus_init(Manager *m, bool try_bus_connect) {
         int r;
 
-        if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
-            set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
-                return log_oom();
-
-        if (m->name_data_slot < 0)
-                if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
-                        return log_oom();
-
-        if (m->conn_data_slot < 0)
-                if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
-                        return log_oom();
-
-        if (m->subscribed_data_slot < 0)
-                if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
-                        return log_oom();
-
         if (try_bus_connect) {
-                if ((r = bus_init_system(m)) < 0 ||
-                    (r = bus_init_api(m)) < 0)
+                r = bus_init_system(m);
+                if (r < 0)
+                        return r;
+
+                r = bus_init_api(m);
+                if (r < 0)
                         return r;
         }
 
@@ -1163,415 +961,113 @@ int bus_init(Manager *m, bool try_bus_connect) {
         return 0;
 }
 
-static void shutdown_connection(Manager *m, DBusConnection *c) {
-        Job *j;
+static void destroy_bus(Manager *m, sd_bus **bus) {
         Iterator i;
+        Job *j;
 
-        HASHMAP_FOREACH(j, m->jobs, i) {
-                JobBusClient *cl, *nextcl;
-                LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
-                        if (cl->bus == c) {
-                                LIST_REMOVE(client, j->bus_client_list, cl);
-                                free(cl);
-                        }
-                }
-        }
-
-        set_remove(m->bus_connections, c);
-        set_remove(m->bus_connections_for_dispatch, c);
-        set_free_free(BUS_CONNECTION_SUBSCRIBED(m, c));
-
-        if (m->queued_message_connection == c) {
-                m->queued_message_connection = NULL;
-
-                if (m->queued_message) {
-                        dbus_message_unref(m->queued_message);
-                        m->queued_message = NULL;
-                }
-        }
-
-        dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
-        /* system manager cannot afford to block on DBus */
-        if (m->running_as != SYSTEMD_SYSTEM)
-                dbus_connection_flush(c);
-        dbus_connection_close(c);
-        dbus_connection_unref(c);
-}
+        assert(m);
+        assert(bus);
 
-static void bus_done_api(Manager *m) {
-        if (!m->api_bus)
+        if (!*bus)
                 return;
 
-        if (m->running_as == SYSTEMD_USER)
-                shutdown_connection(m, m->api_bus);
+        /* Get rid of tracked clients on this bus */
+        bus_client_untrack_bus(m->subscribed, *bus);
+        HASHMAP_FOREACH(j, m->jobs, i)
+                bus_client_untrack_bus(j->subscribed, *bus);
 
-        m->api_bus = NULL;
+        /* Get rid of queued message on this bus */
+        if (m->queued_message_bus == *bus) {
+                m->queued_message_bus = sd_bus_unref(m->queued_message_bus);
 
-        if (m->queued_message) {
-                dbus_message_unref(m->queued_message);
-                m->queued_message = NULL;
+                if (m->queued_message)
+                        m->queued_message = sd_bus_message_unref(m->queued_message);
         }
-}
-
-static void bus_done_system(Manager *m) {
-        if (!m->system_bus)
-                return;
-
-        if (m->running_as == SYSTEMD_SYSTEM)
-                bus_done_api(m);
 
-        shutdown_connection(m, m->system_bus);
-        m->system_bus = NULL;
-}
-
-static void bus_done_private(Manager *m) {
-        if (!m->private_bus)
-                return;
+        /* Possibly flush unwritten data, but only if we are
+         * unprivileged, since we don't want to sync here */
+        if (m->running_as != SYSTEMD_SYSTEM)
+                sd_bus_flush(*bus);
 
-        dbus_server_disconnect(m->private_bus);
-        dbus_server_unref(m->private_bus);
-        m->private_bus = NULL;
+        /* And destroy the object */
+        sd_bus_close(*bus);
+        *bus = sd_bus_unref(*bus);
 }
 
 void bus_done(Manager *m) {
-        DBusConnection *c;
-
-        bus_done_api(m);
-        bus_done_system(m);
-        bus_done_private(m);
-
-        while ((c = set_steal_first(m->bus_connections)))
-                shutdown_connection(m, c);
-
-        while ((c = set_steal_first(m->bus_connections_for_dispatch)))
-                shutdown_connection(m, c);
-
-        set_free(m->bus_connections);
-        set_free(m->bus_connections_for_dispatch);
-
-        if (m->name_data_slot >= 0)
-                dbus_pending_call_free_data_slot(&m->name_data_slot);
-
-        if (m->conn_data_slot >= 0)
-                dbus_pending_call_free_data_slot(&m->conn_data_slot);
-
-        if (m->subscribed_data_slot >= 0)
-                dbus_connection_free_data_slot(&m->subscribed_data_slot);
-}
-
-static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
-        Manager *m = userdata;
-        DBusMessage *reply;
-        DBusError error;
-        const char *name;
-
-        dbus_error_init(&error);
-
-        assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
-        assert_se(reply = dbus_pending_call_steal_reply(pending));
-
-        switch (dbus_message_get_type(reply)) {
-
-        case DBUS_MESSAGE_TYPE_ERROR:
-
-                assert_se(dbus_set_error_from_message(&error, reply));
-                log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
-                break;
-
-        case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
-                uint32_t r;
-
-                if (!dbus_message_get_args(reply,
-                                           &error,
-                                           DBUS_TYPE_UINT32, &r,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
-                        break;
-                }
-
-                manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
-                break;
-        }
-
-        default:
-                assert_not_reached("Invalid reply message");
-        }
-
-        dbus_message_unref(reply);
-        dbus_error_free(&error);
-}
-
-int bus_query_pid(Manager *m, const char *name) {
-        DBusMessage *message = NULL;
-        DBusPendingCall *pending = NULL;
-        char *n = NULL;
+        sd_bus *b;
 
         assert(m);
-        assert(name);
-
-        if (!(message = dbus_message_new_method_call(
-                              DBUS_SERVICE_DBUS,
-                              DBUS_PATH_DBUS,
-                              DBUS_INTERFACE_DBUS,
-                              "GetConnectionUnixProcessID")))
-                goto oom;
 
-        if (!(dbus_message_append_args(
-                              message,
-                              DBUS_TYPE_STRING, &name,
-                              DBUS_TYPE_INVALID)))
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
-                goto oom;
-
-        if (!(n = strdup(name)))
-                goto oom;
-
-        if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
-                goto oom;
-
-        n = NULL;
-
-        if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
-                goto oom;
-
-        dbus_message_unref(message);
-        dbus_pending_call_unref(pending);
+        if (m->api_bus)
+                destroy_bus(m, &m->api_bus);
+        if (m->system_bus)
+                destroy_bus(m, &m->system_bus);
+        while ((b = set_steal_first(m->private_buses)))
+                destroy_bus(m, &b);
 
-        return 0;
+        set_free(m->private_buses);
+        set_free(m->subscribed);
 
-oom:
-        free(n);
+        if (m->private_listen_event_source)
+                m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
 
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
+        if (m->private_listen_fd >= 0) {
+                close_nointr_nofail(m->private_listen_fd);
+                m->private_listen_fd = -1;
         }
-
-        if (message)
-                dbus_message_unref(message);
-
-        return -ENOMEM;
-}
-
-int bus_broadcast(Manager *m, DBusMessage *message) {
-        bool oom = false;
-        Iterator i;
-        DBusConnection *c;
-
-        assert(m);
-        assert(message);
-
-        SET_FOREACH(c, m->bus_connections_for_dispatch, i)
-                if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
-                        oom = !dbus_connection_send(c, message, NULL);
-
-        SET_FOREACH(c, m->bus_connections, i)
-                if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
-                        oom = !dbus_connection_send(c, message, NULL);
-
-        return oom ? -ENOMEM : 0;
-}
-
-bool bus_has_subscriber(Manager *m) {
-        Iterator i;
-        DBusConnection *c;
-
-        assert(m);
-
-        /* If we are reloading then we might not have deserialized the
-           subscribers yet, hence let's assume that there are some */
-
-        if (m->n_reloading > 0)
-                return true;
-
-        SET_FOREACH(c, m->bus_connections_for_dispatch, i)
-                if (bus_connection_has_subscriber(m, c))
-                        return true;
-
-        SET_FOREACH(c, m->bus_connections, i)
-                if (bus_connection_has_subscriber(m, c))
-                        return true;
-
-        return false;
-}
-
-bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
-        assert(m);
-        assert(c);
-
-        return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
 }
 
 int bus_fdset_add_all(Manager *m, FDSet *fds) {
         Iterator i;
-        DBusConnection *c;
+        sd_bus *b;
+        int fd;
 
         assert(m);
         assert(fds);
 
         /* When we are about to reexecute we add all D-Bus fds to the
          * set to pass over to the newly executed systemd. They won't
-         * be used there however, except that they are closed at the
+         * be used there however, except thatt they are closed at the
          * very end of deserialization, those making it possible for
          * clients to synchronously wait for systemd to reexec by
          * simply waiting for disconnection */
 
-        SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
-                int fd;
-
-                if (dbus_connection_get_unix_fd(c, &fd)) {
+        if (m->api_bus) {
+                fd = sd_bus_get_fd(m->api_bus);
+                if (fd >= 0) {
                         fd = fdset_put_dup(fds, fd);
-
                         if (fd < 0)
                                 return fd;
                 }
         }
 
-        SET_FOREACH(c, m->bus_connections, i) {
-                int fd;
-
-                if (dbus_connection_get_unix_fd(c, &fd)) {
+        SET_FOREACH(b, m->private_buses, i) {
+                fd = sd_bus_get_fd(b);
+                if (fd >= 0) {
                         fd = fdset_put_dup(fds, fd);
-
                         if (fd < 0)
                                 return fd;
                 }
         }
 
-        return 0;
-}
-
-void bus_broadcast_finished(
-                Manager *m,
-                usec_t firmware_usec,
-                usec_t loader_usec,
-                usec_t kernel_usec,
-                usec_t initrd_usec,
-                usec_t userspace_usec,
-                usec_t total_usec) {
-
-        _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
-
-        assert(m);
-
-        message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
-        if (!message) {
-                log_oom();
-                return;
-        }
-
-        assert_cc(sizeof(usec_t) == sizeof(uint64_t));
-        if (!dbus_message_append_args(message,
-                                      DBUS_TYPE_UINT64, &firmware_usec,
-                                      DBUS_TYPE_UINT64, &loader_usec,
-                                      DBUS_TYPE_UINT64, &kernel_usec,
-                                      DBUS_TYPE_UINT64, &initrd_usec,
-                                      DBUS_TYPE_UINT64, &userspace_usec,
-                                      DBUS_TYPE_UINT64, &total_usec,
-                                      DBUS_TYPE_INVALID)) {
-                log_oom();
-                return;
-        }
-
-
-        if (bus_broadcast(m, message) < 0) {
-                log_oom();
-                return;
-        }
-}
-
-void bus_broadcast_reloading(Manager *m, bool active) {
-
-        _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
-        dbus_bool_t b = active;
-
-        assert(m);
-
-        message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
-        if (!message) {
-                log_oom();
-                return;
-        }
-
-        assert_cc(sizeof(usec_t) == sizeof(uint64_t));
-        if (!dbus_message_append_args(message,
-                                      DBUS_TYPE_BOOLEAN, &b,
-                                      DBUS_TYPE_INVALID)) {
-                log_oom();
-                return;
-        }
-
-
-        if (bus_broadcast(m, message) < 0) {
-                log_oom();
-                return;
-        }
-}
-
-Set *bus_acquire_subscribed(Manager *m, DBusConnection *c) {
-        Set *s;
-
-        assert(m);
-        assert(c);
-
-        s = BUS_CONNECTION_SUBSCRIBED(m, c);
-        if (s)
-                return s;
-
-        s = set_new(string_hash_func, string_compare_func);
-        if (!s)
-                return NULL;
+        /* We don't offer any APIs on the system bus (well, unless it
+         * is the same as the API bus) hence we don't bother with it
+         * here */
 
-        if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) {
-                set_free(s);
-                return NULL;
-        }
-
-        return s;
+        return 0;
 }
 
 void bus_serialize(Manager *m, FILE *f) {
-        char *client;
-        Iterator i;
-        Set *s;
-
         assert(m);
         assert(f);
 
-        if (!m->api_bus)
-                return;
-
-        s = BUS_CONNECTION_SUBSCRIBED(m, m->api_bus);
-        SET_FOREACH(client, s, i)
-                fprintf(f, "subscribed=%s\n", client);
+        bus_client_track_serialize(m, f, m->subscribed);
 }
 
 int bus_deserialize_item(Manager *m, const char *line) {
-        const char *e;
-        char *b;
-        Set *s;
-
         assert(m);
         assert(line);
 
-        if (!m->api_bus)
-                return 0;
-
-        e = startswith(line, "subscribed=");
-        if (!e)
-                return 0;
-
-        s = bus_acquire_subscribed(m, m->api_bus);
-        if (!s)
-                return -ENOMEM;
-
-        b = strdup(e);
-        if (!b)
-                return -ENOMEM;
-
-        set_consume(s, b);
-
-        return 1;
+        return bus_client_track_deserialize_item(m, &m->subscribed, line);
 }
index 6500cd74555ebda2cf7c42523aaea7fc4f135082..a3bef47d5de9aa352fe3ab96020e81a89a885626 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
 #include "manager.h"
 
+int bus_send_queued_message(Manager *m);
+
 int bus_init(Manager *m, bool try_bus_connect);
 void bus_done(Manager *m);
 
-unsigned bus_dispatch(Manager *m);
-
-void bus_watch_event(Manager *m, Watch *w, int events);
-void bus_timeout_event(Manager *m, Watch *w, int events);
-
-int bus_query_pid(Manager *m, const char *name);
-
-int bus_broadcast(Manager *m, DBusMessage *message);
-
-bool bus_has_subscriber(Manager *m);
-bool bus_connection_has_subscriber(Manager *m, DBusConnection *c);
-
 int bus_fdset_add_all(Manager *m, FDSet *fds);
 
-void bus_broadcast_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec);
-void bus_broadcast_reloading(Manager *m, bool active);
-
-Set *bus_acquire_subscribed(Manager *m, DBusConnection *c);
-
 void bus_serialize(Manager *m, FILE *f);
 int bus_deserialize_item(Manager *m, const char *line);
-
-#define BUS_CONNECTION_SUBSCRIBED(m, c) dbus_connection_get_data((c), (m)->subscribed_data_slot)
-#define BUS_PENDING_CALL_NAME(m, p) dbus_pending_call_get_data((p), (m)->name_data_slot)
-
-extern const char * const bus_interface_table[];
index 6fc4c95ea0388e1bee3e4806618489b33326dd19..91e37e09dbeca196f5eec3d359b92985498336b7 100644 (file)
 #include "dbus-device.h"
 #include "def.h"
 #include "path-util.h"
+#include "udev-util.h"
 
 static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
         [DEVICE_DEAD] = UNIT_INACTIVE,
         [DEVICE_PLUGGED] = UNIT_ACTIVE
 };
 
+static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+
 static void device_unset_sysfs(Device *d) {
         Device *first;
 
@@ -137,7 +140,7 @@ _pure_ static const char *device_sub_state_to_string(Unit *u) {
 }
 
 static int device_add_escaped_name(Unit *u, const char *dn) {
-        char *e;
+        _cleanup_free_ char *e = NULL;
         int r;
 
         assert(u);
@@ -149,8 +152,6 @@ static int device_add_escaped_name(Unit *u, const char *dn) {
                 return -ENOMEM;
 
         r = unit_add_name(u, e);
-        free(e);
-
         if (r < 0 && r != -EEXIST)
                 return r;
 
@@ -158,7 +159,7 @@ static int device_add_escaped_name(Unit *u, const char *dn) {
 }
 
 static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
-        char *e;
+        _cleanup_free_ char *e = NULL;
         Unit *u;
 
         assert(m);
@@ -171,8 +172,6 @@ static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
                 return -ENOMEM;
 
         u = manager_get_unit(m, e);
-        free(e);
-
         if (u) {
                 *_u = u;
                 return 1;
@@ -222,16 +221,15 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
         if (!DEVICE(u)->sysfs) {
                 Device *first;
 
-                if (!(DEVICE(u)->sysfs = strdup(sysfs))) {
+                DEVICE(u)->sysfs = strdup(sysfs);
+                if (!DEVICE(u)->sysfs) {
                         r = -ENOMEM;
                         goto fail;
                 }
 
-                if (!m->devices_by_sysfs)
-                        if (!(m->devices_by_sysfs = hashmap_new(string_hash_func, string_compare_func))) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
+                r = hashmap_ensure_allocated(&m->devices_by_sysfs, string_hash_func, string_compare_func);
+                if (r < 0)
+                        goto fail;
 
                 first = hashmap_get(m->devices_by_sysfs, sysfs);
                 LIST_PREPEND(same_sysfs, first, DEVICE(u));
@@ -242,15 +240,12 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
         }
 
         if ((model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE")) ||
-            (model = udev_device_get_property_value(dev, "ID_MODEL"))) {
+            (model = udev_device_get_property_value(dev, "ID_MODEL")))
                 r = unit_set_description(u, model);
-                if (r < 0)
-                        goto fail;
-        } else {
+        else
                 r = unit_set_description(u, path);
-                if (r < 0)
-                        goto fail;
-        }
+        if (r < 0)
+                goto fail;
 
         if (main) {
                 /* The additional systemd udev properties we only
@@ -278,7 +273,7 @@ static int device_update_unit(Manager *m, struct udev_device *dev, const char *p
                         }
                 }
 
-                wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS");
+                wants = udev_device_get_property_value(dev, m->running_as == SYSTEMD_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS");
                 if (wants) {
                         char *state, *w;
                         size_t l;
@@ -324,7 +319,8 @@ static int device_process_new_device(Manager *m, struct udev_device *dev, bool u
 
         assert(m);
 
-        if (!(sysfs = udev_device_get_syspath(dev)))
+        sysfs = udev_device_get_syspath(dev);
+        if (!sysfs)
                 return -ENOMEM;
 
         /* Add the main unit named after the sysfs path */
@@ -384,7 +380,8 @@ static int device_process_path(Manager *m, const char *path, bool update_state)
         assert(m);
         assert(path);
 
-        if (!(dev = udev_device_new_from_syspath(m->udev, path))) {
+        dev = udev_device_new_from_syspath(m->udev, path);
+        if (!dev) {
                 log_warning("Failed to get udev device object from udev for path %s.", path);
                 return -ENOMEM;
         }
@@ -473,6 +470,8 @@ fail:
 static void device_shutdown(Manager *m) {
         assert(m);
 
+        m->udev_event_source = sd_event_source_unref(m->udev_event_source);
+
         if (m->udev_monitor) {
                 udev_monitor_unref(m->udev_monitor);
                 m->udev_monitor = NULL;
@@ -488,19 +487,19 @@ static void device_shutdown(Manager *m) {
 }
 
 static int device_enumerate(Manager *m) {
-        int r;
-        struct udev_enumerate *e = NULL;
+        _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
         struct udev_list_entry *item = NULL, *first = NULL;
+        int r;
 
         assert(m);
 
         if (!m->udev) {
-                struct epoll_event ev;
-
-                if (!(m->udev = udev_new()))
+                m->udev = udev_new();
+                if (!m->udev)
                         return -ENOMEM;
 
-                if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
+                m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
+                if (!m->udev_monitor) {
                         r = -ENOMEM;
                         goto fail;
                 }
@@ -510,101 +509,88 @@ static int device_enumerate(Manager *m) {
                  * during boot. */
                 udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
 
-                if (udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd") < 0) {
-                        r = -ENOMEM;
+                r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd");
+                if (r < 0)
                         goto fail;
-                }
 
-                if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
-                        r = -EIO;
+                r = udev_monitor_enable_receiving(m->udev_monitor);
+                if (r < 0)
                         goto fail;
-                }
-
-                m->udev_watch.type = WATCH_UDEV;
-                m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
-
-                zero(ev);
-                ev.events = EPOLLIN;
-                ev.data.ptr = &m->udev_watch;
 
-                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
-                        return -errno;
+                r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_monitor), EPOLLIN, device_dispatch_io, m, &m->udev_event_source);
+                if (r < 0)
+                        goto fail;
         }
 
-        if (!(e = udev_enumerate_new(m->udev))) {
+        e = udev_enumerate_new(m->udev);
+        if (!e) {
                 r = -ENOMEM;
                 goto fail;
         }
-        if (udev_enumerate_add_match_tag(e, "systemd") < 0) {
-                r = -EIO;
+
+        r = udev_enumerate_add_match_tag(e, "systemd");
+        if (r < 0)
                 goto fail;
-        }
 
-        if (udev_enumerate_scan_devices(e) < 0) {
-                r = -EIO;
+        r = udev_enumerate_scan_devices(e);
+        if (r < 0)
                 goto fail;
-        }
 
         first = udev_enumerate_get_list_entry(e);
         udev_list_entry_foreach(item, first)
                 device_process_path(m, udev_list_entry_get_name(item), false);
 
-        udev_enumerate_unref(e);
         return 0;
 
 fail:
-        if (e)
-                udev_enumerate_unref(e);
-
         device_shutdown(m);
         return r;
 }
 
-void device_fd_event(Manager *m, int events) {
-        struct udev_device *dev;
-        int r;
+static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
         const char *action, *ready;
+        Manager *m = userdata;
+        int r;
 
         assert(m);
 
-        if (events != EPOLLIN) {
+        if (revents != EPOLLIN) {
                 static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
 
                 if (!ratelimit_test(&limit))
                         log_error("Failed to get udev event: %m");
-                if (!(events & EPOLLIN))
-                        return;
+                if (!(revents & EPOLLIN))
+                        return 0;
         }
 
-        if (!(dev = udev_monitor_receive_device(m->udev_monitor))) {
-                /*
-                 * libudev might filter-out devices which pass the bloom filter,
-                 * so getting NULL here is not necessarily an error
-                 */
-                return;
-        }
+        /*
+         * libudev might filter-out devices which pass the bloom
+         * filter, so getting NULL here is not necessarily an error.
+         */
+        dev = udev_monitor_receive_device(m->udev_monitor);
+        if (!dev)
+                return 0;
 
-        if (!(action = udev_device_get_action(dev))) {
+        action = udev_device_get_action(dev);
+        if (!action) {
                 log_error("Failed to get udev action string.");
-                goto fail;
+                return 0;
         }
 
         ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
 
         if (streq(action, "remove") || (ready && parse_boolean(ready) == 0)) {
-                if ((r = device_process_removed_device(m, dev)) < 0) {
+                r = device_process_removed_device(m, dev);
+                if (r < 0)
                         log_error("Failed to process udev device event: %s", strerror(-r));
-                        goto fail;
-                }
         } else {
-                if ((r = device_process_new_device(m, dev, true)) < 0) {
+                r = device_process_new_device(m, dev, true);
+                if (r < 0)
                         log_error("Failed to process udev device event: %s", strerror(-r));
-                        goto fail;
-                }
         }
 
-fail:
-        udev_device_unref(dev);
+        return 0;
 }
 
 static const char* const device_state_table[_DEVICE_STATE_MAX] = {
@@ -624,9 +610,9 @@ const UnitVTable device_vtable = {
         .no_instances = true,
 
         .init = device_init,
-
-        .load = unit_load_fragment_and_dropin_optional,
         .done = device_done,
+        .load = unit_load_fragment_and_dropin_optional,
+
         .coldplug = device_coldplug,
 
         .dump = device_dump,
@@ -635,8 +621,8 @@ const UnitVTable device_vtable = {
         .sub_state_to_string = device_sub_state_to_string,
 
         .bus_interface = "org.freedesktop.systemd1.Device",
-        .bus_message_handler = bus_device_message_handler,
-        .bus_invalidating_properties =  bus_device_invalidating_properties,
+        .bus_changing_properties = bus_device_changing_properties,
+        .bus_vtable = bus_device_vtable,
 
         .following = device_following,
         .following_set = device_following_set,
index 41e8de970366c49566b7925d57025e8269fff9c1..bb7ae0783499cfcb60ce8e908c279acfeef2773d 100644 (file)
@@ -50,7 +50,5 @@ struct Device {
 
 extern const UnitVTable device_vtable;
 
-void device_fd_event(Manager *m, int events);
-
 const char* device_state_to_string(DeviceState i) _const_;
 DeviceState device_state_from_string(const char *s) _pure_;
index 0dd161c1c58104313214d6b01c2bef7fca019276..f053d57349d4c6a2af9fae730fc04b9da83d732e 100644 (file)
@@ -24,8 +24,8 @@
 #include <sys/timerfd.h>
 #include <sys/epoll.h>
 
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include "sd-id128.h"
+#include "sd-messages.h"
 #include "set.h"
 #include "unit.h"
 #include "macro.h"
 #include "special.h"
 #include "async.h"
 #include "virt.h"
-
-JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
-        JobBusClient *cl;
-        size_t name_len;
-
-        name_len = strlen(name);
-        cl = malloc0(sizeof(JobBusClient) + name_len + 1);
-        if (!cl)
-                return NULL;
-
-        cl->bus = connection;
-        memcpy(cl->name, name, name_len + 1);
-        return cl;
-}
+#include "dbus-client-track.h"
 
 Job* job_new_raw(Unit *unit) {
         Job *j;
@@ -66,7 +53,6 @@ Job* job_new_raw(Unit *unit) {
         j->manager = unit->manager;
         j->unit = unit;
         j->type = _JOB_TYPE_INVALID;
-        j->timer_watch.type = WATCH_INVALID;
 
         return j;
 }
@@ -89,8 +75,6 @@ Job* job_new(Unit *unit, JobType type) {
 }
 
 void job_free(Job *j) {
-        JobBusClient *cl;
-
         assert(j);
         assert(!j->installed);
         assert(!j->transaction_prev);
@@ -104,19 +88,10 @@ void job_free(Job *j) {
         if (j->in_dbus_queue)
                 LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
 
-        if (j->timer_watch.type != WATCH_INVALID) {
-                assert(j->timer_watch.type == WATCH_JOB_TIMER);
-                assert(j->timer_watch.data.job == j);
-                assert(j->timer_watch.fd >= 0);
+        sd_event_source_unref(j->timer_event_source);
 
-                assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
-                close_nointr_nofail(j->timer_watch.fd);
-        }
+        bus_client_track_free(j->subscribed);
 
-        while ((cl = j->bus_client_list)) {
-                LIST_REMOVE(client, j->bus_client_list, cl);
-                free(cl);
-        }
         free(j);
 }
 
@@ -859,48 +834,32 @@ finish:
         return 0;
 }
 
-int job_start_timer(Job *j) {
-        struct itimerspec its = {};
-        struct epoll_event ev = {
-                .data.ptr = &j->timer_watch,
-                .events = EPOLLIN,
-        };
-        int fd, r;
-
-        if (j->unit->job_timeout <= 0 ||
-            j->timer_watch.type == WATCH_JOB_TIMER)
-                return 0;
+static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) {
+        Job *j = userdata;
 
-        assert(j->timer_watch.type == WATCH_INVALID);
-
-        if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
-                r = -errno;
-                goto fail;
-        }
+        assert(j);
+        assert(s == j->timer_event_source);
 
-        timespec_store(&its.it_value, j->unit->job_timeout);
+        log_warning_unit(j->unit->id, "Job %s/%s timed out.",
+                         j->unit->id, job_type_to_string(j->type));
 
-        if (timerfd_settime(fd, 0, &its, NULL) < 0) {
-                r = -errno;
-                goto fail;
-        }
+        job_finish_and_invalidate(j, JOB_TIMEOUT, true);
+        return 0;
+}
 
-        if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
-                r = -errno;
-                goto fail;
-        }
+int job_start_timer(Job *j) {
+        int r;
 
-        j->timer_watch.type = WATCH_JOB_TIMER;
-        j->timer_watch.fd = fd;
-        j->timer_watch.data.job = j;
+        if (j->unit->job_timeout <= 0 || j->timer_event_source)
+                return 0;
 
-        return 0;
+        j->begin_usec = now(CLOCK_MONOTONIC);
 
-fail:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        r = sd_event_add_monotonic(j->manager->event, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j, &j->timer_event_source);
+        if (r < 0)
+                return r;
 
-        return r;
+        return 0;
 }
 
 void job_add_to_run_queue(Job *j) {
@@ -940,15 +899,6 @@ char *job_dbus_path(Job *j) {
         return p;
 }
 
-void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
-        assert(j);
-        assert(w == &j->timer_watch);
-
-        log_warning_unit(j->unit->id, "Job %s/%s timed out.",
-                         j->unit->id, job_type_to_string(j->type));
-        job_finish_and_invalidate(j, JOB_TIMEOUT, true);
-}
-
 int job_serialize(Job *j, FILE *f, FDSet *fds) {
         fprintf(f, "job-id=%u\n", j->id);
         fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
@@ -957,16 +907,11 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) {
         fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
         fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
         fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
-        /* Cannot save bus clients. Just note the fact that we're losing
-         * them. job_send_message() will fallback to broadcasting. */
-        fprintf(f, "job-forgot-bus-clients=%s\n",
-                yes_no(j->forgot_bus_clients || j->bus_client_list));
-        if (j->timer_watch.type == WATCH_JOB_TIMER) {
-                int copy = fdset_put_dup(fds, j->timer_watch.fd);
-                if (copy < 0)
-                        return copy;
-                fprintf(f, "job-timer-watch-fd=%d\n", copy);
-        }
+
+        if (j->begin_usec > 0)
+                fprintf(f, "job-begin=%llu", (unsigned long long) j->begin_usec);
+
+        bus_client_track_serialize(j->manager, f, j->subscribed);
 
         /* End marker */
         fputc('\n', f);
@@ -974,6 +919,8 @@ int job_serialize(Job *j, FILE *f, FDSet *fds) {
 }
 
 int job_deserialize(Job *j, FILE *f, FDSet *fds) {
+        assert(j);
+
         for (;;) {
                 char line[LINE_MAX], *l, *v;
                 size_t k;
@@ -1000,81 +947,101 @@ int job_deserialize(Job *j, FILE *f, FDSet *fds) {
                         v = l+k;
 
                 if (streq(l, "job-id")) {
+
                         if (safe_atou32(v, &j->id) < 0)
                                 log_debug("Failed to parse job id value %s", v);
+
                 } else if (streq(l, "job-type")) {
-                        JobType t = job_type_from_string(v);
+                        JobType t;
+
+                        t = job_type_from_string(v);
                         if (t < 0)
                                 log_debug("Failed to parse job type %s", v);
                         else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
                                 log_debug("Cannot deserialize job of type %s", v);
                         else
                                 j->type = t;
+
                 } else if (streq(l, "job-state")) {
-                        JobState s = job_state_from_string(v);
+                        JobState s;
+
+                        s = job_state_from_string(v);
                         if (s < 0)
                                 log_debug("Failed to parse job state %s", v);
                         else
                                 j->state = s;
+
                 } else if (streq(l, "job-override")) {
-                        int b = parse_boolean(v);
+                        int b;
+
+                        b = parse_boolean(v);
                         if (b < 0)
                                 log_debug("Failed to parse job override flag %s", v);
                         else
                                 j->override = j->override || b;
+
                 } else if (streq(l, "job-irreversible")) {
-                        int b = parse_boolean(v);
+                        int b;
+
+                        b = parse_boolean(v);
                         if (b < 0)
                                 log_debug("Failed to parse job irreversible flag %s", v);
                         else
                                 j->irreversible = j->irreversible || b;
+
                 } else if (streq(l, "job-sent-dbus-new-signal")) {
-                        int b = parse_boolean(v);
+                        int b;
+
+                        b = parse_boolean(v);
                         if (b < 0)
                                 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
                         else
                                 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
+
                 } else if (streq(l, "job-ignore-order")) {
-                        int b = parse_boolean(v);
+                        int b;
+
+                        b = parse_boolean(v);
                         if (b < 0)
                                 log_debug("Failed to parse job ignore_order flag %s", v);
                         else
                                 j->ignore_order = j->ignore_order || b;
-                } else if (streq(l, "job-forgot-bus-clients")) {
-                        int b = parse_boolean(v);
-                        if (b < 0)
-                                log_debug("Failed to parse job forgot_bus_clients flag %s", v);
+
+                } else if (streq(l, "job-begin")) {
+                        unsigned long long ull;
+
+                        if (sscanf(v, "%llu", &ull) != 1)
+                                log_debug("Failed to parse job-begin value %s", v);
                         else
-                                j->forgot_bus_clients = j->forgot_bus_clients || b;
-                } else if (streq(l, "job-timer-watch-fd")) {
-                        int fd;
-                        if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
-                                log_debug("Failed to parse job-timer-watch-fd value %s", v);
-                        else {
-                                if (j->timer_watch.type == WATCH_JOB_TIMER)
-                                        close_nointr_nofail(j->timer_watch.fd);
-
-                                j->timer_watch.type = WATCH_JOB_TIMER;
-                                j->timer_watch.fd = fdset_remove(fds, fd);
-                                j->timer_watch.data.job = j;
-                        }
+                                j->begin_usec = ull;
+
+                } else {
+                        char t[strlen(l) + 1 + strlen(v) + 1];
+
+                        strcpy(stpcpy(stpcpy(t, l), "="), v);
+
+                        if (bus_client_track_deserialize_item(j->manager, &j->subscribed, t) == 0)
+                                log_debug("Unknown deserialization key '%s'", l);
                 }
         }
 }
 
 int job_coldplug(Job *j) {
-        struct epoll_event ev = {
-                .data.ptr = &j->timer_watch,
-                .events = EPOLLIN,
-        };
+        int r;
+
+        assert(j);
 
-        if (j->timer_watch.type != WATCH_JOB_TIMER)
+        if (j->begin_usec <= 0)
                 return 0;
 
-        if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
-                return -errno;
+        if (j->timer_event_source)
+                j->timer_event_source = sd_event_source_unref(j->timer_event_source);
 
-        return 0;
+        r = sd_event_add_monotonic(j->manager->event, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j, &j->timer_event_source);
+        if (r < 0)
+                log_debug("Failed to restart timeout for job: %s", strerror(-r));
+
+        return r;
 }
 
 void job_shutdown_magic(Job *j) {
index be9d278b0c9fdc551b799a2386aa805b053bd986..60bb87d75a83bf9b94b93b49167a8439069a4a5d 100644 (file)
@@ -27,7 +27,6 @@
 
 typedef struct Job Job;
 typedef struct JobDependency JobDependency;
-typedef struct JobBusClient JobBusClient;
 typedef enum JobType JobType;
 typedef enum JobState JobState;
 typedef enum JobMode JobMode;
@@ -102,6 +101,7 @@ enum JobResult {
         _JOB_RESULT_INVALID = -1
 };
 
+#include "sd-event.h"
 #include "manager.h"
 #include "unit.h"
 #include "hashmap.h"
@@ -120,13 +120,6 @@ struct JobDependency {
         bool conflicts;
 };
 
-struct JobBusClient {
-        LIST_FIELDS(JobBusClient, client);
-        /* Note that this bus object is not ref counted here. */
-        DBusConnection *bus;
-        char name[0];
-};
-
 struct Job {
         Manager *manager;
         Unit *unit;
@@ -147,10 +140,11 @@ struct Job {
         JobType type;
         JobState state;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
+        usec_t begin_usec;
 
         /* There can be more than one client, because of job merging. */
-        LIST_HEAD(JobBusClient, bus_client_list);
+        Set *subscribed;
 
         JobResult result;
 
@@ -165,8 +159,6 @@ struct Job {
         bool irreversible:1;
 };
 
-JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name);
-
 Job* job_new(Unit *unit, JobType type);
 Job* job_new_raw(Unit *unit);
 void job_free(Job *job);
@@ -210,7 +202,6 @@ void job_add_to_run_queue(Job *j);
 void job_add_to_dbus_queue(Job *j);
 
 int job_start_timer(Job *j);
-void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w);
 
 int job_run_and_invalidate(Job *j);
 int job_finish_and_invalidate(Job *j, JobResult result, bool recursive);
index b64fdc9dcba232eb8abe993e348c0c1a5f0e4796..22dc536ee19ab1a3566302575255de86a3e669f0 100644 (file)
@@ -210,7 +210,7 @@ Socket.Broadcast,                config_parse_bool,                  0,
 Socket.PassCredentials,          config_parse_bool,                  0,                             offsetof(Socket, pass_cred)
 Socket.PassSecurity,             config_parse_bool,                  0,                             offsetof(Socket, pass_sec)
 Socket.TCPCongestion,            config_parse_string,                0,                             offsetof(Socket, tcp_congestion)
-Socket.ReusePort,                config_parse_bool,                  0,                             offsetof(Socket, reuseport)
+Socket.ReusePort,                config_parse_bool,                  0,                             offsetof(Socket, reuse_port)
 Socket.MessageQueueMaxMessages,  config_parse_long,                  0,                             offsetof(Socket, mq_maxmsg)
 Socket.MessageQueueMessageSize,  config_parse_long,                  0,                             offsetof(Socket, mq_msgsize)
 Socket.Service,                  config_parse_socket_service,        0,                             0
index 72c46371e47eefb0d33165ec8375f983ec97fcd7..de612f05cb7ed166d7f1f71e80c2ee9db4eb3f0a 100644 (file)
 #include "missing.h"
 #include "unit-name.h"
 #include "unit-printf.h"
-#include "dbus-common.h"
 #include "utf8.h"
 #include "path-util.h"
 #include "syscall-list.h"
 #include "env-util.h"
 #include "cgroup.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 #ifndef HAVE_SYSV_COMPAT
 int config_parse_warn_compat(const char *unit,
@@ -1288,6 +1289,7 @@ int config_parse_path_spec(const char *unit,
         if (!s)
                 return log_oom();
 
+        s->unit = UNIT(p);
         s->path = path_kill_slashes(k);
         k = NULL;
         s->type = b;
@@ -1308,9 +1310,9 @@ int config_parse_socket_service(const char *unit,
                                 void *data,
                                 void *userdata) {
 
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         Socket *s = data;
         int r;
-        DBusError error;
         Unit *x;
         _cleanup_free_ char *p = NULL;
 
@@ -1319,25 +1321,18 @@ int config_parse_socket_service(const char *unit,
         assert(rvalue);
         assert(data);
 
-        dbus_error_init(&error);
-
         r = unit_name_printf(UNIT(s), rvalue, &p);
         if (r < 0)
-                log_syntax(unit, LOG_ERR, filename, line, -r,
-                           "Failed to resolve specifiers, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
 
         if (!endswith(p ?: rvalue, ".service")) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Unit must be of type service, ignoring: %s", rvalue);
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
                 return 0;
         }
 
         r = manager_load_unit(UNIT(s)->manager, p ?: rvalue, NULL, &error, &x);
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, r,
-                           "Failed to load unit %s, ignoring: %s",
-                           rvalue, bus_error(&error, r));
-                dbus_error_free(&error);
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
                 return 0;
         }
 
index c89c12343ecafc6ef097630bb11af58c0fcf7a0b..f342cdd2895559c6a322d9cdc8e2f5a12f6a85dd 100644 (file)
@@ -19,8 +19,6 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus/dbus.h>
-
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/prctl.h>
 #include <sys/mount.h>
 
+#include "sd-daemon.h"
+#include "sd-messages.h"
+#include "sd-bus.h"
 #include "manager.h"
 #include "log.h"
 #include "load-fragment.h"
 #include "fdset.h"
 #include "special.h"
 #include "conf-parser.h"
-#include "dbus-common.h"
 #include "missing.h"
 #include "label.h"
 #include "build.h"
 #include "killall.h"
 #include "env-util.h"
 #include "hwclock.h"
-#include "sd-daemon.h"
-#include "sd-messages.h"
+#include "fileio.h"
+#include "dbus-manager.h"
+#include "bus-error.h"
+#include "bus-util.h"
 
 #include "mount-setup.h"
 #include "loopback-setup.h"
-#ifdef HAVE_KMOD
-#include "kmod-setup.h"
-#endif
 #include "hostname-setup.h"
 #include "machine-id-setup.h"
 #include "selinux-setup.h"
 #include "ima-setup.h"
-#include "fileio.h"
 #include "smack-setup.h"
+#ifdef HAVE_KMOD
+#include "kmod-setup.h"
+#endif
 
 static enum {
         ACTION_RUN,
@@ -1039,7 +1040,7 @@ static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool switching
 
         /* Make sure nothing is really destructed when we shut down */
         m->n_reloading ++;
-        bus_broadcast_reloading(m, true);
+        bus_manager_send_reloading(m, true);
 
         fds = fdset_new();
         if (!fds) {
@@ -1442,9 +1443,6 @@ int main(int argc, char *argv[]) {
         /* Move out of the way, so that we won't block unmounts */
         assert_se(chdir("/")  == 0);
 
-        /* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
-        dbus_connection_set_change_sigpipe(FALSE);
-
         /* Reset the console, but only if this is really init and we
          * are freshly booted */
         if (arg_running_as == SYSTEMD_SYSTEM && arg_action == ACTION_RUN)
@@ -1551,7 +1549,7 @@ int main(int argc, char *argv[]) {
         manager_set_default_rlimits(m, arg_default_rlimit);
 
         if (arg_default_environment)
-                manager_environment_add(m, arg_default_environment);
+                manager_environment_add(m, NULL, arg_default_environment);
 
         manager_set_show_status(m, arg_show_status);
 
@@ -1575,19 +1573,16 @@ int main(int argc, char *argv[]) {
         }
 
         if (queue_default_job) {
-                DBusError error;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 Unit *target = NULL;
                 Job *default_unit_job;
 
-                dbus_error_init(&error);
-
                 log_debug("Activating default unit: %s", arg_default_unit);
 
                 r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
-                if (r < 0) {
-                        log_error("Failed to load default target: %s", bus_error(&error, r));
-                        dbus_error_free(&error);
-                } else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND)
+                if (r < 0)
+                        log_error("Failed to load default target: %s", bus_error_message(&error, r));
+                else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND)
                         log_error("Failed to load default target: %s", strerror(-target->load_error));
                 else if (target->load_state == UNIT_MASKED)
                         log_error("Default target masked.");
@@ -1597,8 +1592,7 @@ int main(int argc, char *argv[]) {
 
                         r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
                         if (r < 0) {
-                                log_error("Failed to load rescue target: %s", bus_error(&error, r));
-                                dbus_error_free(&error);
+                                log_error("Failed to load rescue target: %s", bus_error_message(&error, r));
                                 goto finish;
                         } else if (target->load_state == UNIT_ERROR || target->load_state == UNIT_NOT_FOUND) {
                                 log_error("Failed to load rescue target: %s", strerror(-target->load_error));
@@ -1618,18 +1612,15 @@ int main(int argc, char *argv[]) {
 
                 r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, false, &error, &default_unit_job);
                 if (r == -EPERM) {
-                        log_debug("Default target could not be isolated, starting instead: %s", bus_error(&error, r));
-                        dbus_error_free(&error);
+                        log_debug("Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
 
                         r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
                         if (r < 0) {
-                                log_error("Failed to start default target: %s", bus_error(&error, r));
-                                dbus_error_free(&error);
+                                log_error("Failed to start default target: %s", bus_error_message(&error, r));
                                 goto finish;
                         }
                 } else if (r < 0) {
-                        log_error("Failed to isolate default target: %s", bus_error(&error, r));
-                        dbus_error_free(&error);
+                        log_error("Failed to isolate default target: %s", bus_error_message(&error, r));
                         goto finish;
                 }
 
@@ -1725,7 +1716,6 @@ finish:
         free(arg_default_unit);
         free_join_controllers();
 
-        dbus_shutdown();
         label_finish();
 
         if (reexecute) {
index c99a022cd5390ffc42d66848c223d3c4d6f0ab8a..86de0e3fbfad4eb003254392d89ce8962a2b9630 100644 (file)
@@ -42,9 +42,9 @@
 #include <libaudit.h>
 #endif
 
-#include "systemd/sd-daemon.h"
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include "sd-daemon.h"
+#include "sd-id128.h"
+#include "sd-messages.h"
 
 #include "manager.h"
 #include "transaction.h"
 #include "locale-setup.h"
 #include "mount-setup.h"
 #include "unit-name.h"
-#include "dbus-unit.h"
-#include "dbus-job.h"
 #include "missing.h"
 #include "path-lookup.h"
 #include "special.h"
-#include "bus-errors.h"
 #include "exit-status.h"
 #include "virt.h"
 #include "watchdog.h"
 #include "audit-fd.h"
 #include "boot-timestamps.h"
 #include "env-util.h"
+#include "bus-errors.h"
+#include "bus-error.h"
+#include "bus-util.h"
+#include "dbus.h"
+#include "dbus-unit.h"
+#include "dbus-job.h"
+#include "dbus-manager.h"
 
 /* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
 #define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
 
 #define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
 
+static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata);
+
 static int manager_setup_notify(Manager *m) {
         union {
                 struct sockaddr sa;
@@ -93,15 +103,10 @@ static int manager_setup_notify(Manager *m) {
         } sa = {
                 .sa.sa_family = AF_UNIX,
         };
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->notify_watch,
-        };
         int one = 1, r;
 
-        m->notify_watch.type = WATCH_NOTIFY;
-        m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
-        if (m->notify_watch.fd < 0) {
+        m->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (m->notify_fd < 0) {
                 log_error("Failed to allocate notification socket: %m");
                 return -errno;
         }
@@ -110,25 +115,23 @@ static int manager_setup_notify(Manager *m) {
                 snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET "/%llu", random_ull());
         else
                 strncpy(sa.un.sun_path, NOTIFY_SOCKET, sizeof(sa.un.sun_path));
-
         sa.un.sun_path[0] = 0;
 
-        r = bind(m->notify_watch.fd, &sa.sa,
-                 offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1));
+        r = bind(m->notify_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1));
         if (r < 0) {
                 log_error("bind() failed: %m");
                 return -errno;
         }
 
-        r = setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
+        r = setsockopt(m->notify_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
         if (r < 0) {
                 log_error("SO_PASSCRED failed: %m");
                 return -errno;
         }
 
-        r = epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev);
+        r = sd_event_add_io(m->event, m->notify_fd, EPOLLIN, manager_dispatch_notify_fd, m, &m->notify_event_source);
         if (r < 0) {
-                log_error("Failed to add notification socket fd to epoll: %m");
+                log_error("Failed to allocate notify event source: %s", strerror(-r));
                 return -errno;
         }
 
@@ -142,75 +145,17 @@ static int manager_setup_notify(Manager *m) {
         return 0;
 }
 
-static int manager_jobs_in_progress_mod_timer(Manager *m) {
-        struct itimerspec its = {
-                .it_value.tv_sec = JOBS_IN_PROGRESS_WAIT_SEC,
-                .it_interval.tv_sec = JOBS_IN_PROGRESS_PERIOD_SEC,
-        };
-
-        if (m->jobs_in_progress_watch.type != WATCH_JOBS_IN_PROGRESS)
-                return 0;
-
-        if (timerfd_settime(m->jobs_in_progress_watch.fd, 0, &its, NULL) < 0)
-                return -errno;
-
-        return 0;
-}
-
 static int manager_watch_jobs_in_progress(Manager *m) {
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->jobs_in_progress_watch,
-        };
-        int r;
+        assert(m);
 
-        if (m->jobs_in_progress_watch.type != WATCH_INVALID)
+        if (m->jobs_in_progress_event_source)
                 return 0;
 
-        m->jobs_in_progress_watch.type = WATCH_JOBS_IN_PROGRESS;
-        m->jobs_in_progress_watch.fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
-        if (m->jobs_in_progress_watch.fd < 0) {
-                log_error("Failed to create timerfd: %m");
-                r = -errno;
-                goto err;
-        }
-
-        r = manager_jobs_in_progress_mod_timer(m);
-        if (r < 0) {
-                log_error("Failed to set up timer for jobs progress watch: %s", strerror(-r));
-                goto err;
-        }
-
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->jobs_in_progress_watch.fd, &ev) < 0) {
-                log_error("Failed to add jobs progress timer fd to epoll: %m");
-                r = -errno;
-                goto err;
-        }
-
-        log_debug("Set up jobs progress timerfd.");
-
-        return 0;
-
-err:
-        if (m->jobs_in_progress_watch.fd >= 0)
-                close_nointr_nofail(m->jobs_in_progress_watch.fd);
-        watch_init(&m->jobs_in_progress_watch);
-        return r;
+        return sd_event_add_monotonic(m->event, JOBS_IN_PROGRESS_WAIT_SEC, 0, manager_dispatch_jobs_in_progress, m, &m->jobs_in_progress_event_source);
 }
 
-static void manager_unwatch_jobs_in_progress(Manager *m) {
-        if (m->jobs_in_progress_watch.type != WATCH_JOBS_IN_PROGRESS)
-                return;
-
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->jobs_in_progress_watch.fd, NULL) >= 0);
-        close_nointr_nofail(m->jobs_in_progress_watch.fd);
-        watch_init(&m->jobs_in_progress_watch);
-        m->jobs_in_progress_iteration = 0;
-
-        log_debug("Closed jobs progress timerfd.");
-}
+#define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1))
 
-#define CYLON_BUFFER_EXTRA (2*strlen(ANSI_RED_ON) + strlen(ANSI_HIGHLIGHT_RED_ON) + 2*strlen(ANSI_HIGHLIGHT_OFF))
 static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
         char *p = buffer;
 
@@ -241,13 +186,15 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po
 }
 
 static void manager_print_jobs_in_progress(Manager *m) {
+        _cleanup_free_ char *job_of_n = NULL;
         Iterator i;
         Job *j;
-        char *job_of_n = NULL;
         unsigned counter = 0, print_nr;
         char cylon[6 + CYLON_BUFFER_EXTRA + 1];
         unsigned cylon_pos;
 
+        assert(m);
+
         print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs;
 
         HASHMAP_FOREACH(j, m->jobs, i)
@@ -270,94 +217,69 @@ static void manager_print_jobs_in_progress(Manager *m) {
 
         manager_status_printf(m, true, cylon, "%sA %s job is running for %s",
                               strempty(job_of_n), job_type_to_string(j->type), unit_description(j->unit));
-        free(job_of_n);
 
         m->jobs_in_progress_iteration++;
 }
 
 static int manager_watch_idle_pipe(Manager *m) {
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->idle_pipe_watch,
-        };
         int r;
 
-        if (m->idle_pipe_watch.type != WATCH_INVALID)
+        assert(m);
+
+        if (m->idle_pipe_event_source)
                 return 0;
 
         if (m->idle_pipe[2] < 0)
                 return 0;
 
-        m->idle_pipe_watch.type = WATCH_IDLE_PIPE;
-        m->idle_pipe_watch.fd = m->idle_pipe[2];
-        if (m->idle_pipe_watch.fd < 0) {
-                log_error("Failed to create timerfd: %m");
-                r = -errno;
-                goto err;
-        }
-
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_pipe_watch.fd, &ev) < 0) {
-                log_error("Failed to add idle_pipe fd to epoll: %m");
-                r = -errno;
-                goto err;
+        r = sd_event_add_io(m->event, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m, &m->idle_pipe_event_source);
+        if (r < 0) {
+                log_error("Failed to watch idle pipe: %s", strerror(-r));
+                return r;
         }
 
-        log_debug("Set up idle_pipe watch.");
-
         return 0;
-
-err:
-        if (m->idle_pipe_watch.fd >= 0)
-                close_nointr_nofail(m->idle_pipe_watch.fd);
-        watch_init(&m->idle_pipe_watch);
-        return r;
 }
 
-static void manager_unwatch_idle_pipe(Manager *m) {
-        if (m->idle_pipe_watch.type != WATCH_IDLE_PIPE)
-                return;
-
-        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->idle_pipe_watch.fd, NULL) >= 0);
-        watch_init(&m->idle_pipe_watch);
+static void manager_close_idle_pipe(Manager *m) {
+        assert(m);
 
-        log_debug("Closed idle_pipe watch.");
+        close_pipe(m->idle_pipe);
+        close_pipe(m->idle_pipe + 2);
 }
 
 static int manager_setup_time_change(Manager *m) {
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->time_change_watch,
-        };
+        int r;
 
         /* We only care for the cancellation event, hence we set the
          * timeout to the latest possible value. */
         struct itimerspec its = {
                 .it_value.tv_sec = TIME_T_MAX,
         };
-        assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
 
-        assert(m->time_change_watch.type == WATCH_INVALID);
+        assert(m);
+        assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
 
         /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
          * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
 
-        m->time_change_watch.type = WATCH_TIME_CHANGE;
-        m->time_change_watch.fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
-        if (m->time_change_watch.fd < 0) {
+        m->time_change_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+        if (m->time_change_fd < 0) {
                 log_error("Failed to create timerfd: %m");
                 return -errno;
         }
 
-        if (timerfd_settime(m->time_change_watch.fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
+        if (timerfd_settime(m->time_change_fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
                 log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
-                close_nointr_nofail(m->time_change_watch.fd);
-                watch_init(&m->time_change_watch);
+                close_nointr_nofail(m->time_change_fd);
+                m->time_change_fd = -1;
                 return 0;
         }
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->time_change_watch.fd, &ev) < 0) {
-                log_error("Failed to add timer change fd to epoll: %m");
-                return -errno;
+        r = sd_event_add_io(m->event, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m, &m->time_change_event_source);
+        if (r < 0) {
+                log_error("Failed to create time change event source: %s", strerror(-r));
+                return r;
         }
 
         log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
@@ -366,7 +288,7 @@ static int manager_setup_time_change(Manager *m) {
 }
 
 static int enable_special_signals(Manager *m) {
-        int fd;
+        _cleanup_close_ int fd = -1;
 
         assert(m);
 
@@ -385,23 +307,18 @@ static int enable_special_signals(Manager *m) {
                 /* Enable that we get SIGWINCH on kbrequest */
                 if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
                         log_warning("Failed to enable kbrequest handling: %s", strerror(errno));
-
-                close_nointr_nofail(fd);
         }
 
         return 0;
 }
 
 static int manager_setup_signals(Manager *m) {
-        sigset_t mask;
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.ptr = &m->signal_watch,
-        };
         struct sigaction sa = {
                 .sa_handler = SIG_DFL,
                 .sa_flags = SA_NOCLDSTOP|SA_RESTART,
         };
+        sigset_t mask;
+        int r;
 
         assert(m);
 
@@ -442,13 +359,13 @@ static int manager_setup_signals(Manager *m) {
                         -1);
         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
 
-        m->signal_watch.type = WATCH_SIGNAL;
-        m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
-        if (m->signal_watch.fd < 0)
+        m->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
+        if (m->signal_fd < 0)
                 return -errno;
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
-                return -errno;
+        r = sd_event_add_io(m->event, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m, &m->signal_event_source);
+        if (r < 0)
+                return r;
 
         if (m->running_as == SYSTEMD_SYSTEM)
                 return enable_special_signals(m);
@@ -502,44 +419,39 @@ int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) {
 #endif
 
         m->running_as = running_as;
-        m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
         m->exit_code = _MANAGER_EXIT_CODE_INVALID;
-        m->pin_cgroupfs_fd = -1;
-        m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
 
-        watch_init(&m->signal_watch);
-        watch_init(&m->mount_watch);
-        watch_init(&m->swap_watch);
-        watch_init(&m->udev_watch);
-        watch_init(&m->time_change_watch);
-        watch_init(&m->jobs_in_progress_watch);
+        m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
 
-        m->epoll_fd = m->dev_autofs_fd = -1;
+        m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = -1;
         m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
 
         r = manager_default_environment(m);
         if (r < 0)
                 goto fail;
 
-        if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
+        r = hashmap_ensure_allocated(&m->units, string_hash_func, string_compare_func);
+        if (r < 0)
                 goto fail;
 
-        if (!(m->jobs = hashmap_new(trivial_hash_func, trivial_compare_func)))
+        r = hashmap_ensure_allocated(&m->jobs, trivial_hash_func, trivial_compare_func);
+        if (r < 0)
                 goto fail;
 
-        if (!(m->watch_pids = hashmap_new(trivial_hash_func, trivial_compare_func)))
+        r = hashmap_ensure_allocated(&m->cgroup_unit, string_hash_func, string_compare_func);
+        if (r < 0)
                 goto fail;
 
-        m->cgroup_unit = hashmap_new(string_hash_func, string_compare_func);
-        if (!m->cgroup_unit)
+        r = hashmap_ensure_allocated(&m->watch_pids, trivial_hash_func, trivial_compare_func);
+        if (r < 0)
                 goto fail;
 
-        m->watch_bus = hashmap_new(string_hash_func, string_compare_func);
-        if (!m->watch_bus)
+        r = hashmap_ensure_allocated(&m->watch_bus, string_hash_func, string_compare_func);
+        if (r < 0)
                 goto fail;
 
-        m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
-        if (m->epoll_fd < 0)
+        r = sd_event_default(&m->event);
+        if (r < 0)
                 goto fail;
 
         r = manager_setup_signals(m);
@@ -718,11 +630,6 @@ static void manager_clear_jobs_and_units(Manager *m) {
         m->n_running_jobs = 0;
 }
 
-static void close_idle_pipe(Manager *m) {
-        close_pipe(m->idle_pipe);
-        close_pipe(m->idle_pipe + 2);
-}
-
 void manager_free(Manager *m) {
         UnitType c;
         int i;
@@ -748,16 +655,22 @@ void manager_free(Manager *m) {
         hashmap_free(m->watch_pids);
         hashmap_free(m->watch_bus);
 
-        if (m->epoll_fd >= 0)
-                close_nointr_nofail(m->epoll_fd);
-        if (m->signal_watch.fd >= 0)
-                close_nointr_nofail(m->signal_watch.fd);
-        if (m->notify_watch.fd >= 0)
-                close_nointr_nofail(m->notify_watch.fd);
-        if (m->time_change_watch.fd >= 0)
-                close_nointr_nofail(m->time_change_watch.fd);
-        if (m->jobs_in_progress_watch.fd >= 0)
-                close_nointr_nofail(m->jobs_in_progress_watch.fd);
+        sd_event_source_unref(m->signal_event_source);
+        sd_event_source_unref(m->notify_event_source);
+        sd_event_source_unref(m->time_change_event_source);
+        sd_event_source_unref(m->jobs_in_progress_event_source);
+        sd_event_source_unref(m->idle_pipe_event_source);
+
+        if (m->signal_fd >= 0)
+                close_nointr_nofail(m->signal_fd);
+        if (m->notify_fd >= 0)
+                close_nointr_nofail(m->notify_fd);
+        if (m->time_change_fd >= 0)
+                close_nointr_nofail(m->time_change_fd);
+
+        manager_close_idle_pipe(m);
+
+        sd_event_unref(m->event);
 
         free(m->notify_socket);
 
@@ -767,8 +680,6 @@ void manager_free(Manager *m) {
         hashmap_free(m->cgroup_unit);
         set_free_free(m->unit_path_cache);
 
-        close_idle_pipe(m);
-
         free(m->switch_root);
         free(m->switch_root_init);
 
@@ -929,9 +840,9 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
                 m->n_reloading ++;
 
         /* First, enumerate what we can from all config files */
-        dual_timestamp_get(&m->unitsload_start_timestamp);
+        dual_timestamp_get(&m->units_load_start_timestamp);
         r = manager_enumerate(m);
-        dual_timestamp_get(&m->unitsload_finish_timestamp);
+        dual_timestamp_get(&m->units_load_finish_timestamp);
 
         /* Second, deserialize if there is something to deserialize */
         if (serialization) {
@@ -968,7 +879,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
         return r;
 }
 
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, DBusError *e, Job **_ret) {
+int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
         int r;
         Transaction *tr;
 
@@ -978,12 +889,12 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove
         assert(mode < _JOB_MODE_MAX);
 
         if (mode == JOB_ISOLATE && type != JOB_START) {
-                dbus_set_error(e, BUS_ERROR_INVALID_JOB_MODE, "Isolate is only valid for start.");
+                sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
                 return -EINVAL;
         }
 
         if (mode == JOB_ISOLATE && !unit->allow_isolate) {
-                dbus_set_error(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
+                sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
                 return -EPERM;
         }
 
@@ -1029,7 +940,7 @@ tr_abort:
         return r;
 }
 
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, DBusError *e, Job **_ret) {
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, sd_bus_error *e, Job **_ret) {
         Unit *unit;
         int r;
 
@@ -1088,7 +999,7 @@ int manager_load_unit_prepare(
                 Manager *m,
                 const char *name,
                 const char *path,
-                DBusError *e,
+                sd_bus_error *e,
                 Unit **_ret) {
 
         Unit *ret;
@@ -1101,20 +1012,16 @@ int manager_load_unit_prepare(
         /* This will prepare the unit for loading, but not actually
          * load anything from disk. */
 
-        if (path && !is_path(path)) {
-                dbus_set_error(e, BUS_ERROR_INVALID_PATH, "Path %s is not absolute.", path);
-                return -EINVAL;
-        }
+        if (path && !is_path(path))
+                return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
 
         if (!name)
                 name = path_get_file_name(path);
 
         t = unit_name_to_type(name);
 
-        if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false)) {
-                dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
-                return -EINVAL;
-        }
+        if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, false))
+                return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
 
         ret = manager_get_unit(m, name);
         if (ret) {
@@ -1154,7 +1061,7 @@ int manager_load_unit(
                 Manager *m,
                 const char *name,
                 const char *path,
-                DBusError *e,
+                sd_bus_error *e,
                 Unit **_ret) {
 
         int r;
@@ -1269,16 +1176,26 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) {
         if (m->send_reloading_done) {
                 m->send_reloading_done = false;
 
-                bus_broadcast_reloading(m, false);
+                bus_manager_send_reloading(m, false);
         }
 
+        if (m->queued_message)
+                bus_send_queued_message(m);
+
         return n;
 }
 
-static int manager_process_notify_fd(Manager *m) {
+static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
         ssize_t n;
 
         assert(m);
+        assert(m->notify_fd == fd);
+
+        if (revents != EPOLLIN) {
+                log_warning("Got unexpected poll event for notify fd.");
+                return 0;
+        }
 
         for (;;) {
                 char buf[4096];
@@ -1302,7 +1219,7 @@ static int manager_process_notify_fd(Manager *m) {
                 Unit *u;
                 _cleanup_strv_free_ char **tags = NULL;
 
-                n = recvmsg(m->notify_watch.fd, &msghdr, MSG_DONTWAIT);
+                n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT);
                 if (n <= 0) {
                         if (n == 0)
                                 return -EIO;
@@ -1383,7 +1300,7 @@ static int manager_dispatch_sigchld(Manager *m) {
                  * have queued for us. This ensures that the process
                  * still exists in /proc so that we can figure out
                  * which cgroup and hence unit it belongs to. */
-                r = manager_process_notify_fd(m);
+                r = manager_dispatch_notify_fd(m->notify_event_source, m->notify_fd, EPOLLIN, m);
                 if (r < 0)
                         return r;
 
@@ -1425,32 +1342,34 @@ static int manager_dispatch_sigchld(Manager *m) {
 }
 
 static int manager_start_target(Manager *m, const char *name, JobMode mode) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
-        DBusError error;
-
-        dbus_error_init(&error);
 
         log_debug_unit(name, "Activating special unit %s", name);
 
         r = manager_add_job_by_name(m, JOB_START, name, mode, true, &error, NULL);
         if (r < 0)
-                log_error_unit(name,
-                               "Failed to enqueue %s job: %s", name, bus_error(&error, r));
-
-        dbus_error_free(&error);
+                log_error_unit(name, "Failed to enqueue %s job: %s", name, bus_error_message(&error, r));
 
         return r;
 }
 
-static int manager_process_signal_fd(Manager *m) {
+static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
         ssize_t n;
         struct signalfd_siginfo sfsi;
         bool sigchld = false;
 
         assert(m);
+        assert(m->signal_fd == fd);
+
+        if (revents != EPOLLIN) {
+                log_warning("Got unexpected events from signal file descriptor.");
+                return 0;
+        }
 
         for (;;) {
-                n = read(m->signal_watch.fd, &sfsi, sizeof(sfsi));
+                n = read(m->signal_fd, &sfsi, sizeof(sfsi));
                 if (n != sizeof(sfsi)) {
 
                         if (n >= 0)
@@ -1537,11 +1456,12 @@ static int manager_process_signal_fd(Manager *m) {
                 }
 
                 case SIGUSR2: {
-                        FILE *f;
-                        char *dump = NULL;
+                        _cleanup_free_ char *dump = NULL;
+                        _cleanup_fclose_ FILE *f = NULL;
                         size_t size;
 
-                        if (!(f = open_memstream(&dump, &size))) {
+                        f = open_memstream(&dump, &size);
+                        if (!f) {
                                 log_warning("Failed to allocate memory stream.");
                                 break;
                         }
@@ -1550,16 +1470,11 @@ static int manager_process_signal_fd(Manager *m) {
                         manager_dump_jobs(m, f, "\t");
 
                         if (ferror(f)) {
-                                fclose(f);
-                                free(dump);
                                 log_warning("Failed to write status stream");
                                 break;
                         }
 
-                        fclose(f);
                         log_dump(LOG_INFO, dump);
-                        free(dump);
-
                         break;
                 }
 
@@ -1666,141 +1581,54 @@ static int manager_process_signal_fd(Manager *m) {
         return 0;
 }
 
-static int process_event(Manager *m, struct epoll_event *ev) {
-        int r;
-        Watch *w;
+static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
+        Iterator i;
+        Unit *u;
 
         assert(m);
-        assert(ev);
-
-        assert_se(w = ev->data.ptr);
-
-        if (w->type == WATCH_INVALID)
-                return 0;
-
-        switch (w->type) {
-
-        case WATCH_SIGNAL:
-
-                /* An incoming signal? */
-                if (ev->events != EPOLLIN)
-                        return -EINVAL;
-
-                if ((r = manager_process_signal_fd(m)) < 0)
-                        return r;
-
-                break;
-
-        case WATCH_NOTIFY:
-
-                /* An incoming daemon notification event? */
-                if (ev->events != EPOLLIN)
-                        return -EINVAL;
-
-                if ((r = manager_process_notify_fd(m)) < 0)
-                        return r;
-
-                break;
-
-        case WATCH_FD:
-
-                /* Some fd event, to be dispatched to the units */
-                UNIT_VTABLE(w->data.unit)->fd_event(w->data.unit, w->fd, ev->events, w);
-                break;
-
-        case WATCH_UNIT_TIMER:
-        case WATCH_JOB_TIMER: {
-                uint64_t v;
-                ssize_t k;
-
-                /* Some timer event, to be dispatched to the units */
-                k = read(w->fd, &v, sizeof(v));
-                if (k != sizeof(v)) {
+        assert(m->time_change_fd == fd);
 
-                        if (k < 0 && (errno == EINTR || errno == EAGAIN))
-                                break;
-
-                        log_error("Failed to read timer event counter: %s", k < 0 ? strerror(-k) : "Short read");
-                        return k < 0 ? -errno : -EIO;
-                }
+        log_struct(LOG_INFO,
+                   MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
+                   "MESSAGE=Time has been changed",
+                   NULL);
 
-                if (w->type == WATCH_UNIT_TIMER)
-                        UNIT_VTABLE(w->data.unit)->timer_event(w->data.unit, v, w);
-                else
-                        job_timer_event(w->data.job, v, w);
-                break;
-        }
+        /* Restart the watch */
+        m->time_change_event_source = sd_event_source_unref(m->time_change_event_source);
 
-        case WATCH_MOUNT:
-                /* Some mount table change, intended for the mount subsystem */
-                mount_fd_event(m, ev->events);
-                break;
+        close_nointr_nofail(m->time_change_fd);
+        m->time_change_fd = -1;
 
-        case WATCH_SWAP:
-                /* Some swap table change, intended for the swap subsystem */
-                swap_fd_event(m, ev->events);
-                break;
+        manager_setup_time_change(m);
 
-        case WATCH_UDEV:
-                /* Some notification from udev, intended for the device subsystem */
-                device_fd_event(m, ev->events);
-                break;
-
-        case WATCH_DBUS_WATCH:
-                bus_watch_event(m, w, ev->events);
-                break;
+        HASHMAP_FOREACH(u, m->units, i)
+                if (UNIT_VTABLE(u)->time_change)
+                        UNIT_VTABLE(u)->time_change(u);
 
-        case WATCH_DBUS_TIMEOUT:
-                bus_timeout_event(m, w, ev->events);
-                break;
+        return 0;
+}
 
-        case WATCH_TIME_CHANGE: {
-                Unit *u;
-                Iterator i;
-
-                log_struct(LOG_INFO,
-                           MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
-                           "MESSAGE=Time has been changed",
-                           NULL);
-
-                /* Restart the watch */
-                epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->time_change_watch.fd,
-                          NULL);
-                close_nointr_nofail(m->time_change_watch.fd);
-                watch_init(&m->time_change_watch);
-                manager_setup_time_change(m);
-
-                HASHMAP_FOREACH(u, m->units, i) {
-                        if (UNIT_VTABLE(u)->time_change)
-                                UNIT_VTABLE(u)->time_change(u);
-                }
+static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
 
-                break;
-        }
+        assert(m);
+        assert(m->idle_pipe[2] == fd);
 
-        case WATCH_JOBS_IN_PROGRESS: {
-                uint64_t v;
+        m->no_console_output = m->n_on_console > 0;
 
-                /* not interested in the data */
-                read(w->fd, &v, sizeof(v));
+        m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
+        manager_close_idle_pipe(m);
 
-                manager_print_jobs_in_progress(m);
-                break;
-        }
-
-        case WATCH_IDLE_PIPE: {
-                m->no_console_output = m->n_on_console > 0;
+        return 0;
+}
 
-                manager_unwatch_idle_pipe(m);
-                close_idle_pipe(m);
-                break;
-        }
+static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) {
+        Manager *m = userdata;
 
-        default:
-                log_error("event type=%i", w->type);
-                assert_not_reached("Unknown epoll event type.");
-        }
+        assert(m);
 
+        manager_print_jobs_in_progress(m);
         return 0;
 }
 
@@ -1825,9 +1653,7 @@ int manager_loop(Manager *m) {
                 return r;
 
         while (m->exit_code == MANAGER_RUNNING) {
-                struct epoll_event event;
-                int n;
-                int wait_msec = -1;
+                usec_t wait_usec;
 
                 if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM)
                         watchdog_ping();
@@ -1854,44 +1680,28 @@ int manager_loop(Manager *m) {
                 if (manager_dispatch_run_queue(m) > 0)
                         continue;
 
-                if (bus_dispatch(m) > 0)
-                        continue;
-
                 if (manager_dispatch_dbus_queue(m) > 0)
                         continue;
 
-                if (swap_dispatch_reload(m) > 0)
-                        continue;
-
                 /* Sleep for half the watchdog time */
                 if (m->runtime_watchdog > 0 && m->running_as == SYSTEMD_SYSTEM) {
-                        wait_msec = (int) (m->runtime_watchdog / 2 / USEC_PER_MSEC);
-                        if (wait_msec <= 0)
-                                wait_msec = 1;
+                        wait_usec = m->runtime_watchdog / 2;
+                        if (wait_usec <= 0)
+                                wait_usec = 1;
                 } else
-                        wait_msec = -1;
-
-                n = epoll_wait(m->epoll_fd, &event, 1, wait_msec);
-                if (n < 0) {
+                        wait_usec = (usec_t) -1;
 
-                        if (errno == EINTR)
-                                continue;
-
-                        return -errno;
-                } else if (n == 0)
-                        continue;
-
-                assert(n == 1);
-
-                r = process_event(m, &event);
-                if (r < 0)
+                r = sd_event_run(m->event, wait_usec);
+                if (r < 0) {
+                        log_error("Failed to run event loop: %s", strerror(-r));
                         return r;
+                }
         }
 
         return m->exit_code;
 }
 
-int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u) {
+int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u) {
         _cleanup_free_ char *n = NULL;
         Unit *u;
         int r;
@@ -1914,18 +1724,20 @@ int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Un
 }
 
 int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) {
-        Job *j;
+        const char *p;
         unsigned id;
+        Job *j;
         int r;
 
         assert(m);
         assert(s);
         assert(_j);
 
-        if (!startswith(s, "/org/freedesktop/systemd1/job/"))
+        p = startswith(s, "/org/freedesktop/systemd1/job/");
+        if (!p)
                 return -EINVAL;
 
-        r = safe_atou(s + 30, &id);
+        r = safe_atou(p, &id);
         if (r < 0)
                 return r;
 
@@ -2060,29 +1872,13 @@ void manager_dispatch_bus_name_owner_changed(
         assert(m);
         assert(name);
 
-        if (!(u = hashmap_get(m->watch_bus, name)))
+        u = hashmap_get(m->watch_bus, name);
+        if (!u)
                 return;
 
         UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner);
 }
 
-void manager_dispatch_bus_query_pid_done(
-                Manager *m,
-                const char *name,
-                pid_t pid) {
-
-        Unit *u;
-
-        assert(m);
-        assert(name);
-        assert(pid >= 1);
-
-        if (!(u = hashmap_get(m->watch_bus, name)))
-                return;
-
-        UNIT_VTABLE(u)->bus_query_pid_done(u, name, pid);
-}
-
 int manager_open_serialization(Manager *m, FILE **_f) {
         char *path = NULL;
         int fd = -1;
@@ -2140,13 +1936,19 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
         fprintf(f, "n-failed-jobs=%u\n", m->n_failed_jobs);
 
         dual_timestamp_serialize(f, "firmware-timestamp", &m->firmware_timestamp);
-        dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp);
         dual_timestamp_serialize(f, "loader-timestamp", &m->loader_timestamp);
+        dual_timestamp_serialize(f, "kernel-timestamp", &m->kernel_timestamp);
         dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp);
 
         if (!in_initrd()) {
                 dual_timestamp_serialize(f, "userspace-timestamp", &m->userspace_timestamp);
                 dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
+                dual_timestamp_serialize(f, "security-start-timestamp", &m->security_start_timestamp);
+                dual_timestamp_serialize(f, "security-finish-timestamp", &m->security_finish_timestamp);
+                dual_timestamp_serialize(f, "generators-start-timestamp", &m->generators_start_timestamp);
+                dual_timestamp_serialize(f, "generators-finish-timestamp", &m->generators_finish_timestamp);
+                dual_timestamp_serialize(f, "units-load-start-timestamp", &m->units_load_start_timestamp);
+                dual_timestamp_serialize(f, "units-load-finish-timestamp", &m->units_load_finish_timestamp);
         }
 
         if (!switching_root) {
@@ -2229,6 +2031,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 log_debug("Failed to parse current job id value %s", l+15);
                         else
                                 m->current_job_id = MAX(m->current_job_id, id);
+
                 } else if (startswith(l, "n-installed-jobs=")) {
                         uint32_t n;
 
@@ -2236,6 +2039,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 log_debug("Failed to parse installed jobs counter %s", l+17);
                         else
                                 m->n_installed_jobs += n;
+
                 } else if (startswith(l, "n-failed-jobs=")) {
                         uint32_t n;
 
@@ -2243,6 +2047,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 log_debug("Failed to parse failed jobs counter %s", l+14);
                         else
                                 m->n_failed_jobs += n;
+
                 } else if (startswith(l, "taint-usr=")) {
                         int b;
 
@@ -2250,6 +2055,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                                 log_debug("Failed to parse taint /usr flag %s", l+10);
                         else
                                 m->taint_usr = m->taint_usr || b;
+
                 } else if (startswith(l, "firmware-timestamp="))
                         dual_timestamp_deserialize(l+19, &m->firmware_timestamp);
                 else if (startswith(l, "loader-timestamp="))
@@ -2262,6 +2068,18 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
                         dual_timestamp_deserialize(l+20, &m->userspace_timestamp);
                 else if (startswith(l, "finish-timestamp="))
                         dual_timestamp_deserialize(l+17, &m->finish_timestamp);
+                else if (startswith(l, "security-start-timestamp="))
+                        dual_timestamp_deserialize(l+25, &m->security_start_timestamp);
+                else if (startswith(l, "security-finish-timestamp="))
+                        dual_timestamp_deserialize(l+26, &m->security_finish_timestamp);
+                else if (startswith(l, "generators-start-timestamp="))
+                        dual_timestamp_deserialize(l+27, &m->generators_start_timestamp);
+                else if (startswith(l, "generators-finish-timestamp="))
+                        dual_timestamp_deserialize(l+28, &m->generators_finish_timestamp);
+                else if (startswith(l, "units-load-start-timestamp="))
+                        dual_timestamp_deserialize(l+27, &m->units_load_start_timestamp);
+                else if (startswith(l, "units-load-finish-timestamp="))
+                        dual_timestamp_deserialize(l+28, &m->units_load_finish_timestamp);
                 else if (startswith(l, "env=")) {
                         _cleanup_free_ char *uce = NULL;
                         char **e;
@@ -2333,7 +2151,7 @@ int manager_reload(Manager *m) {
                 return r;
 
         m->n_reloading ++;
-        bus_broadcast_reloading(m, true);
+        bus_manager_send_reloading(m, true);
 
         fds = fdset_new();
         if (!fds) {
@@ -2450,16 +2268,16 @@ void manager_check_finished(Manager *m) {
         assert(m);
 
         if (m->n_running_jobs == 0)
-                manager_unwatch_jobs_in_progress(m);
+                m->jobs_in_progress_event_source = sd_event_source_unref(m->jobs_in_progress_event_source);
 
-        if (hashmap_size(m->jobs) > 0) {
-                manager_jobs_in_progress_mod_timer(m);
+        if (hashmap_size(m->jobs) > 0 && m->jobs_in_progress_event_source) {
+                sd_event_source_set_time(m->jobs_in_progress_event_source, JOBS_IN_PROGRESS_PERIOD_SEC);
                 return;
         }
 
         /* Notify Type=idle units that we are done now */
-        manager_unwatch_idle_pipe(m);
-        close_idle_pipe(m);
+        m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
+        manager_close_idle_pipe(m);
 
         /* Turn off confirm spawn now */
         m->confirm_spawn = false;
@@ -2526,7 +2344,7 @@ void manager_check_finished(Manager *m) {
                                    NULL);
         }
 
-        bus_broadcast_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
+        bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec);
 
         sd_notifyf(false,
                    "READY=1\nSTATUS=Startup finished in %s.",
@@ -2590,7 +2408,7 @@ static void trim_generator_dir(Manager *m, char **generator) {
 }
 
 void manager_run_generators(Manager *m) {
-        DIR *d = NULL;
+        _cleanup_closedir_ DIR *d = NULL;
         const char *generator_path;
         const char *argv[5];
         int r;
@@ -2626,17 +2444,13 @@ void manager_run_generators(Manager *m) {
         argv[3] = m->generator_unit_path_late;
         argv[4] = NULL;
 
-        RUN_WITH_UMASK(0022) {
+        RUN_WITH_UMASK(0022)
                 execute_directory(generator_path, d, (char**) argv);
-        }
 
+finish:
         trim_generator_dir(m, &m->generator_unit_path);
         trim_generator_dir(m, &m->generator_unit_path_early);
         trim_generator_dir(m, &m->generator_unit_path_late);
-
-finish:
-        if (d)
-                closedir(d);
 }
 
 static void remove_generator_dir(Manager *m, char **generator) {
@@ -2661,17 +2475,36 @@ void manager_undo_generators(Manager *m) {
         remove_generator_dir(m, &m->generator_unit_path_late);
 }
 
-int manager_environment_add(Manager *m, char **environment) {
-        char **e = NULL;
+int manager_environment_add(Manager *m, char **minus, char **plus) {
+        char **a = NULL, **b = NULL, **l;
         assert(m);
 
-        e = strv_env_merge(2, m->environment, environment);
-        if (!e)
-                return -ENOMEM;
+        l = m->environment;
 
-        strv_free(m->environment);
-        m->environment = e;
+        if (!strv_isempty(minus)) {
+                a = strv_env_delete(l, 1, minus);
+                if (!a)
+                        return -ENOMEM;
+
+                l = a;
+        }
+
+        if (!strv_isempty(plus)) {
+                b = strv_env_merge(2, l, plus);
+                if (!b)
+                        return -ENOMEM;
 
+                l = b;
+        }
+
+        if (m->environment != l)
+                strv_free(m->environment);
+        if (a != l)
+                strv_free(a);
+        if (b != l)
+                strv_free(b);
+
+        m->environment = l;
         return 0;
 }
 
@@ -2802,10 +2635,3 @@ Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
 
         return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
 }
-
-void watch_init(Watch *w) {
-        assert(w);
-
-        w->type = WATCH_INVALID;
-        w->fd = -1;
-}
index b04397034013beb51bedfcae4afbb8527b9921fe..9eddef20dc1165401f886384678c0a77a97fcdb8 100644 (file)
@@ -24,8 +24,9 @@
 #include <stdbool.h>
 #include <inttypes.h>
 #include <stdio.h>
-#include <dbus/dbus.h>
 
+#include "sd-bus.h"
+#include "sd-event.h"
 #include "fdset.h"
 #include "cgroup-util.h"
 
@@ -33,8 +34,6 @@
 #define MANAGER_MAX_NAMES 131072 /* 128K */
 
 typedef struct Manager Manager;
-typedef enum WatchType WatchType;
-typedef struct Watch Watch;
 
 typedef enum ManagerExitCode {
         MANAGER_RUNNING,
@@ -50,42 +49,11 @@ typedef enum ManagerExitCode {
         _MANAGER_EXIT_CODE_INVALID = -1
 } ManagerExitCode;
 
-enum WatchType {
-        WATCH_INVALID,
-        WATCH_SIGNAL,
-        WATCH_NOTIFY,
-        WATCH_FD,
-        WATCH_UNIT_TIMER,
-        WATCH_JOB_TIMER,
-        WATCH_MOUNT,
-        WATCH_SWAP,
-        WATCH_UDEV,
-        WATCH_DBUS_WATCH,
-        WATCH_DBUS_TIMEOUT,
-        WATCH_TIME_CHANGE,
-        WATCH_JOBS_IN_PROGRESS,
-        WATCH_IDLE_PIPE,
-};
-
-struct Watch {
-        int fd;
-        WatchType type;
-        union {
-                struct Unit *unit;
-                struct Job *job;
-                DBusWatch *bus_watch;
-                DBusTimeout *bus_timeout;
-        } data;
-        bool fd_is_dupped:1;
-        bool socket_accept:1;
-};
-
 #include "unit.h"
 #include "job.h"
 #include "hashmap.h"
 #include "list.h"
 #include "set.h"
-#include "dbus.h"
 #include "path-lookup.h"
 #include "execute.h"
 #include "unit-name.h"
@@ -125,17 +93,21 @@ struct Manager {
         /* Units that should be realized */
         LIST_HEAD(Unit, cgroup_queue);
 
+        sd_event *event;
+
         Hashmap *watch_pids;  /* pid => Unit object n:1 */
 
         char *notify_socket;
+        int notify_fd;
+        sd_event_source *notify_event_source;
+
+        int signal_fd;
+        sd_event_source *signal_event_source;
 
-        Watch notify_watch;
-        Watch signal_watch;
-        Watch time_change_watch;
-        Watch jobs_in_progress_watch;
-        Watch idle_pipe_watch;
+        int time_change_fd;
+        sd_event_source *time_change_event_source;
 
-        int epoll_fd;
+        sd_event_source *jobs_in_progress_event_source;
 
         unsigned n_snapshots;
 
@@ -157,8 +129,8 @@ struct Manager {
         dual_timestamp security_finish_timestamp;
         dual_timestamp generators_start_timestamp;
         dual_timestamp generators_finish_timestamp;
-        dual_timestamp unitsload_start_timestamp;
-        dual_timestamp unitsload_finish_timestamp;
+        dual_timestamp units_load_start_timestamp;
+        dual_timestamp units_load_finish_timestamp;
 
         char *generator_unit_path;
         char *generator_unit_path_early;
@@ -167,34 +139,33 @@ struct Manager {
         /* Data specific to the device subsystem */
         struct udev* udev;
         struct udev_monitor* udev_monitor;
-        Watch udev_watch;
+        sd_event_source *udev_event_source;
         Hashmap *devices_by_sysfs;
 
         /* Data specific to the mount subsystem */
         FILE *proc_self_mountinfo;
-        Watch mount_watch;
+        sd_event_source *mount_event_source;
 
         /* Data specific to the swap filesystem */
         FILE *proc_swaps;
+        sd_event_source *swap_event_source;
         Hashmap *swaps_by_proc_swaps;
         bool request_reload;
-        Watch swap_watch;
 
         /* Data specific to the D-Bus subsystem */
-        DBusConnection *api_bus, *system_bus;
-        DBusServer *private_bus;
-        Set *bus_connections, *bus_connections_for_dispatch;
+        sd_bus *api_bus, *system_bus;
+        Set *private_buses;
+        int private_listen_fd;
+        sd_event_source *private_listen_event_source;
+        Set *subscribed;
 
-        DBusMessage *queued_message; /* This is used during reloading:
+        sd_bus_message *queued_message; /* This is used during reloading:
                                       * before the reload we queue the
                                       * reply message here, and
                                       * afterwards we send it */
-        DBusConnection *queued_message_connection; /* The connection to send the queued message on */
+        sd_bus *queued_message_bus; /* The connection to send the queued message on */
 
         Hashmap *watch_bus;  /* D-Bus names => Unit object n:1 */
-        int32_t name_data_slot;
-        int32_t conn_data_slot;
-        int32_t subscribed_data_slot;
 
         bool send_reloading_done;
 
@@ -253,6 +224,7 @@ struct Manager {
 
         /* Type=idle pipes */
         int idle_pipe[4];
+        sd_event_source *idle_pipe_event_source;
 
         char *switch_root;
         char *switch_root_init;
@@ -276,12 +248,12 @@ int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, U
 
 int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j);
 
-int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret);
-int manager_load_unit(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret);
-int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u);
+int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
+int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret);
+int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u);
 
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool force, DBusError *e, Job **_ret);
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool force, DBusError *e, Job **_ret);
+int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool force, sd_bus_error *e, Job **_ret);
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool force, sd_bus_error *e, Job **_ret);
 
 void manager_dump_units(Manager *s, FILE *f, const char *prefix);
 void manager_dump_jobs(Manager *s, FILE *f, const char *prefix);
@@ -290,13 +262,12 @@ void manager_clear_jobs(Manager *m);
 
 unsigned manager_dispatch_load_queue(Manager *m);
 
-int manager_environment_add(Manager *m, char **environment);
+int manager_environment_add(Manager *m, char **minus, char **plus);
 int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit);
 
 int manager_loop(Manager *m);
 
 void manager_dispatch_bus_name_owner_changed(Manager *m, const char *name, const char* old_owner, const char *new_owner);
-void manager_dispatch_bus_query_pid_done(Manager *m, const char *name, pid_t pid);
 
 int manager_open_serialization(Manager *m, FILE **_f);
 
@@ -325,5 +296,3 @@ void manager_set_show_status(Manager *m, bool b);
 void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) _printf_(4,5);
 
 Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path);
-
-void watch_init(Watch *w);
index 0c15b99f945e85a83aa42ee86acfb0062d9ed6b3..99e7cedc459da0144f7ff79fd388a50cdb5c307d 100644 (file)
@@ -59,6 +59,9 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
         [MOUNT_FAILED] = UNIT_FAILED
 };
 
+static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+
 static char* mount_test_option(const char *haystack, const char *needle) {
         struct mntent me = { .mnt_opts = (char*) haystack };
 
@@ -156,13 +159,32 @@ static void mount_init(Unit *u) {
          * already trying to comply its last one. */
         m->exec_context.same_pgrp = true;
 
-        m->timer_watch.type = WATCH_INVALID;
-
         m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
 
         UNIT(m)->ignore_on_isolate = true;
 }
 
+static int mount_arm_timer(Mount *m) {
+        int r;
+
+        assert(m);
+
+        if (m->timeout_usec <= 0) {
+                m->timer_event_source = sd_event_source_unref(m->timer_event_source);
+                return 0;
+        }
+
+        if (m->timer_event_source) {
+                r = sd_event_source_set_time(m->timer_event_source, now(CLOCK_MONOTONIC) + m->timeout_usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(m)->manager->event, now(CLOCK_MONOTONIC) + m->timeout_usec, 0, mount_dispatch_timer, m, &m->timer_event_source);
+}
+
 static void mount_unwatch_control_pid(Mount *m) {
         assert(m);
 
@@ -201,7 +223,7 @@ static void mount_done(Unit *u) {
 
         mount_unwatch_control_pid(m);
 
-        unit_unwatch_timer(u, &m->timer_watch);
+        m->timer_event_source = sd_event_source_unref(m->timer_event_source);
 }
 
 _pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) {
@@ -626,7 +648,7 @@ static void mount_set_state(Mount *m, MountState state) {
             state != MOUNT_UNMOUNTING_SIGKILL &&
             state != MOUNT_REMOUNTING_SIGTERM &&
             state != MOUNT_REMOUNTING_SIGKILL) {
-                unit_unwatch_timer(UNIT(m), &m->timer_watch);
+                m->timer_event_source = sd_event_source_unref(m->timer_event_source);
                 mount_unwatch_control_pid(m);
                 m->control_command = NULL;
                 m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
@@ -692,7 +714,7 @@ static int mount_coldplug(Unit *u) {
                         if (r < 0)
                                 return r;
 
-                        r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
+                        r = mount_arm_timer(m);
                         if (r < 0)
                                 return r;
                 }
@@ -751,7 +773,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
 
         unit_realize_cgroup(UNIT(m));
 
-        r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
+        r = mount_arm_timer(m);
         if (r < 0)
                 goto fail;
 
@@ -782,7 +804,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
         return 0;
 
 fail:
-        unit_unwatch_timer(UNIT(m), &m->timer_watch);
+        m->timer_event_source = sd_event_source_unref(m->timer_event_source);
 
         return r;
 }
@@ -825,7 +847,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
                 goto fail;
 
         if (r > 0) {
-                r = unit_watch_timer(UNIT(m), CLOCK_MONOTONIC, true, m->timeout_usec, &m->timer_watch);
+                r = mount_arm_timer(m);
                 if (r < 0)
                         goto fail;
 
@@ -959,17 +981,11 @@ static void mount_enter_remounting(Mount *m) {
         m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT;
 
         if (m->from_fragment) {
-                char *buf = NULL;
                 const char *o;
 
-                if (m->parameters_fragment.options) {
-                        if (!(buf = strappend("remount,", m->parameters_fragment.options))) {
-                                r = -ENOMEM;
-                                goto fail;
-                        }
-
-                        o = buf;
-                } else
+                if (m->parameters_fragment.options)
+                        o = strappenda("remount,", m->parameters_fragment.options);
+                else
                         o = "remount";
 
                 r = exec_command_set(
@@ -980,8 +996,6 @@ static void mount_enter_remounting(Mount *m) {
                                 "-t", m->parameters_fragment.fstype ? m->parameters_fragment.fstype : "auto",
                                 "-o", o,
                                 NULL);
-
-                free(buf);
         } else
                 r = -ENOENT;
 
@@ -990,7 +1004,8 @@ static void mount_enter_remounting(Mount *m) {
 
         mount_unwatch_control_pid(m);
 
-        if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
+        r = mount_spawn(m, m->control_command, &m->control_pid);
+        if (r < 0)
                 goto fail;
 
         mount_set_state(m, MOUNT_REMOUNTING);
@@ -1279,44 +1294,43 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         unit_add_to_dbus_queue(u);
 }
 
-static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
-        Mount *m = MOUNT(u);
+static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Mount *m = MOUNT(userdata);
 
         assert(m);
-        assert(elapsed == 1);
-        assert(w == &m->timer_watch);
+        assert(m->timer_event_source == source);
 
         switch (m->state) {
 
         case MOUNT_MOUNTING:
         case MOUNT_MOUNTING_DONE:
-                log_warning_unit(u->id,
-                                 "%s mounting timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(m)->id,
+                                 "%s mounting timed out. Stopping.", UNIT(m)->id);
                 mount_enter_signal(m, MOUNT_MOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
                 break;
 
         case MOUNT_REMOUNTING:
-                log_warning_unit(u->id,
-                                 "%s remounting timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(m)->id,
+                                 "%s remounting timed out. Stopping.", UNIT(m)->id);
                 m->reload_result = MOUNT_FAILURE_TIMEOUT;
                 mount_enter_mounted(m, MOUNT_SUCCESS);
                 break;
 
         case MOUNT_UNMOUNTING:
-                log_warning_unit(u->id,
-                                 "%s unmounting timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(m)->id,
+                                 "%s unmounting timed out. Stopping.", UNIT(m)->id);
                 mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT);
                 break;
 
         case MOUNT_MOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s mounting timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(m)->id,
+                                         "%s mounting timed out. Killing.", UNIT(m)->id);
                         mount_enter_signal(m, MOUNT_MOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(m)->id,
                                          "%s mounting timed out. Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(m)->id);
 
                         if (m->from_proc_self_mountinfo)
                                 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1327,13 +1341,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
 
         case MOUNT_REMOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s remounting timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(m)->id,
+                                         "%s remounting timed out. Killing.", UNIT(m)->id);
                         mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(m)->id,
                                          "%s remounting timed out. Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(m)->id);
 
                         if (m->from_proc_self_mountinfo)
                                 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1344,13 +1358,13 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
 
         case MOUNT_UNMOUNTING_SIGTERM:
                 if (m->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s unmounting timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(m)->id,
+                                         "%s unmounting timed out. Killing.", UNIT(m)->id);
                         mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(m)->id,
                                          "%s unmounting timed out. Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(m)->id);
 
                         if (m->from_proc_self_mountinfo)
                                 mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1362,9 +1376,9 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
         case MOUNT_MOUNTING_SIGKILL:
         case MOUNT_REMOUNTING_SIGKILL:
         case MOUNT_UNMOUNTING_SIGKILL:
-                log_warning_unit(u->id,
+                log_warning_unit(UNIT(m)->id,
                                  "%s mount process still around after SIGKILL. Ignoring.",
-                                 u->id);
+                                 UNIT(m)->id);
 
                 if (m->from_proc_self_mountinfo)
                         mount_enter_mounted(m, MOUNT_FAILURE_TIMEOUT);
@@ -1375,6 +1389,8 @@ static void mount_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
 }
 
 static int mount_add_one(
@@ -1582,6 +1598,8 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
 static void mount_shutdown(Manager *m) {
         assert(m);
 
+        m->mount_event_source = sd_event_source_unref(m->mount_event_source);
+
         if (m->proc_self_mountinfo) {
                 fclose(m->proc_self_mountinfo);
                 m->proc_self_mountinfo = NULL;
@@ -1593,20 +1611,13 @@ static int mount_enumerate(Manager *m) {
         assert(m);
 
         if (!m->proc_self_mountinfo) {
-                struct epoll_event ev = {
-                        .events = EPOLLPRI,
-                        .data.ptr = &m->mount_watch,
-                };
-
                 m->proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
                 if (!m->proc_self_mountinfo)
                         return -errno;
 
-                m->mount_watch.type = WATCH_MOUNT;
-                m->mount_watch.fd = fileno(m->proc_self_mountinfo);
-
-                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->mount_watch.fd, &ev) < 0)
-                        return -errno;
+                r = sd_event_add_io(m->event, fileno(m->proc_self_mountinfo), EPOLLPRI, mount_dispatch_io, m, &m->mount_event_source);
+                if (r < 0)
+                        goto fail;
         }
 
         r = mount_load_proc_self_mountinfo(m, false);
@@ -1620,12 +1631,13 @@ fail:
         return r;
 }
 
-void mount_fd_event(Manager *m, int events) {
+static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
         Unit *u;
         int r;
 
         assert(m);
-        assert(events & EPOLLPRI);
+        assert(revents & EPOLLPRI);
 
         /* The manager calls this for every fd event happening on the
          * /proc/self/mountinfo file, which informs us about mounting
@@ -1642,7 +1654,7 @@ void mount_fd_event(Manager *m, int events) {
                         mount->is_mounted = mount->just_mounted = mount->just_changed = false;
                 }
 
-                return;
+                return 0;
         }
 
         manager_dispatch_load_queue(m);
@@ -1696,6 +1708,8 @@ void mount_fd_event(Manager *m, int events) {
                 /* Reset the flags for later calls */
                 mount->is_mounted = mount->just_mounted = mount->just_changed = false;
         }
+
+        return 0;
 }
 
 static void mount_reset_failed(Unit *u) {
@@ -1710,7 +1724,7 @@ static void mount_reset_failed(Unit *u) {
         m->reload_result = MOUNT_SUCCESS;
 }
 
-static int mount_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, MOUNT(u)->control_pid, error);
 }
 
@@ -1753,15 +1767,15 @@ DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult);
 
 const UnitVTable mount_vtable = {
         .object_size = sizeof(Mount),
+        .exec_context_offset = offsetof(Mount, exec_context),
+        .cgroup_context_offset = offsetof(Mount, cgroup_context),
+        .kill_context_offset = offsetof(Mount, kill_context),
 
         .sections =
                 "Unit\0"
                 "Mount\0"
                 "Install\0",
-
         .private_section = "Mount",
-        .exec_context_offset = offsetof(Mount, exec_context),
-        .cgroup_context_offset = offsetof(Mount, cgroup_context),
 
         .no_alias = true,
         .no_instances = true,
@@ -1789,13 +1803,12 @@ const UnitVTable mount_vtable = {
         .check_gc = mount_check_gc,
 
         .sigchld_event = mount_sigchld_event,
-        .timer_event = mount_timer_event,
 
         .reset_failed = mount_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Mount",
-        .bus_message_handler = bus_mount_message_handler,
-        .bus_invalidating_properties =  bus_mount_invalidating_properties,
+        .bus_vtable = bus_mount_vtable,
+        .bus_changing_properties = bus_mount_changing_properties,
         .bus_set_property = bus_mount_set_property,
         .bus_commit_properties = bus_mount_commit_properties,
 
index a9550697e59a150bb9aa46c110ac1bf7ae394f56..2edb75eb544c55a63cb2bf14bb63bc5f66776088 100644 (file)
@@ -107,7 +107,7 @@ struct Mount {
         MountExecCommand control_command_id;
         pid_t control_pid;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
 };
 
 extern const UnitVTable mount_vtable;
index 10df80f695bec6150e8b660d3849d1259996a3eb..51e8d1dbcc7a92c67f909df056ac1872e9c9799d 100644 (file)
 #include "mkdir.h"
 #include "dbus-path.h"
 #include "special.h"
-#include "dbus-common.h"
 #include "path-util.h"
 #include "macro.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
         [PATH_DEAD] = UNIT_INACTIVE,
@@ -42,7 +43,9 @@ static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = {
         [PATH_FAILED] = UNIT_FAILED
 };
 
-int path_spec_watch(PathSpec *s, Unit *u) {
+static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+
+int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) {
 
         static const int flags_table[_PATH_TYPE_MAX] = {
                 [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB,
@@ -56,10 +59,11 @@ int path_spec_watch(PathSpec *s, Unit *u) {
         char *slash, *oldslash = NULL;
         int r;
 
-        assert(u);
         assert(s);
+        assert(s->unit);
+        assert(handler);
 
-        path_spec_unwatch(s, u);
+        path_spec_unwatch(s);
 
         s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
         if (s->inotify_fd < 0) {
@@ -67,7 +71,7 @@ int path_spec_watch(PathSpec *s, Unit *u) {
                 goto fail;
         }
 
-        r = unit_watch_fd(u, s->inotify_fd, EPOLLIN, &s->watch);
+        r = sd_event_add_io(s->unit->manager->event, s->inotify_fd, EPOLLIN, handler, s, &s->event_source);
         if (r < 0)
                 goto fail;
 
@@ -140,29 +144,29 @@ int path_spec_watch(PathSpec *s, Unit *u) {
         return 0;
 
 fail:
-        path_spec_unwatch(s, u);
+        path_spec_unwatch(s);
         return r;
 }
 
-void path_spec_unwatch(PathSpec *s, Unit *u) {
-
-        if (s->inotify_fd < 0)
-                return;
+void path_spec_unwatch(PathSpec *s) {
+        assert(s);
 
-        unit_unwatch_fd(u, &s->watch);
+        s->event_source = sd_event_source_unref(s->event_source);
 
-        close_nointr_nofail(s->inotify_fd);
-        s->inotify_fd = -1;
+        if (s->inotify_fd >= 0) {
+                close_nointr_nofail(s->inotify_fd);
+                s->inotify_fd = -1;
+        }
 }
 
-int path_spec_fd_event(PathSpec *s, uint32_t events) {
+int path_spec_fd_event(PathSpec *s, uint32_t revents) {
         _cleanup_free_ uint8_t *buf = NULL;
         struct inotify_event *e;
         ssize_t k;
         int l;
         int r = 0;
 
-        if (events != EPOLLIN) {
+        if (revents != EPOLLIN) {
                 log_error("Got invalid poll event on inotify.");
                 return -EINVAL;
         }
@@ -282,7 +286,7 @@ void path_free_specs(Path *p) {
         assert(p);
 
         while ((s = p->specs)) {
-                path_spec_unwatch(s, UNIT(p));
+                path_spec_unwatch(s);
                 LIST_REMOVE(spec, p->specs, s);
                 path_spec_done(s);
                 free(s);
@@ -419,7 +423,7 @@ static void path_unwatch(Path *p) {
         assert(p);
 
         LIST_FOREACH(spec, s, p->specs)
-                path_spec_unwatch(s, UNIT(p));
+                path_spec_unwatch(s);
 }
 
 static int path_watch(Path *p) {
@@ -429,7 +433,7 @@ static int path_watch(Path *p) {
         assert(p);
 
         LIST_FOREACH(spec, s, p->specs) {
-                r = path_spec_watch(s, UNIT(p));
+                r = path_spec_watch(s, path_dispatch_io);
                 if (r < 0)
                         return r;
         }
@@ -487,13 +491,11 @@ static void path_enter_dead(Path *p, PathResult f) {
 }
 
 static void path_enter_running(Path *p) {
-        _cleanup_dbus_error_free_ DBusError error;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(p);
 
-        dbus_error_init(&error);
-
         /* Don't start job if we are supposed to go down */
         if (unit_stop_pending(UNIT(p)))
                 return;
@@ -514,7 +516,7 @@ static void path_enter_running(Path *p) {
 
 fail:
         log_warning("%s failed to queue unit startup job: %s",
-                    UNIT(p)->id, bus_error(&error, r));
+                    UNIT(p)->id, bus_error_message(&error, r));
         path_enter_dead(p, PATH_FAILURE_RESOURCES);
 }
 
@@ -664,17 +666,20 @@ _pure_ static const char *path_sub_state_to_string(Unit *u) {
         return path_state_to_string(PATH(u)->state);
 }
 
-static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
-        Path *p = PATH(u);
-        PathSpec *s;
+static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        PathSpec *s = userdata;
+        Path *p;
         int changed;
 
-        assert(p);
+        assert(s);
+        assert(s->unit);
         assert(fd >= 0);
 
+        p = PATH(s->unit);
+
         if (p->state != PATH_WAITING &&
             p->state != PATH_RUNNING)
-                return;
+                return 0;
 
         /* log_debug("inotify wakeup on %s.", u->id); */
 
@@ -687,7 +692,7 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                 goto fail;
         }
 
-        changed = path_spec_fd_event(s, events);
+        changed = path_spec_fd_event(s, revents);
         if (changed < 0)
                 goto fail;
 
@@ -701,10 +706,11 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
         else
                 path_enter_waiting(p, false, true);
 
-        return;
+        return 0;
 
 fail:
         path_enter_dead(p, PATH_FAILURE_RESOURCES);
+        return 0;
 }
 
 static void path_trigger_notify(Unit *u, Unit *other) {
@@ -771,6 +777,7 @@ DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
 
 const UnitVTable path_vtable = {
         .object_size = sizeof(Path),
+
         .sections =
                 "Unit\0"
                 "Path\0"
@@ -793,13 +800,11 @@ const UnitVTable path_vtable = {
         .active_state = path_active_state,
         .sub_state_to_string = path_sub_state_to_string,
 
-        .fd_event = path_fd_event,
-
         .trigger_notify = path_trigger_notify,
 
         .reset_failed = path_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Path",
-        .bus_message_handler = bus_path_message_handler,
-        .bus_invalidating_properties = bus_path_invalidating_properties
+        .bus_vtable = bus_path_vtable,
+        .bus_changing_properties = bus_path_changing_properties
 };
index dec3df70351ea9f6a8b59dde6ce6aea4e6f56fb2..d2e91d7d71ed51f0f8b79718b034c982ff221b06 100644 (file)
@@ -46,9 +46,11 @@ typedef enum PathType {
 } PathType;
 
 typedef struct PathSpec {
+        Unit *unit;
+
         char *path;
 
-        Watch watch;
+        sd_event_source *event_source;
 
         LIST_FIELDS(struct PathSpec, spec);
 
@@ -59,8 +61,8 @@ typedef struct PathSpec {
         bool previous_exists;
 } PathSpec;
 
-int path_spec_watch(PathSpec *s, Unit *u);
-void path_spec_unwatch(PathSpec *s, Unit *u);
+int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler);
+void path_spec_unwatch(PathSpec *s);
 int path_spec_fd_event(PathSpec *s, uint32_t events);
 void path_spec_done(PathSpec *s);
 
index 41da3b9378dc2f083fa8d5bf119aadfd783ef826..a3c94794b1eb4740df9cad886f799ba4ed3991c8 100644 (file)
@@ -40,6 +40,8 @@ static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
         [SCOPE_FAILED] = UNIT_FAILED
 };
 
+static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+
 static void scope_init(Unit *u) {
         Scope *s = SCOPE(u);
 
@@ -48,8 +50,6 @@ static void scope_init(Unit *u) {
 
         s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
 
-        watch_init(&s->timer_watch);
-
         cgroup_context_init(&s->cgroup_context);
         kill_context_init(&s->kill_context);
 
@@ -67,7 +67,28 @@ static void scope_done(Unit *u) {
         set_free(s->pids);
         s->pids = NULL;
 
-        unit_unwatch_timer(u, &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+}
+
+static int scope_arm_timer(Scope *s) {
+        int r;
+
+        assert(s);
+
+        if (s->timeout_stop_usec <= 0) {
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+                return 0;
+        }
+
+        if (s->timer_event_source) {
+                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0, scope_dispatch_timer, s, &s->timer_event_source);
 }
 
 static void scope_set_state(Scope *s, ScopeState state) {
@@ -79,7 +100,7 @@ static void scope_set_state(Scope *s, ScopeState state) {
 
         if (state != SCOPE_STOP_SIGTERM &&
             state != SCOPE_STOP_SIGKILL)
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         if (state != old_state)
                 log_debug("%s changed %s -> %s",
@@ -158,11 +179,9 @@ static int scope_coldplug(Unit *u) {
 
         if (s->deserialized_state != s->state) {
 
-                if ((s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM)
-                    && s->timeout_stop_usec > 0) {
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
+                if (s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM) {
+                        r = scope_arm_timer(s);
                         if (r < 0)
-
                                 return r;
                 }
 
@@ -214,11 +233,9 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
                 goto fail;
 
         if (r > 0) {
-                if (s->timeout_stop_usec > 0) {
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_stop_usec, &s->timer_watch);
-                        if (r < 0)
-                                goto fail;
-                }
+                r = scope_arm_timer(s);
+                if (r < 0)
+                        goto fail;
 
                 scope_set_state(s, state);
         } else
@@ -297,7 +314,7 @@ static void scope_reset_failed(Unit *u) {
         s->result = SCOPE_SUCCESS;
 }
 
-static int scope_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, -1, error);
 }
 
@@ -353,34 +370,35 @@ static bool scope_check_gc(Unit *u) {
         return false;
 }
 
-static void scope_timer_event(Unit *u, uint64_t elapsed, Watch*w) {
-        Scope *s = SCOPE(u);
+static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Scope *s = SCOPE(userdata);
 
         assert(s);
-        assert(elapsed == 1);
-        assert(w == &s->timer_watch);
+        assert(s->timer_event_source == source);
 
         switch (s->state) {
 
         case SCOPE_STOP_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id, "%s stopping timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s stopping timed out. Killing.", UNIT(s)->id);
                         scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id, "%s stopping timed out. Skipping SIGKILL.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
                         scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
                 }
 
                 break;
 
         case SCOPE_STOP_SIGKILL:
-                log_warning_unit(u->id, "%s still around after SIGKILL. Ignoring.", u->id);
+                log_warning_unit(UNIT(s)->id, "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
                 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
                 break;
 
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
 }
 
 static void scope_notify_cgroup_empty_event(Unit *u) {
@@ -435,13 +453,14 @@ DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
 
 const UnitVTable scope_vtable = {
         .object_size = sizeof(Scope),
+        .cgroup_context_offset = offsetof(Scope, cgroup_context),
+        .kill_context_offset = offsetof(Scope, kill_context),
+
         .sections =
                 "Unit\0"
                 "Scope\0"
                 "Install\0",
-
         .private_section = "Scope",
-        .cgroup_context_offset = offsetof(Scope, cgroup_context),
 
         .no_alias = true,
         .no_instances = true,
@@ -467,14 +486,13 @@ const UnitVTable scope_vtable = {
 
         .check_gc = scope_check_gc,
 
-        .timer_event = scope_timer_event,
-
         .reset_failed = scope_reset_failed,
 
         .notify_cgroup_empty = scope_notify_cgroup_empty_event,
 
         .bus_interface = "org.freedesktop.systemd1.Scope",
-        .bus_message_handler = bus_scope_message_handler,
+        .bus_vtable = bus_scope_vtable,
+        .bus_changing_properties = bus_scope_changing_properties,
         .bus_set_property = bus_scope_set_property,
         .bus_commit_properties = bus_scope_commit_properties,
 
index 2a3dcb73d7a0c9f449fdb82090e0843ff261cfb0..4d8a1714bcc1a9385787bec346469fe07b52598f 100644 (file)
@@ -57,7 +57,7 @@ struct Scope {
 
         Set *pids;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
 };
 
 extern const UnitVTable scope_vtable;
index c7e951cde6ea961dbe5a7e7582c07128ec39f7e6..0ecbdf0be6bb2ae21c2577d1adad83ae4aeadfae 100644 (file)
 #ifdef HAVE_AUDIT
 #include <libaudit.h>
 #endif
-#include <dbus.h>
 
+#include "sd-bus.h"
+#include "bus-util.h"
 #include "util.h"
 #include "log.h"
-#include "bus-errors.h"
-#include "dbus-common.h"
 #include "audit.h"
 #include "selinux-util.h"
 #include "audit-fd.h"
@@ -53,72 +52,59 @@ struct auditstruct {
 };
 
 static int bus_get_selinux_security_context(
-                DBusConnection *connection,
+                sd_bus *bus,
                 const char *name,
-                char **scon,
-                DBusError *error) {
+                sd_bus_error *error,
+                char **ret) {
 
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
-        DBusMessageIter iter, sub;
-        const char *bytes;
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        const void *p;
+        size_t sz;
         char *b;
-        int nbytes;
-
-        m = dbus_message_new_method_call(
-                        DBUS_SERVICE_DBUS,
-                        DBUS_PATH_DBUS,
-                        DBUS_INTERFACE_DBUS,
-                        "GetConnectionSELinuxSecurityContext");
-        if (!m) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return -ENOMEM;
-        }
-
-        if (!dbus_message_append_args(
-                            m,
-                            DBUS_TYPE_STRING, &name,
-                            DBUS_TYPE_INVALID)) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return -ENOMEM;
-        }
-
-        reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
-        if (!reply)
-                return -EIO;
-
-        if (dbus_set_error_from_message(error, reply))
-                return -EIO;
-
-        if (!dbus_message_iter_init(reply, &iter))
-                return -EIO;
+        int r;
 
-        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
-                return -EIO;
+        assert(bus);
+        assert(name);
+        assert(ret);
+
+        r = sd_bus_call_method(
+                        bus,
+                        "org.freedesktop.DBus",
+                        "/org/freedesktop/DBus",
+                        "org.freedesktop.DBus",
+                        "GetConnectionSELinuxSecurityContext",
+                        error, &m,
+                        "s", name);
+        if (r < 0)
+                return r;
 
-        dbus_message_iter_recurse(&iter, &sub);
-        dbus_message_iter_get_fixed_array(&sub, &bytes, &nbytes);
+        r = sd_bus_message_read_array(m, 'y', &p, &sz);
+        if (r < 0)
+                return r;
 
-        b = strndup(bytes, nbytes);
+        b = strndup(p, sz);
         if (!b)
                 return -ENOMEM;
 
-        *scon = b;
-
+        *ret = b;
         return 0;
 }
 
 static int bus_get_audit_data(
-                DBusConnection *connection,
+                sd_bus *bus,
                 const char *name,
-                struct auditstruct *audit,
-                DBusError *error) {
+                struct auditstruct *audit) {
 
         pid_t pid;
         int r;
 
-        pid = bus_get_unix_process_id(connection, name, error);
-        if (pid <= 0)
-                return -EIO;
+        assert(bus);
+        assert(name);
+        assert(audit);
+
+        r = sd_bus_get_owner_pid(bus, name, &pid);
+        if (r < 0)
+                return r;
 
         r = audit_loginuid_from_pid(pid, &audit->loginuid);
         if (r < 0)
@@ -207,7 +193,7 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
    If you want to cleanup memory you should need to call selinux_access_finish.
 */
 static int access_init(void) {
-        int r;
+        int r = 0;
 
         if (avc_open(NULL, 0)) {
                 log_error("avc_open() failed: %m");
@@ -217,34 +203,33 @@ static int access_init(void) {
         selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
         selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback);
 
-        if (security_getenforce() >= 0)
-                return 0;
-
-        r = -errno;
-        avc_destroy();
+        if (security_getenforce() < 0){
+                r = -errno;
+                avc_destroy();
+        }
 
         return r;
 }
 
-static int selinux_access_init(DBusError *error) {
+static int selinux_access_init(sd_bus_error *error) {
         int r;
 
         if (initialized)
                 return 0;
 
-        if (use_selinux()) {
-                r = access_init();
-                if (r < 0) {
-                        dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
-                        return r;
-                }
-        }
+        if (!use_selinux())
+                return 0;
+
+        r = access_init();
+        if (r < 0)
+                return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
 
         initialized = true;
         return 0;
 }
 
 void selinux_access_free(void) {
+
         if (!initialized)
                 return;
 
@@ -253,28 +238,27 @@ void selinux_access_free(void) {
 }
 
 static int get_audit_data(
-                DBusConnection *connection,
-                DBusMessage *message,
-                struct auditstruct *audit,
-                DBusError *error) {
+                sd_bus *bus,
+                sd_bus_message *message,
+                struct auditstruct *audit) {
 
+        struct ucred ucred;
         const char *sender;
+        socklen_t len;
         int r, fd;
-        struct ucred ucred;
-        socklen_t len = sizeof(ucred);
 
-        sender = dbus_message_get_sender(message);
+        sender = sd_bus_message_get_sender(message);
         if (sender)
-                return bus_get_audit_data(connection, sender, audit, error);
+                return bus_get_audit_data(bus, sender, audit);
 
-        if (!dbus_connection_get_unix_fd(connection, &fd))
-                return -EINVAL;
+        fd = sd_bus_get_fd(bus);
+        if (fd < 0)
+                return fd;
 
+        len = sizeof(ucred);
         r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
-        if (r < 0) {
-                log_error("Failed to determine peer credentials: %m");
+        if (r < 0)
                 return -errno;
-        }
 
         audit->uid = ucred.uid;
         audit->gid = ucred.gid;
@@ -295,40 +279,30 @@ static int get_audit_data(
    connections.  Whether it is on the bus or a local connection.
 */
 static int get_calling_context(
-                DBusConnection *connection,
-                DBusMessage *message,
-                security_context_t *scon,
-                DBusError *error) {
+                sd_bus *bus,
+                sd_bus_message *message,
+                sd_bus_error *error,
+                security_context_t *ret) {
 
         const char *sender;
-        int r;
-        int fd;
+        int r, fd;
 
         /*
            If sender exists then
            if sender is NULL this indicates a local connection.  Grab the fd
            from dbus and do an getpeercon to peers process context
         */
-        sender = dbus_message_get_sender(message);
-        if (sender) {
-                r = bus_get_selinux_security_context(connection, sender, scon, error);
-                if (r >= 0)
-                        return r;
-
-                log_error("bus_get_selinux_security_context failed: %m");
-                return r;
-        }
+        sender = sd_bus_message_get_sender(message);
+        if (sender)
+                return bus_get_selinux_security_context(bus, sender, error, ret);
 
-        if (!dbus_connection_get_unix_fd(connection, &fd)) {
-                log_error("bus_connection_get_unix_fd failed %m");
-                return -EINVAL;
-        }
+        fd = sd_bus_get_fd(bus);
+        if (fd < 0)
+                return fd;
 
-        r = getpeercon(fd, scon);
-        if (r < 0) {
-                log_error("getpeercon failed %m");
+        r = getpeercon(fd, ret);
+        if (r < 0)
                 return -errno;
-        }
 
         return 0;
 }
@@ -340,18 +314,18 @@ static int get_calling_context(
    still be generated if the access would be denied in enforcing mode.
 */
 int selinux_access_check(
-                DBusConnection *connection,
-                DBusMessage *message,
+                sd_bus *bus,
+                sd_bus_message *message,
                 const char *path,
                 const char *permission,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         security_context_t scon = NULL, fcon = NULL;
-        int r = 0;
         const char *tclass = NULL;
         struct auditstruct audit;
+        int r = 0;
 
-        assert(connection);
+        assert(bus);
         assert(message);
         assert(permission);
         assert(error);
@@ -368,43 +342,36 @@ int selinux_access_check(
         audit.cmdline = NULL;
         audit.path = path;
 
-        r = get_calling_context(connection, message, &scon, error);
-        if (r < 0) {
-                log_error("Failed to get caller's security context on: %m");
+        r = get_calling_context(bus, message, error, &scon);
+        if (r < 0)
                 goto finish;
-        }
 
         if (path) {
-                tclass = "service";
-                /* get the file context of the unit file */
+                /* Get the file context of the unit file */
+
                 r = getfilecon(path, &fcon);
                 if (r < 0) {
-                        dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
-                        r = -errno;
-                        log_error("Failed to get security context on %s: %m",path);
+                        r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
                         goto finish;
                 }
 
+                tclass = "service";
         } else {
-                tclass = "system";
                 r = getcon(&fcon);
                 if (r < 0) {
-                        dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
-                        r = -errno;
-                        log_error("Failed to get current process context on: %m");
+                        r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context.");
                         goto finish;
                 }
+
+                tclass = "system";
         }
 
-        (void) get_audit_data(connection, message, &audit, error);
+        get_audit_data(bus, message, &audit);
 
         errno = 0;
         r = selinux_check_access(scon, fcon, tclass, permission, &audit);
-        if (r < 0) {
-                dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
-                r = -errno;
-                log_error("SELinux policy denies access.");
-        }
+        if (r < 0)
+                r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
 
         log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, audit.cmdline, r);
 
@@ -414,7 +381,7 @@ finish:
         freecon(fcon);
 
         if (r && security_getenforce() != 1) {
-                dbus_error_init(error);
+                sd_bus_error_free(error);
                 r = 0;
         }
 
@@ -424,11 +391,11 @@ finish:
 #else
 
 int selinux_access_check(
-                DBusConnection *connection,
-                DBusMessage *message,
+                sd_bus *bus,
+                sd_bus_message *message,
                 const char *path,
                 const char *permission,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         return 0;
 }
index 2d7ac64c8f112f0e1a4af21ba79af306607d9729..0926a5eb099265cd290f92d55f33091cd12d6566 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <dbus.h>
+#include "sd-bus.h"
+#include "bus-error.h"
+#include "bus-util.h"
 
 void selinux_access_free(void);
 
-int selinux_access_check(DBusConnection *connection, DBusMessage *message, const char *path, const char *permission, DBusError *error);
+int selinux_access_check(sd_bus *bus, sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error);
 
 #ifdef HAVE_SELINUX
 
-#define SELINUX_ACCESS_CHECK(connection, message, permission) \
+#define SELINUX_ACCESS_CHECK(bus, message, permission)                  \
         do {                                                            \
-                DBusError _error;                                       \
+                _cleanup_bus_error_free_ sd_bus_error _error = SD_BUS_ERROR_NULL; \
+                sd_bus_message *_m = (message);                         \
+                sd_bus *_b = (bus);                                     \
                 int _r;                                                 \
-                DBusConnection *_c = (connection);                      \
-                DBusMessage *_m = (message);                            \
-                dbus_error_init(&_error);                               \
-                _r = selinux_access_check(_c, _m, NULL, (permission), &_error); \
+                _r = selinux_access_check(_b, _m, NULL, (permission), &_error); \
                 if (_r < 0)                                             \
-                        return bus_send_error_reply(_c, _m, &_error, _r); \
+                        return sd_bus_reply_method_errno(_b, _m, _r, &_error); \
         } while (false)
 
-#define SELINUX_UNIT_ACCESS_CHECK(unit, connection, message, permission) \
+#define SELINUX_UNIT_ACCESS_CHECK(unit, bus, message, permission)       \
         do {                                                            \
-                DBusError _error;                                       \
-                int _r;                                                 \
-                DBusConnection *_c = (connection);                      \
-                DBusMessage *_m = (message);                            \
+                _cleanup_bus_error_free_ sd_bus_error _error = SD_BUS_ERROR_NULL; \
+                sd_bus_message *_m = (message);                         \
+                sd_bus *_b = (bus);                                     \
                 Unit *_u = (unit);                                      \
-                dbus_error_init(&_error);                               \
-                _r = selinux_access_check(_c, _m, _u->source_path ?: _u->fragment_path, (permission), &_error); \
+                int _r;                                                 \
+                _r = selinux_access_check(_b, _m, _u->source_path ?: _u->fragment_path, (permission), &_error); \
                 if (_r < 0)                                             \
-                        return bus_send_error_reply(_c, _m, &_error, _r); \
+                        return sd_bus_reply_method_errno(_b, _m, _r, &_error); \
         } while (false)
 
 #else
 
-#define SELINUX_ACCESS_CHECK(connection, message, permission) do { } while (false)
-#define SELINUX_UNIT_ACCESS_CHECK(unit, connection, message, permission) do { } while (false)
+#define SELINUX_ACCESS_CHECK(bus, message, permission) do { } while (false)
+#define SELINUX_UNIT_ACCESS_CHECK(unit, bus, message, permission) do { } while (false)
 
 #endif
index c0ee1140a8aeddfdfd8b685c0ac4f5376010894a..d9e525e48545c4a7b35f6a15cc65d10e194b5c1b 100644 (file)
@@ -36,7 +36,6 @@
 #include "unit-printf.h"
 #include "dbus-service.h"
 #include "special.h"
-#include "dbus-common.h"
 #include "exit-status.h"
 #include "def.h"
 #include "path-util.h"
@@ -44,6 +43,8 @@
 #include "utf8.h"
 #include "env-util.h"
 #include "fileio.h"
+#include "bus-error.h"
+#include "bus-util.h"
 
 #ifdef HAVE_SYSV_COMPAT
 
@@ -118,6 +119,10 @@ static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] =
         [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING
 };
 
+static int service_dispatch_io(sd_event_source *source, int fd, uint32_t events, void *userdata);
+static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata);
+
 static void service_init(Unit *u) {
         Service *s = SERVICE(u);
 
@@ -129,9 +134,6 @@ static void service_init(Unit *u) {
         s->restart_usec = u->manager->default_restart_usec;
         s->type = _SERVICE_TYPE_INVALID;
 
-        watch_init(&s->watchdog_watch);
-        watch_init(&s->timer_watch);
-
 #ifdef HAVE_SYSV_COMPAT
         s->sysv_start_priority = -1;
         s->sysv_start_priority_from_rcnd = -1;
@@ -176,7 +178,7 @@ static void service_unwatch_pid_file(Service *s) {
 
         log_debug_unit(UNIT(s)->id, "Stopping watch for %s's PID file %s",
                        UNIT(s)->id, s->pid_file_pathspec->path);
-        path_spec_unwatch(s->pid_file_pathspec, UNIT(s));
+        path_spec_unwatch(s->pid_file_pathspec);
         path_spec_done(s->pid_file_pathspec);
         free(s->pid_file_pathspec);
         s->pid_file_pathspec = NULL;
@@ -239,15 +241,14 @@ static void service_connection_unref(Service *s) {
 static void service_stop_watchdog(Service *s) {
         assert(s);
 
-        unit_unwatch_timer(UNIT(s), &s->watchdog_watch);
-        s->watchdog_timestamp.realtime = 0;
-        s->watchdog_timestamp.monotonic = 0;
+        s->watchdog_event_source = sd_event_source_unref(s->watchdog_event_source);
+        s->watchdog_timestamp = (struct dual_timestamp) { 0, 0 };
 }
 
 static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
 
 static void service_handle_watchdog(Service *s) {
-        usec_t offset;
+        usec_t nw;
         int r;
 
         assert(s);
@@ -255,14 +256,24 @@ static void service_handle_watchdog(Service *s) {
         if (s->watchdog_usec == 0)
                 return;
 
-        offset = now(CLOCK_MONOTONIC) - s->watchdog_timestamp.monotonic;
-        if (offset >= s->watchdog_usec) {
+        nw = now(CLOCK_MONOTONIC);
+        if (nw >=  s->watchdog_timestamp.monotonic + s->watchdog_usec) {
                 log_error_unit(UNIT(s)->id, "%s watchdog timeout!", UNIT(s)->id);
                 service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_WATCHDOG);
                 return;
         }
 
-        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->watchdog_usec - offset, &s->watchdog_watch);
+        if (s->watchdog_event_source) {
+                r = sd_event_source_set_time(s->watchdog_event_source, s->watchdog_timestamp.monotonic + s->watchdog_usec);
+                if (r < 0) {
+                        log_warning_unit(UNIT(s)->id, "%s failed to reset watchdog timer: %s", UNIT(s)->id, strerror(-r));
+                        return;
+                }
+
+                r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ON);
+        } else
+                r = sd_event_add_monotonic(UNIT(s)->manager->event, s->watchdog_timestamp.monotonic + s->watchdog_usec, 0, service_dispatch_watchdog, s, &s->watchdog_event_source);
+
         if (r < 0)
                 log_warning_unit(UNIT(s)->id,
                                  "%s failed to install watchdog timer: %s",
@@ -327,7 +338,28 @@ static void service_done(Unit *u) {
 
         service_stop_watchdog(s);
 
-        unit_unwatch_timer(u, &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+}
+
+static int service_arm_timer(Service *s, usec_t usec) {
+        int r;
+
+        assert(s);
+
+        if (usec <= 0) {
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+                return 0;
+        }
+
+        if (s->timer_event_source) {
+                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + usec, 0, service_dispatch_timer, s, &s->timer_event_source);
 }
 
 #ifdef HAVE_SYSV_COMPAT
@@ -1214,9 +1246,11 @@ static int service_load(Unit *u) {
                         return r;
 #endif
 
-                if (s->bus_name)
-                        if ((r = unit_watch_bus_name(u, s->bus_name)) < 0)
+                if (s->bus_name) {
+                        r = unit_watch_bus_name(u, s->bus_name);
+                        if (r < 0)
                                 return r;
+                }
 
                 if (s->type == SERVICE_NOTIFY && s->notify_access == NOTIFY_NONE)
                         s->notify_access = NOTIFY_MAIN;
@@ -1467,7 +1501,7 @@ static void service_set_state(Service *s, ServiceState state) {
             state != SERVICE_FINAL_SIGTERM &&
             state != SERVICE_FINAL_SIGKILL &&
             state != SERVICE_AUTO_RESTART)
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         if (state != SERVICE_START &&
             state != SERVICE_START_POST &&
@@ -1567,11 +1601,12 @@ static int service_coldplug(Unit *u) {
                     s->deserialized_state == SERVICE_AUTO_RESTART) {
 
                         if (s->deserialized_state == SERVICE_AUTO_RESTART || s->timeout_start_usec > 0) {
-                                usec_t k;
 
-                                k = s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec : s->timeout_start_usec;
-
-                                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, k, &s->timer_watch);
+                                r = service_arm_timer(s,
+                                                      s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec :
+                                                      s->deserialized_state == SERVICE_START_PRE || s->deserialized_state == SERVICE_START ||
+                                                      s->deserialized_state == SERVICE_START_POST || s->deserialized_state == SERVICE_RELOAD ? s->timeout_start_usec :
+                                                      s->timeout_stop_usec);
                                 if (r < 0)
                                         return r;
                         }
@@ -1728,13 +1763,9 @@ static int service_spawn(
                 }
         }
 
-        if (timeout && s->timeout_start_usec) {
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true,
-                                     s->timeout_start_usec, &s->timer_watch);
-                if (r < 0)
-                        goto fail;
-        } else
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+        r = service_arm_timer(s, timeout ? s->timeout_start_usec : 0);
+        if (r < 0)
+                goto fail;
 
         r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
         if (r < 0)
@@ -1810,7 +1841,7 @@ static int service_spawn(
 
 fail:
         if (timeout)
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         return r;
 }
@@ -1881,10 +1912,9 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
             (s->result != SERVICE_FAILURE_EXIT_CODE ||
              !set_contains(s->restart_ignore_status.code, INT_TO_PTR(s->main_exec_status.status))) &&
             (s->result != SERVICE_FAILURE_SIGNAL ||
-             !set_contains(s->restart_ignore_status.signal, INT_TO_PTR(s->main_exec_status.status)))
-                ) {
+             !set_contains(s->restart_ignore_status.signal, INT_TO_PTR(s->main_exec_status.status)))) {
 
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->restart_usec, &s->timer_watch);
+                r = service_arm_timer(s, s->restart_usec);
                 if (r < 0)
                         goto fail;
 
@@ -1971,8 +2001,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
 
         if (r > 0) {
                 if (s->timeout_stop_usec > 0) {
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true,
-                                             s->timeout_stop_usec, &s->timer_watch);
+                        r = service_arm_timer(s, s->timeout_stop_usec);
                         if (r < 0)
                                 goto fail;
                 }
@@ -2225,18 +2254,17 @@ fail:
 }
 
 static void service_enter_restart(Service *s) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
-        DBusError error;
 
         assert(s);
-        dbus_error_init(&error);
 
         if (UNIT(s)->job && UNIT(s)->job->type == JOB_STOP) {
                 /* Don't restart things if we are going down anyway */
                 log_info_unit(UNIT(s)->id,
                               "Stop job pending for unit, delaying automatic restart.");
 
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->restart_usec, &s->timer_watch);
+                r = service_arm_timer(s, s->restart_usec);
                 if (r < 0)
                         goto fail;
 
@@ -2262,10 +2290,8 @@ static void service_enter_restart(Service *s) {
 fail:
         log_warning_unit(UNIT(s)->id,
                          "%s failed to schedule restart job: %s",
-                         UNIT(s)->id, bus_error(&error, -r));
+                         UNIT(s)->id, bus_error_message(&error, -r));
         service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
-
-        dbus_error_free(&error);
 }
 
 static void service_enter_reload(Service *s) {
@@ -2402,22 +2428,18 @@ static int service_start_limit_test(Service *s) {
                 break;
 
         case SERVICE_START_LIMIT_REBOOT: {
-                DBusError error;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 int r;
 
-                dbus_error_init(&error);
-
                 log_warning_unit(UNIT(s)->id,
                                  "%s start request repeated too quickly, rebooting.", UNIT(s)->id);
 
                 r = manager_add_job_by_name(UNIT(s)->manager, JOB_START,
                                             SPECIAL_REBOOT_TARGET, JOB_REPLACE,
                                             true, &error, NULL);
-                if (r < 0) {
+                if (r < 0)
                         log_error_unit(UNIT(s)->id,
-                                       "Failed to reboot: %s.", bus_error(&error, r));
-                        dbus_error_free(&error);
-                }
+                                       "Failed to reboot: %s.", bus_error_message(&error, r));
 
                 break;
         }
@@ -2837,7 +2859,7 @@ static int service_watch_pid_file(Service *s) {
         log_debug_unit(UNIT(s)->id,
                        "Setting watch for %s's PID file %s",
                        UNIT(s)->id, s->pid_file_pathspec->path);
-        r = path_spec_watch(s->pid_file_pathspec, UNIT(s));
+        r = path_spec_watch(s->pid_file_pathspec, service_dispatch_io);
         if (r < 0)
                 goto fail;
 
@@ -2866,6 +2888,7 @@ static int service_demand_pid_file(Service *s) {
         if (!ps)
                 return -ENOMEM;
 
+        ps->unit = UNIT(s);
         ps->path = strdup(s->pid_file);
         if (!ps->path) {
                 free(ps);
@@ -2884,8 +2907,8 @@ static int service_demand_pid_file(Service *s) {
         return service_watch_pid_file(s);
 }
 
-static void service_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
-        Service *s = SERVICE(u);
+static int service_dispatch_io(sd_event_source *source, int fd, uint32_t events, void *userdata) {
+        Service *s = SERVICE(userdata);
 
         assert(s);
         assert(fd >= 0);
@@ -2893,21 +2916,23 @@ static void service_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
         assert(s->pid_file_pathspec);
         assert(path_spec_owns_inotify_fd(s->pid_file_pathspec, fd));
 
-        log_debug_unit(u->id, "inotify event for %s", u->id);
+        log_debug_unit(UNIT(s)->id, "inotify event for %s", UNIT(s)->id);
 
         if (path_spec_fd_event(s->pid_file_pathspec, events) < 0)
                 goto fail;
 
         if (service_retry_pid_file(s) == 0)
-                return;
+                return 0;
 
         if (service_watch_pid_file(s) < 0)
                 goto fail;
 
-        return;
+        return 0;
+
 fail:
         service_unwatch_pid_file(s);
         service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
+        return 0;
 }
 
 static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
@@ -3180,55 +3205,48 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         unit_add_to_dbus_queue(u);
 }
 
-static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
-        Service *s = SERVICE(u);
+static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Service *s = SERVICE(userdata);
 
         assert(s);
-        assert(elapsed == 1);
-
-        if (w == &s->watchdog_watch) {
-                service_handle_watchdog(s);
-                return;
-        }
-
-        assert(w == &s->timer_watch);
+        assert(source == s->timer_event_source);
 
         switch (s->state) {
 
         case SERVICE_START_PRE:
         case SERVICE_START:
-                log_warning_unit(u->id,
-                                 "%s operation timed out. Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s operation timed out. Terminating.", UNIT(s)->id);
                 service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_START_POST:
-                log_warning_unit(u->id,
-                                 "%s operation timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s operation timed out. Stopping.", UNIT(s)->id);
                 service_enter_stop(s, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_RELOAD:
-                log_warning_unit(u->id,
-                                 "%s operation timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s operation timed out. Stopping.", UNIT(s)->id);
                 s->reload_result = SERVICE_FAILURE_TIMEOUT;
                 service_enter_running(s, SERVICE_SUCCESS);
                 break;
 
         case SERVICE_STOP:
-                log_warning_unit(u->id,
-                                 "%s stopping timed out. Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s stopping timed out. Terminating.", UNIT(s)->id);
                 service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_STOP_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out. Killing.", UNIT(s)->id);
                         service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out. Skipping SIGKILL.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
                         service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
                 }
 
@@ -3239,46 +3257,58 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
                  * Must be something we cannot kill, so let's just be
                  * weirded out and continue */
 
-                log_warning_unit(u->id,
-                                 "%s still around after SIGKILL. Ignoring.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
                 service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_STOP_POST:
-                log_warning_unit(u->id,
-                                 "%s stopping timed out (2). Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s stopping timed out (2). Terminating.", UNIT(s)->id);
                 service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
                 break;
 
         case SERVICE_FINAL_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out (2). Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out (2). Killing.", UNIT(s)->id);
                         service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(s)->id,
                                          "%s stopping timed out (2). Skipping SIGKILL. Entering failed mode.",
-                                         u->id);
+                                         UNIT(s)->id);
                         service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false);
                 }
 
                 break;
 
         case SERVICE_FINAL_SIGKILL:
-                log_warning_unit(u->id,
-                                 "%s still around after SIGKILL (2). Entering failed mode.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s still around after SIGKILL (2). Entering failed mode.", UNIT(s)->id);
                 service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, true);
                 break;
 
         case SERVICE_AUTO_RESTART:
-                log_info_unit(u->id,
-                              "%s holdoff time over, scheduling restart.", u->id);
+                log_info_unit(UNIT(s)->id,
+                              "%s holdoff time over, scheduling restart.", UNIT(s)->id);
                 service_enter_restart(s);
                 break;
 
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
+}
+
+static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata) {
+        Service *s = SERVICE(userdata);
+
+        assert(s);
+        assert(source == s->watchdog_event_source);
+
+        service_handle_watchdog(s);
+        return 0;
 }
 
 static void service_notify_cgroup_empty_event(Unit *u) {
@@ -3606,6 +3636,7 @@ static void service_bus_name_owner_change(
                 const char *new_owner) {
 
         Service *s = SERVICE(u);
+        int r;
 
         assert(s);
         assert(name);
@@ -3644,35 +3675,17 @@ static void service_bus_name_owner_change(
                     s->state == SERVICE_RUNNING ||
                     s->state == SERVICE_RELOAD)) {
 
-                /* Try to acquire PID from bus service */
-                log_debug_unit(u->id,
-                               "Trying to acquire PID from D-Bus name...");
-
-                bus_query_pid(u->manager, name);
-        }
-}
-
-static void service_bus_query_pid_done(
-                Unit *u,
-                const char *name,
-                pid_t pid) {
-
-        Service *s = SERVICE(u);
+                pid_t pid;
 
-        assert(s);
-        assert(name);
+                /* Try to acquire PID from bus service */
 
-        log_debug_unit(u->id,
-                       "%s's D-Bus name %s is now owned by process %u",
-                       u->id, name, (unsigned) pid);
+                r = sd_bus_get_owner_pid(u->manager->api_bus, name, &pid);
+                if (r >= 0) {
+                        log_debug_unit(u->id, "%s's D-Bus name %s is now owned by process %u", u->id, name, (unsigned) pid);
 
-        if (s->main_pid <= 0 &&
-            (s->state == SERVICE_START ||
-             s->state == SERVICE_START_POST ||
-             s->state == SERVICE_RUNNING ||
-             s->state == SERVICE_RELOAD)){
-                service_set_main_pid(s, pid);
-                unit_watch_pid(UNIT(s), pid);
+                        service_set_main_pid(s, pid);
+                        unit_watch_pid(UNIT(s), pid);
+                }
         }
 }
 
@@ -3716,7 +3729,7 @@ static void service_reset_failed(Unit *u) {
         RATELIMIT_RESET(s->start_limit);
 }
 
-static int service_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         Service *s = SERVICE(u);
 
         return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error);
@@ -3806,15 +3819,15 @@ DEFINE_STRING_TABLE_LOOKUP(start_limit_action, StartLimitAction);
 
 const UnitVTable service_vtable = {
         .object_size = sizeof(Service),
+        .exec_context_offset = offsetof(Service, exec_context),
+        .cgroup_context_offset = offsetof(Service, cgroup_context),
+        .kill_context_offset = offsetof(Service, kill_context),
 
         .sections =
                 "Unit\0"
                 "Service\0"
                 "Install\0",
-
         .private_section = "Service",
-        .exec_context_offset = offsetof(Service, exec_context),
-        .cgroup_context_offset = offsetof(Service, cgroup_context),
 
         .init = service_init,
         .done = service_done,
@@ -3842,8 +3855,6 @@ const UnitVTable service_vtable = {
         .check_snapshot = service_check_snapshot,
 
         .sigchld_event = service_sigchld_event,
-        .timer_event = service_timer_event,
-        .fd_event = service_fd_event,
 
         .reset_failed = service_reset_failed,
 
@@ -3851,19 +3862,19 @@ const UnitVTable service_vtable = {
         .notify_message = service_notify_message,
 
         .bus_name_owner_change = service_bus_name_owner_change,
-        .bus_query_pid_done = service_bus_query_pid_done,
 
         .bus_interface = "org.freedesktop.systemd1.Service",
-        .bus_message_handler = bus_service_message_handler,
-        .bus_invalidating_properties =  bus_service_invalidating_properties,
+        .bus_vtable = bus_service_vtable,
+        .bus_changing_properties = bus_service_changing_properties,
         .bus_set_property = bus_service_set_property,
         .bus_commit_properties = bus_service_commit_properties,
 
-        .can_transient = true,
-
 #ifdef HAVE_SYSV_COMPAT
         .enumerate = service_enumerate,
 #endif
+
+        .can_transient = true,
+
         .status_message_formats = {
                 .starting_stopping = {
                         [0] = "Starting %s...",
index 37fa6ff0fab6f09712e71ee5d27c4b6b8c506dce..5c53791753d73bfa28c4969b96ef3ebce554bf33 100644 (file)
@@ -130,7 +130,7 @@ struct Service {
 
         dual_timestamp watchdog_timestamp;
         usec_t watchdog_usec;
-        Watch watchdog_watch;
+        sd_event_source *watchdog_event_source;
 
         ExecCommand* exec_command[_SERVICE_EXEC_COMMAND_MAX];
 
@@ -191,7 +191,7 @@ struct Service {
 
         UnitRef accept_socket;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
         PathSpec *pid_file_pathspec;
 
         NotifyAccess notify_access;
index 40d416e35ee53e44088b52b4e6ce2db7e71e0004..1e42df2b8be7a652d9e66f037e7f904d2fb703ed 100644 (file)
@@ -216,7 +216,7 @@ static int slice_stop(Unit *u) {
         return 0;
 }
 
-static int slice_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, -1, error);
 }
 
@@ -275,13 +275,13 @@ DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState);
 
 const UnitVTable slice_vtable = {
         .object_size = sizeof(Slice),
+        .cgroup_context_offset = offsetof(Slice, cgroup_context),
+
         .sections =
                 "Unit\0"
                 "Slice\0"
                 "Install\0",
-
         .private_section = "Slice",
-        .cgroup_context_offset = offsetof(Slice, cgroup_context),
 
         .no_alias = true,
         .no_instances = true,
@@ -306,7 +306,7 @@ const UnitVTable slice_vtable = {
         .sub_state_to_string = slice_sub_state_to_string,
 
         .bus_interface = "org.freedesktop.systemd1.Slice",
-        .bus_message_handler = bus_slice_message_handler,
+        .bus_vtable = bus_slice_vtable,
         .bus_set_property = bus_slice_set_property,
         .bus_commit_properties = bus_slice_commit_properties,
 
index d11239dff395995b1234ba90af75bda815b584b0..21e89ac9964a7f07ed7caee2c962b3563909f928 100644 (file)
@@ -189,7 +189,7 @@ _pure_ static const char *snapshot_sub_state_to_string(Unit *u) {
         return snapshot_state_to_string(SNAPSHOT(u)->state);
 }
 
-int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Snapshot **_s) {
+int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **_s) {
         _cleanup_free_ char *n = NULL;
         Unit *other, *u = NULL;
         Iterator i;
@@ -200,20 +200,14 @@ int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Sn
         assert(_s);
 
         if (name) {
-                if (!unit_name_is_valid(name, false)) {
-                        dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
-                        return -EINVAL;
-                }
+                if (!unit_name_is_valid(name, false))
+                        return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
 
-                if (unit_name_to_type(name) != UNIT_SNAPSHOT) {
-                        dbus_set_error(e, BUS_ERROR_UNIT_TYPE_MISMATCH, "Unit name %s lacks snapshot suffix.", name);
-                        return -EINVAL;
-                }
+                if (unit_name_to_type(name) != UNIT_SNAPSHOT)
+                        return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s lacks snapshot suffix.", name);
 
-                if (manager_get_unit(m, name)) {
-                        dbus_set_error(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
-                        return -EEXIST;
-                }
+                if (manager_get_unit(m, name))
+                        sd_bus_error_setf(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
 
         } else {
 
@@ -293,8 +287,8 @@ const UnitVTable snapshot_vtable = {
         .no_gc = true,
 
         .init = snapshot_init,
-
         .load = snapshot_load,
+
         .coldplug = snapshot_coldplug,
 
         .dump = snapshot_dump,
@@ -309,5 +303,5 @@ const UnitVTable snapshot_vtable = {
         .sub_state_to_string = snapshot_sub_state_to_string,
 
         .bus_interface = "org.freedesktop.systemd1.Snapshot",
-        .bus_message_handler = bus_snapshot_message_handler
+        .bus_vtable = bus_snapshot_vtable
 };
index 2675b1b2429371c570ace4b669faecf78ce5e62b..e6dc661060664d859bdf22683b4d82ffbfc3ab0a 100644 (file)
@@ -42,7 +42,7 @@ struct Snapshot {
 
 extern const UnitVTable snapshot_vtable;
 
-int snapshot_create(Manager *m, const char *name, bool cleanup, DBusError *e, Snapshot **s);
+int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **s);
 void snapshot_remove(Snapshot *s);
 
 const char* snapshot_state_to_string(SnapshotState i) _const_;
index 751f20bdcac73684095099aa8266081168b49d15..eae9465788058b5b726b530386dc9bfc4a6f4c53 100644 (file)
 #include <sys/epoll.h>
 #include <signal.h>
 #include <arpa/inet.h>
+#include <netinet/tcp.h>
 #include <mqueue.h>
 #ifdef HAVE_XATTR
 #include <attr/xattr.h>
 #endif
 
+#include "sd-event.h"
 #include "unit.h"
 #include "socket.h"
-#include "netinet/tcp.h"
 #include "log.h"
 #include "load-dropin.h"
 #include "load-fragment.h"
 #include "dbus-socket.h"
 #include "missing.h"
 #include "special.h"
-#include "dbus-common.h"
 #include "label.h"
 #include "exit-status.h"
 #include "def.h"
 #include "smack-util.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_DEAD] = UNIT_INACTIVE,
@@ -67,6 +69,9 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
         [SOCKET_FAILED] = UNIT_FAILED
 };
 
+static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+
 static void socket_init(Unit *u) {
         Socket *s = SOCKET(u);
 
@@ -112,10 +117,10 @@ void socket_free_ports(Socket *s) {
         while ((p = s->ports)) {
                 LIST_REMOVE(port, s->ports, p);
 
-                if (p->fd >= 0) {
-                        unit_unwatch_fd(UNIT(s), &p->fd_watch);
+                sd_event_source_unref(p->event_source);
+
+                if (p->fd >= 0)
                         close_nointr_nofail(p->fd);
-                }
 
                 free(p->path);
                 free(p);
@@ -149,7 +154,28 @@ static void socket_done(Unit *u) {
         free(s->smack_ip_in);
         free(s->smack_ip_out);
 
-        unit_unwatch_timer(u, &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+}
+
+static int socket_arm_timer(Socket *s) {
+        int r;
+
+        assert(s);
+
+        if (s->timeout_usec <= 0) {
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+                return 0;
+        }
+
+        if (s->timer_event_source) {
+                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, socket_dispatch_timer, s, &s->timer_event_source);
 }
 
 static int socket_instantiate_service(Socket *s) {
@@ -508,10 +534,10 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                         "%sMessageQueueMessageSize: %li\n",
                         prefix, s->mq_msgsize);
 
-        if (s->reuseport)
+        if (s->reuse_port)
                 fprintf(f,
                         "%sReusePort: %s\n",
-                         prefix, yes_no(s->reuseport));
+                         prefix, yes_no(s->reuse_port));
 
         if (s->smack)
                 fprintf(f,
@@ -673,10 +699,12 @@ static void socket_close_fds(Socket *s) {
         assert(s);
 
         LIST_FOREACH(port, p, s->ports) {
+
+                p->event_source = sd_event_source_unref(p->event_source);
+
                 if (p->fd < 0)
                         continue;
 
-                unit_unwatch_fd(UNIT(s), &p->fd_watch);
                 close_nointr_nofail(p->fd);
 
                 /* One little note: we should never delete any sockets
@@ -769,8 +797,8 @@ static void socket_apply_socket_options(Socket *s, int fd) {
                 if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0)
                         log_warning_unit(UNIT(s)->id, "TCP_CONGESTION failed: %m");
 
-        if (s->reuseport) {
-                int b = s->reuseport;
+        if (s->reuse_port) {
+                int b = s->reuse_port;
                 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &b, sizeof(b)) < 0)
                         log_warning_unit(UNIT(s)->id, "SO_REUSEPORT failed: %m");
         }
@@ -1054,6 +1082,7 @@ rollback:
 
 static void socket_unwatch_fds(Socket *s) {
         SocketPort *p;
+        int r;
 
         assert(s);
 
@@ -1061,7 +1090,11 @@ static void socket_unwatch_fds(Socket *s) {
                 if (p->fd < 0)
                         continue;
 
-                unit_unwatch_fd(UNIT(s), &p->fd_watch);
+                if (p->event_source) {
+                        r = sd_event_source_set_enabled(p->event_source, SD_EVENT_OFF);
+                        if (r < 0)
+                                log_debug_unit(UNIT(s)->id, "Failed to disable event source.");
+                }
         }
 }
 
@@ -1075,13 +1108,15 @@ static int socket_watch_fds(Socket *s) {
                 if (p->fd < 0)
                         continue;
 
-                p->fd_watch.socket_accept =
-                        s->accept &&
-                        p->type == SOCKET_SOCKET &&
-                        socket_address_can_accept(&p->address);
+                if (p->event_source)
+                        r = sd_event_source_set_enabled(p->event_source, SD_EVENT_ON);
+                else
+                        r = sd_event_add_io(UNIT(s)->manager->event, p->fd, EPOLLIN, socket_dispatch_io, p, &p->event_source);
 
-                if ((r = unit_watch_fd(UNIT(s), p->fd, EPOLLIN, &p->fd_watch)) < 0)
+                if (r < 0) {
+                        log_warning_unit(UNIT(s)->id, "Failed to watch listening fds: %s", strerror(-r));
                         goto fail;
+                }
         }
 
         return 0;
@@ -1106,7 +1141,8 @@ static void socket_set_state(Socket *s, SocketState state) {
             state != SOCKET_STOP_POST &&
             state != SOCKET_FINAL_SIGTERM &&
             state != SOCKET_FINAL_SIGKILL) {
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
                 socket_unwatch_control_pid(s);
                 s->control_command = NULL;
                 s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
@@ -1157,7 +1193,7 @@ static int socket_coldplug(Unit *u) {
                         if (r < 0)
                                 return r;
 
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+                        r = socket_arm_timer(s);
                         if (r < 0)
                                 return r;
                 }
@@ -1167,13 +1203,17 @@ static int socket_coldplug(Unit *u) {
                     s->deserialized_state == SOCKET_RUNNING ||
                     s->deserialized_state == SOCKET_STOP_PRE ||
                     s->deserialized_state == SOCKET_STOP_PRE_SIGTERM ||
-                    s->deserialized_state == SOCKET_STOP_PRE_SIGKILL)
-                        if ((r = socket_open_fds(s)) < 0)
+                    s->deserialized_state == SOCKET_STOP_PRE_SIGKILL) {
+                        r = socket_open_fds(s);
+                        if (r < 0)
                                 return r;
+                }
 
-                if (s->deserialized_state == SOCKET_LISTENING)
-                        if ((r = socket_watch_fds(s)) < 0)
+                if (s->deserialized_state == SOCKET_LISTENING) {
+                        r = socket_watch_fds(s);
+                        if (r < 0)
                                 return r;
+                }
 
                 socket_set_state(s, s->deserialized_state);
         }
@@ -1192,7 +1232,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
 
         unit_realize_cgroup(UNIT(s));
 
-        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+        r = socket_arm_timer(s);
         if (r < 0)
                 goto fail;
 
@@ -1219,7 +1259,8 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
         if (r < 0)
                 goto fail;
 
-        if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
+        r = unit_watch_pid(UNIT(s), pid);
+        if (r < 0)
                 /* FIXME: we need to do something here */
                 goto fail;
 
@@ -1228,7 +1269,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
         return 0;
 
 fail:
-        unit_unwatch_timer(UNIT(s), &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         return r;
 }
@@ -1292,7 +1333,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
                 goto fail;
 
         if (r > 0) {
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+                r = socket_arm_timer(s);
                 if (r < 0)
                         goto fail;
 
@@ -1423,11 +1464,10 @@ fail:
 }
 
 static void socket_enter_running(Socket *s, int cfd) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
-        DBusError error;
 
         assert(s);
-        dbus_error_init(&error);
 
         /* We don't take connections anymore if we are supposed to
          * shut down anyway */
@@ -1548,13 +1588,11 @@ fail:
                          "%s failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s",
                          UNIT(s)->id,
                          cfd >= 0 ? "template" : "non-template",
-                         bus_error(&error, r));
+                         bus_error_message(&error, r));
         socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
 
         if (cfd >= 0)
                 close_nointr_nofail(cfd);
-
-        dbus_error_free(&error);
 }
 
 static void socket_run_next(Socket *s) {
@@ -1952,20 +1990,39 @@ const char* socket_port_type_to_string(SocketPort *p) {
         assert(p);
 
         switch (p->type) {
-                case SOCKET_SOCKET:
-                        switch (p->address.type) {
-                                case SOCK_STREAM: return "Stream";
-                                case SOCK_DGRAM: return "Datagram";
-                                case SOCK_SEQPACKET: return "SequentialPacket";
-                                case SOCK_RAW:
-                                        if (socket_address_family(&p->address) == AF_NETLINK)
-                                                return "Netlink";
-                                default: return "Invalid";
-                        }
-                case SOCKET_SPECIAL: return "Special";
-                case SOCKET_MQUEUE: return "MessageQueue";
-                case SOCKET_FIFO: return "FIFO";
-                default: return NULL;
+
+        case SOCKET_SOCKET:
+
+                switch (p->address.type) {
+
+                case SOCK_STREAM:
+                        return "Stream";
+
+                case SOCK_DGRAM:
+                        return "Datagram";
+
+                case SOCK_SEQPACKET:
+                        return "SequentialPacket";
+
+                case SOCK_RAW:
+                        if (socket_address_family(&p->address) == AF_NETLINK)
+                                return "Netlink";
+
+                default:
+                        return NULL;
+                }
+
+        case SOCKET_SPECIAL:
+                return "Special";
+
+        case SOCKET_MQUEUE:
+                return "MessageQueue";
+
+        case SOCKET_FIFO:
+                return "FIFO";
+
+        default:
+                return NULL;
         }
 }
 
@@ -1977,33 +2034,36 @@ _pure_ static bool socket_check_gc(Unit *u) {
         return s->n_connections > 0;
 }
 
-static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
-        Socket *s = SOCKET(u);
+static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        SocketPort *p = userdata;
         int cfd = -1;
 
-        assert(s);
+        assert(p);
         assert(fd >= 0);
 
-        if (s->state != SOCKET_LISTENING)
-                return;
+        if (p->socket->state != SOCKET_LISTENING)
+                return 0;
 
-        log_debug_unit(u->id, "Incoming traffic on %s", u->id);
+        log_debug_unit(UNIT(p->socket)->id, "Incoming traffic on %s", UNIT(p->socket)->id);
 
-        if (events != EPOLLIN) {
+        if (revents != EPOLLIN) {
 
-                if (events & EPOLLHUP)
-                        log_error_unit(u->id,
+                if (revents & EPOLLHUP)
+                        log_error_unit(UNIT(p->socket)->id,
                                        "%s: Got POLLHUP on a listening socket. The service probably invoked shutdown() on it, and should better not do that.",
-                                       u->id);
+                                       UNIT(p->socket)->id);
                 else
-                        log_error_unit(u->id,
+                        log_error_unit(UNIT(p->socket)->id,
                                        "%s: Got unexpected poll event (0x%x) on socket.",
-                                       u->id, events);
+                                       UNIT(p->socket)->id, revents);
 
                 goto fail;
         }
 
-        if (w->socket_accept) {
+        if (p->socket->accept &&
+            p->type == SOCKET_SOCKET &&
+            socket_address_can_accept(&p->address)) {
+
                 for (;;) {
 
                         cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK);
@@ -2012,7 +2072,7 @@ static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                                 if (errno == EINTR)
                                         continue;
 
-                                log_error_unit(u->id,
+                                log_error_unit(UNIT(p->socket)->id,
                                                "Failed to accept socket: %m");
                                 goto fail;
                         }
@@ -2020,14 +2080,15 @@ static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                         break;
                 }
 
-                socket_apply_socket_options(s, cfd);
+                socket_apply_socket_options(p->socket, cfd);
         }
 
-        socket_enter_running(s, cfd);
-        return;
+        socket_enter_running(p->socket, cfd);
+        return 0;
 
 fail:
-        socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
+        socket_enter_stop_pre(p->socket, SOCKET_FAILURE_RESOURCES);
+        return 0;
 }
 
 static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
@@ -2124,81 +2185,82 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         unit_add_to_dbus_queue(u);
 }
 
-static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
-        Socket *s = SOCKET(u);
+static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Socket *s = SOCKET(userdata);
 
         assert(s);
-        assert(elapsed == 1);
-        assert(w == &s->timer_watch);
+        assert(s->timer_event_source == source);
 
         switch (s->state) {
 
         case SOCKET_START_PRE:
-                log_warning_unit(u->id,
-                                 "%s starting timed out. Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s starting timed out. Terminating.", UNIT(s)->id);
                 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_START_POST:
-                log_warning_unit(u->id,
-                                 "%s starting timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s starting timed out. Stopping.", UNIT(s)->id);
                 socket_enter_stop_pre(s, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_STOP_PRE:
-                log_warning_unit(u->id,
-                                 "%s stopping timed out. Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s stopping timed out. Terminating.", UNIT(s)->id);
                 socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_STOP_PRE_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out. Killing.", UNIT(s)->id);
                         socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(s)->id,
                                          "%s stopping timed out. Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(s)->id);
                         socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT);
                 }
                 break;
 
         case SOCKET_STOP_PRE_SIGKILL:
-                log_warning_unit(u->id,
-                                 "%s still around after SIGKILL. Ignoring.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s still around after SIGKILL. Ignoring.", UNIT(s)->id);
                 socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_STOP_POST:
-                log_warning_unit(u->id,
-                                 "%s stopping timed out (2). Terminating.", u->id);
+                log_warning_unit(UNIT(s)->id,
+                                 "%s stopping timed out (2). Terminating.", UNIT(s)->id);
                 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         case SOCKET_FINAL_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id,
-                                         "%s stopping timed out (2). Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id,
+                                         "%s stopping timed out (2). Killing.", UNIT(s)->id);
                         socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id,
+                        log_warning_unit(UNIT(s)->id,
                                          "%s stopping timed out (2). Skipping SIGKILL. Ignoring.",
-                                         u->id);
+                                         UNIT(s)->id);
                         socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT);
                 }
                 break;
 
         case SOCKET_FINAL_SIGKILL:
-                log_warning_unit(u->id,
+                log_warning_unit(UNIT(s)->id,
                                  "%s still around after SIGKILL (2). Entering failed mode.",
-                                 u->id);
+                                 UNIT(s)->id);
                 socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT);
                 break;
 
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
 }
 
 int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
@@ -2319,7 +2381,7 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
                 socket_set_state(s, SOCKET_RUNNING);
 }
 
-static int socket_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int socket_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error);
 }
 
@@ -2363,22 +2425,20 @@ DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
 
 const UnitVTable socket_vtable = {
         .object_size = sizeof(Socket),
+        .exec_context_offset = offsetof(Socket, exec_context),
+        .cgroup_context_offset = offsetof(Socket, cgroup_context),
+        .kill_context_offset = offsetof(Socket, kill_context),
 
         .sections =
                 "Unit\0"
                 "Socket\0"
                 "Install\0",
-
         .private_section = "Socket",
-        .exec_context_offset = offsetof(Socket, exec_context),
-        .cgroup_context_offset = offsetof(Socket, cgroup_context),
 
         .init = socket_init,
         .done = socket_done,
         .load = socket_load,
 
-        .kill = socket_kill,
-
         .coldplug = socket_coldplug,
 
         .dump = socket_dump,
@@ -2386,6 +2446,8 @@ const UnitVTable socket_vtable = {
         .start = socket_start,
         .stop = socket_stop,
 
+        .kill = socket_kill,
+
         .serialize = socket_serialize,
         .deserialize_item = socket_deserialize_item,
         .distribute_fds = socket_distribute_fds,
@@ -2395,17 +2457,15 @@ const UnitVTable socket_vtable = {
 
         .check_gc = socket_check_gc,
 
-        .fd_event = socket_fd_event,
         .sigchld_event = socket_sigchld_event,
-        .timer_event = socket_timer_event,
 
         .trigger_notify = socket_trigger_notify,
 
         .reset_failed = socket_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Socket",
-        .bus_message_handler = bus_socket_message_handler,
-        .bus_invalidating_properties =  bus_socket_invalidating_properties,
+        .bus_vtable = bus_socket_vtable,
+        .bus_changing_properties = bus_socket_changing_properties,
         .bus_set_property = bus_socket_set_property,
         .bus_commit_properties = bus_socket_commit_properties,
 
index 3d7eadc9fe618508975c4d561280c45ee09ebbbe..db0796c4a3c927571c35ddc408b3316a15d692cb 100644 (file)
@@ -77,12 +77,14 @@ typedef enum SocketResult {
 } SocketResult;
 
 typedef struct SocketPort {
+        Socket *socket;
+
         SocketType type;
         int fd;
 
         SocketAddress address;
         char *path;
-        Watch fd_watch;
+        sd_event_source *event_source;
 
         LIST_FIELDS(struct SocketPort, port);
 } SocketPort;
@@ -111,7 +113,7 @@ struct Socket {
 
         SocketState state, deserialized_state;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
 
         ExecCommand* control_command;
         SocketExecCommand control_command_id;
@@ -144,7 +146,7 @@ struct Socket {
         size_t pipe_size;
         char *bind_to_device;
         char *tcp_congestion;
-        bool reuseport;
+        bool reuse_port;
         long mq_maxmsg;
         long mq_msgsize;
 
index c48c0bd5f963551cf72c4072b46fc76fce3d5ccc..a798eca3f1045fa4b61192f87fead1cd1c01e16d 100644 (file)
@@ -53,6 +53,9 @@ static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = {
         [SWAP_FAILED] = UNIT_FAILED
 };
 
+static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
+static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+
 static void swap_unset_proc_swaps(Swap *s) {
         Swap *first;
         Hashmap *swaps;
@@ -96,8 +99,6 @@ static void swap_init(Unit *u) {
 
         s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1;
 
-        s->timer_watch.type = WATCH_INVALID;
-
         s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
 
         UNIT(s)->ignore_on_isolate = true;
@@ -134,7 +135,28 @@ static void swap_done(Unit *u) {
 
         swap_unwatch_control_pid(s);
 
-        unit_unwatch_timer(u, &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+}
+
+static int swap_arm_timer(Swap *s) {
+        int r;
+
+        assert(s);
+
+        if (s->timeout_usec <= 0) {
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+                return 0;
+        }
+
+        if (s->timer_event_source) {
+                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
+                if (r < 0)
+                        return r;
+
+                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
+        }
+
+        return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, swap_dispatch_timer, s, &s->timer_event_source);
 }
 
 static int swap_add_device_links(Swap *s) {
@@ -465,7 +487,7 @@ static void swap_set_state(Swap *s, SwapState state) {
             state != SWAP_DEACTIVATING &&
             state != SWAP_DEACTIVATING_SIGTERM &&
             state != SWAP_DEACTIVATING_SIGKILL) {
-                unit_unwatch_timer(UNIT(s), &s->timer_watch);
+                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
                 swap_unwatch_control_pid(s);
                 s->control_command = NULL;
                 s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
@@ -511,7 +533,7 @@ static int swap_coldplug(Unit *u) {
                         if (r < 0)
                                 return r;
 
-                        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+                        r = swap_arm_timer(s);
                         if (r < 0)
                                 return r;
                 }
@@ -576,7 +598,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
 
         unit_realize_cgroup(UNIT(s));
 
-        r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+        r = swap_arm_timer(s);
         if (r < 0)
                 goto fail;
 
@@ -607,7 +629,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
         return 0;
 
 fail:
-        unit_unwatch_timer(UNIT(s), &s->timer_watch);
+        s->timer_event_source = sd_event_source_unref(s->timer_event_source);
 
         return r;
 }
@@ -650,7 +672,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
                 goto fail;
 
         if (r > 0) {
-                r = unit_watch_timer(UNIT(s), CLOCK_MONOTONIC, true, s->timeout_usec, &s->timer_watch);
+                r = swap_arm_timer(s);
                 if (r < 0)
                         goto fail;
 
@@ -977,54 +999,55 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         u->manager->request_reload = true;
 }
 
-static void swap_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
-        Swap *s = SWAP(u);
+static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
+        Swap *s = SWAP(userdata);
 
         assert(s);
-        assert(elapsed == 1);
-        assert(w == &s->timer_watch);
+        assert(s->timer_event_source == source);
 
         switch (s->state) {
 
         case SWAP_ACTIVATING:
-                log_warning_unit(u->id, "%s activation timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id, "%s activation timed out. Stopping.", UNIT(s)->id);
                 swap_enter_signal(s, SWAP_ACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
                 break;
 
         case SWAP_DEACTIVATING:
-                log_warning_unit(u->id, "%s deactivation timed out. Stopping.", u->id);
+                log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Stopping.", UNIT(s)->id);
                 swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT);
                 break;
 
         case SWAP_ACTIVATING_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id, "%s activation timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s activation timed out. Killing.", UNIT(s)->id);
                         swap_enter_signal(s, SWAP_ACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s activation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
                         swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
                 }
                 break;
 
         case SWAP_DEACTIVATING_SIGTERM:
                 if (s->kill_context.send_sigkill) {
-                        log_warning_unit(u->id, "%s deactivation timed out. Killing.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Killing.", UNIT(s)->id);
                         swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT);
                 } else {
-                        log_warning_unit(u->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", u->id);
+                        log_warning_unit(UNIT(s)->id, "%s deactivation timed out. Skipping SIGKILL. Ignoring.", UNIT(s)->id);
                         swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
                 }
                 break;
 
         case SWAP_ACTIVATING_SIGKILL:
         case SWAP_DEACTIVATING_SIGKILL:
-                log_warning_unit(u->id, "%s swap process still around after SIGKILL. Ignoring.", u->id);
+                log_warning_unit(UNIT(s)->id, "%s swap process still around after SIGKILL. Ignoring.", UNIT(s)->id);
                 swap_enter_dead(s, SWAP_FAILURE_TIMEOUT);
                 break;
 
         default:
                 assert_not_reached("Timeout at wrong time.");
         }
+
+        return 0;
 }
 
 static int swap_load_proc_swaps(Manager *m, bool set_flags) {
@@ -1068,23 +1091,13 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
         return r;
 }
 
-int swap_dispatch_reload(Manager *m) {
-        /* This function should go as soon as the kernel properly notifies us */
-
-        if (_likely_(!m->request_reload))
-                return 0;
-
-        m->request_reload = false;
-
-        return swap_fd_event(m, EPOLLPRI);
-}
-
-int swap_fd_event(Manager *m, int events) {
+static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        Manager *m = userdata;
         Unit *u;
         int r;
 
         assert(m);
-        assert(events & EPOLLPRI);
+        assert(revents & EPOLLPRI);
 
         r = swap_load_proc_swaps(m, true);
         if (r < 0) {
@@ -1212,6 +1225,8 @@ fail:
 static void swap_shutdown(Manager *m) {
         assert(m);
 
+        m->swap_event_source = sd_event_source_unref(m->swap_event_source);
+
         if (m->proc_swaps) {
                 fclose(m->proc_swaps);
                 m->proc_swaps = NULL;
@@ -1226,26 +1241,23 @@ static int swap_enumerate(Manager *m) {
         assert(m);
 
         if (!m->proc_swaps) {
-                struct epoll_event ev = {
-                        .events = EPOLLPRI,
-                        .data.ptr = &m->swap_watch,
-                };
-
                 m->proc_swaps = fopen("/proc/swaps", "re");
                 if (!m->proc_swaps)
-                        return (errno == ENOENT) ? 0 : -errno;
-
-                m->swap_watch.type = WATCH_SWAP;
-                m->swap_watch.fd = fileno(m->proc_swaps);
+                        return errno == ENOENT ? 0 : -errno;
 
-                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->swap_watch.fd, &ev) < 0)
-                        return -errno;
+                r = sd_event_add_io(m->event, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m, &m->swap_event_source);
+                if (r < 0)
+                        goto fail;
         }
 
         r = swap_load_proc_swaps(m, false);
         if (r < 0)
-                swap_shutdown(m);
+                goto fail;
+
+        return 0;
 
+fail:
+        swap_shutdown(m);
         return r;
 }
 
@@ -1260,7 +1272,7 @@ static void swap_reset_failed(Unit *u) {
         s->result = SWAP_SUCCESS;
 }
 
-static int swap_kill(Unit *u, KillWho who, int signo, DBusError *error) {
+static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
 }
 
@@ -1298,15 +1310,15 @@ DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult);
 
 const UnitVTable swap_vtable = {
         .object_size = sizeof(Swap),
+        .exec_context_offset = offsetof(Swap, exec_context),
+        .cgroup_context_offset = offsetof(Swap, cgroup_context),
+        .kill_context_offset = offsetof(Swap, kill_context),
 
         .sections =
                 "Unit\0"
                 "Swap\0"
                 "Install\0",
-
         .private_section = "Swap",
-        .exec_context_offset = offsetof(Swap, exec_context),
-        .cgroup_context_offset = offsetof(Swap, cgroup_context),
 
         .no_alias = true,
         .no_instances = true,
@@ -1333,13 +1345,12 @@ const UnitVTable swap_vtable = {
         .check_gc = swap_check_gc,
 
         .sigchld_event = swap_sigchld_event,
-        .timer_event = swap_timer_event,
 
         .reset_failed = swap_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Swap",
-        .bus_message_handler = bus_swap_message_handler,
-        .bus_invalidating_properties =  bus_swap_invalidating_properties,
+        .bus_vtable = bus_swap_vtable,
+        .bus_changing_properties = bus_swap_changing_properties,
         .bus_set_property = bus_swap_set_property,
         .bus_commit_properties = bus_swap_commit_properties,
 
index dd89535895dd53e5af86cb71a90088e56a0387f0..c51c55f839f620b180864afccac8a6fbb1beee31 100644 (file)
@@ -96,7 +96,7 @@ struct Swap {
         SwapExecCommand control_command_id;
         pid_t control_pid;
 
-        Watch timer_watch;
+        sd_event_source *timer_event_source;
 
         /* In order to be able to distinguish dependencies on
         different device nodes we might end up creating multiple
@@ -107,9 +107,6 @@ struct Swap {
 
 extern const UnitVTable swap_vtable;
 
-int swap_dispatch_reload(Manager *m);
-int swap_fd_event(Manager *m, int events);
-
 const char* swap_state_to_string(SwapState i) _const_;
 SwapState swap_state_from_string(const char *s) _pure_;
 
index 3fffa0d2f5ff0f4dfdb56845568618513dbfc8ce..68be22b38df3acf149afc52ab8f78e7550392fc9 100644 (file)
@@ -205,6 +205,7 @@ DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState);
 
 const UnitVTable target_vtable = {
         .object_size = sizeof(Target),
+
         .sections =
                 "Unit\0"
                 "Target\0"
@@ -225,7 +226,7 @@ const UnitVTable target_vtable = {
         .sub_state_to_string = target_sub_state_to_string,
 
         .bus_interface = "org.freedesktop.systemd1.Target",
-        .bus_message_handler = bus_target_message_handler,
+        .bus_vtable = bus_target_vtable,
 
         .status_message_formats = {
                 .finished_start_job = {
index b90c85f8238a20b771c3441fb607fcb6781d5143..5bc01a26ff796d23ce7e65514c5e3abafa72af5b 100644 (file)
@@ -26,7 +26,8 @@
 #include "timer.h"
 #include "dbus-timer.h"
 #include "special.h"
-#include "dbus-common.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
         [TIMER_DEAD] = UNIT_INACTIVE,
@@ -36,6 +37,8 @@ static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
         [TIMER_FAILED] = UNIT_FAILED
 };
 
+static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
+
 static void timer_init(Unit *u) {
         Timer *t = TIMER(u);
 
@@ -44,8 +47,6 @@ static void timer_init(Unit *u) {
 
         t->next_elapse_monotonic = (usec_t) -1;
         t->next_elapse_realtime = (usec_t) -1;
-        watch_init(&t->monotonic_watch);
-        watch_init(&t->realtime_watch);
 }
 
 void timer_free_values(Timer *t) {
@@ -70,8 +71,8 @@ static void timer_done(Unit *u) {
 
         timer_free_values(t);
 
-        unit_unwatch_timer(u, &t->monotonic_watch);
-        unit_unwatch_timer(u, &t->realtime_watch);
+        t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
+        t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
 }
 
 static int timer_verify(Timer *t) {
@@ -189,8 +190,8 @@ static void timer_set_state(Timer *t, TimerState state) {
         t->state = state;
 
         if (state != TIMER_WAITING) {
-                unit_unwatch_timer(UNIT(t), &t->monotonic_watch);
-                unit_unwatch_timer(UNIT(t), &t->realtime_watch);
+                t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
+                t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
         }
 
         if (state != old_state)
@@ -230,6 +231,7 @@ static void timer_enter_dead(Timer *t, TimerResult f) {
         timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
 }
 
+
 static void timer_enter_waiting(Timer *t, bool initial) {
         TimerValue *v;
         usec_t base = 0;
@@ -337,11 +339,24 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                                UNIT(t)->id,
                                format_timespan(buf, sizeof(buf), t->next_elapse_monotonic > ts.monotonic ? t->next_elapse_monotonic - ts.monotonic : 0, 0));
 
-                r = unit_watch_timer(UNIT(t), CLOCK_MONOTONIC, false, t->next_elapse_monotonic, &t->monotonic_watch);
+                if (t->monotonic_event_source) {
+                        r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic);
+                        if (r < 0)
+                                goto fail;
+
+                        r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
+                } else
+                        r = sd_event_add_monotonic(UNIT(t)->manager->event, t->next_elapse_monotonic, 0, timer_dispatch, t, &t->monotonic_event_source);
+
                 if (r < 0)
                         goto fail;
-        } else
-                unit_unwatch_timer(UNIT(t), &t->monotonic_watch);
+
+        } else if (t->monotonic_event_source) {
+                r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
+
+                if (r < 0)
+                        goto fail;
+        }
 
         if (found_realtime) {
                 char buf[FORMAT_TIMESTAMP_MAX];
@@ -350,11 +365,24 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                                UNIT(t)->id,
                                format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
 
-                r = unit_watch_timer(UNIT(t), CLOCK_REALTIME, false, t->next_elapse_realtime, &t->realtime_watch);
+                if (t->realtime_event_source) {
+                        r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
+                        if (r < 0)
+                                goto fail;
+
+                        r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
+                } else
+                        r = sd_event_add_realtime(UNIT(t)->manager->event, t->next_elapse_realtime, 0, timer_dispatch, t, &t->realtime_event_source);
+
                 if (r < 0)
                         goto fail;
-        } else
-                unit_unwatch_timer(UNIT(t), &t->realtime_watch);
+
+        } else if (t->realtime_event_source) {
+                r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
+
+                if (r < 0)
+                        goto fail;
+        }
 
         timer_set_state(t, TIMER_WAITING);
         return;
@@ -367,11 +395,10 @@ fail:
 }
 
 static void timer_enter_running(Timer *t) {
-        DBusError error;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
 
         assert(t);
-        dbus_error_init(&error);
 
         /* Don't start job if we are supposed to go down */
         if (unit_stop_pending(UNIT(t)))
@@ -390,10 +417,8 @@ static void timer_enter_running(Timer *t) {
 fail:
         log_warning_unit(UNIT(t)->id,
                          "%s failed to queue unit startup job: %s",
-                         UNIT(t)->id, bus_error(&error, r));
+                         UNIT(t)->id, bus_error_message(&error, r));
         timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
-
-        dbus_error_free(&error);
 }
 
 static int timer_start(Unit *u) {
@@ -476,17 +501,17 @@ _pure_ static const char *timer_sub_state_to_string(Unit *u) {
         return timer_state_to_string(TIMER(u)->state);
 }
 
-static void timer_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
-        Timer *t = TIMER(u);
+static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
+        Timer *t = TIMER(userdata);
 
         assert(t);
-        assert(elapsed == 1);
 
         if (t->state != TIMER_WAITING)
-                return;
+                return 0;
 
-        log_debug_unit(u->id, "Timer elapsed on %s", u->id);
+        log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
         timer_enter_running(t);
+        return 0;
 }
 
 static void timer_trigger_notify(Unit *u, Unit *other) {
@@ -587,6 +612,7 @@ DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
 
 const UnitVTable timer_vtable = {
         .object_size = sizeof(Timer),
+
         .sections =
                 "Unit\0"
                 "Timer\0"
@@ -609,14 +635,12 @@ const UnitVTable timer_vtable = {
         .active_state = timer_active_state,
         .sub_state_to_string = timer_sub_state_to_string,
 
-        .timer_event = timer_timer_event,
-
         .trigger_notify = timer_trigger_notify,
 
         .reset_failed = timer_reset_failed,
         .time_change = timer_time_change,
 
         .bus_interface = "org.freedesktop.systemd1.Timer",
-        .bus_message_handler = bus_timer_message_handler,
-        .bus_invalidating_properties =  bus_timer_invalidating_properties
+        .bus_vtable = bus_timer_vtable,
+        .bus_changing_properties = bus_timer_changing_properties,
 };
index 4168553e9d977825f88db063ece5552871cb79aa..b3722f0028f325c2e618e864a4916d6dd1a162ef 100644 (file)
@@ -75,8 +75,8 @@ struct Timer {
 
         TimerState state, deserialized_state;
 
-        Watch monotonic_watch;
-        Watch realtime_watch;
+        sd_event_source *monotonic_event_source;
+        sd_event_source *realtime_event_source;
 
         TimerResult result;
 
index ba7d8d9828087b68b2e3ca06853c955ed180fb7f..e2ff0bd1e5986fe0af05d4c9b0eeb06fe9150103 100644 (file)
 #include <unistd.h>
 #include <fcntl.h>
 
-#include "transaction.h"
 #include "bus-errors.h"
-#include "dbus-common.h"
+#include "bus-util.h"
+#include "bus-error.h"
+#include "transaction.h"
 
 static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies);
 
@@ -231,7 +232,7 @@ static int delete_one_unmergeable_job(Transaction *tr, Job *j) {
         return -EINVAL;
 }
 
-static int transaction_merge_jobs(Transaction *tr, DBusError *e) {
+static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) {
         Job *j;
         Iterator i;
         int r;
@@ -261,8 +262,9 @@ static int transaction_merge_jobs(Transaction *tr, DBusError *e) {
                                 return -EAGAIN;
 
                         /* We couldn't merge anything. Failure */
-                        dbus_set_error(e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, "Transaction contains conflicting jobs '%s' and '%s' for %s. Probably contradicting requirement dependencies configured.",
-                                       job_type_to_string(t), job_type_to_string(k->type), k->unit->id);
+                        sd_bus_error_setf(
+                                        e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, "Transaction contains conflicting jobs '%s' and '%s' for %s. Probably contradicting requirement dependencies configured.",
+                                        job_type_to_string(t), job_type_to_string(k->type), k->unit->id);
                         return r;
                 }
         }
@@ -334,7 +336,7 @@ _pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) {
         return false;
 }
 
-static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, DBusError *e) {
+static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) {
         Iterator i;
         Unit *u;
         int r;
@@ -405,8 +407,8 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
 
                 log_error("Unable to break cycle");
 
-                dbus_set_error(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
-                               "Transaction order is cyclic. See system logs for details.");
+                sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC,
+                                  "Transaction order is cyclic. See system logs for details.");
                 return -ENOEXEC;
         }
 
@@ -445,7 +447,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi
         return 0;
 }
 
-static int transaction_verify_order(Transaction *tr, unsigned *generation, DBusError *e) {
+static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bus_error *e) {
         Job *j;
         int r;
         Iterator i;
@@ -490,7 +492,7 @@ rescan:
         }
 }
 
-static int transaction_is_destructive(Transaction *tr, JobMode mode, DBusError *e) {
+static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_error *e) {
         Iterator i;
         Job *j;
 
@@ -508,7 +510,7 @@ static int transaction_is_destructive(Transaction *tr, JobMode mode, DBusError *
                 if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) &&
                     !job_type_is_superset(j->type, j->unit->job->type)) {
 
-                        dbus_set_error(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, "Transaction is destructive.");
+                        sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, "Transaction is destructive.");
                         return -EEXIST;
                 }
         }
@@ -635,7 +637,7 @@ rollback:
         return r;
 }
 
-int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e) {
+int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e) {
         Iterator i;
         Job *j;
         int r;
@@ -677,7 +679,7 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
                         break;
 
                 if (r != -EAGAIN) {
-                        log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error(e, r));
+                        log_warning("Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error_message(e, r));
                         return r;
                 }
 
@@ -694,7 +696,7 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
                         break;
 
                 if (r != -EAGAIN) {
-                        log_warning("Requested transaction contains unmergeable jobs: %s", bus_error(e, r));
+                        log_warning("Requested transaction contains unmergeable jobs: %s", bus_error_message(e, r));
                         return r;
                 }
 
@@ -713,7 +715,7 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
         /* Ninth step: check whether we can actually apply this */
         r = transaction_is_destructive(tr, mode, e);
         if (r < 0) {
-                log_notice("Requested transaction contradicts existing jobs: %s", bus_error(e, r));
+                log_notice("Requested transaction contradicts existing jobs: %s", bus_error_message(e, r));
                 return r;
         }
 
@@ -835,7 +837,7 @@ int transaction_add_job_and_dependencies(
                 bool conflicts,
                 bool ignore_requirements,
                 bool ignore_order,
-                DBusError *e) {
+                sd_bus_error *e) {
         Job *ret;
         Iterator i;
         Unit *dep;
@@ -856,12 +858,12 @@ int transaction_add_job_and_dependencies(
             unit->load_state != UNIT_ERROR &&
             unit->load_state != UNIT_NOT_FOUND &&
             unit->load_state != UNIT_MASKED) {
-                dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
+                sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
                 return -EINVAL;
         }
 
         if (type != JOB_STOP && unit->load_state == UNIT_ERROR) {
-                dbus_set_error(e, BUS_ERROR_LOAD_FAILED,
+                sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
                                "Unit %s failed to load: %s. "
                                "See system logs and 'systemctl status %s' for details.",
                                unit->id,
@@ -871,7 +873,7 @@ int transaction_add_job_and_dependencies(
         }
 
         if (type != JOB_STOP && unit->load_state == UNIT_NOT_FOUND) {
-                dbus_set_error(e, BUS_ERROR_LOAD_FAILED,
+                sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED,
                                "Unit %s failed to load: %s.",
                                unit->id,
                                strerror(-unit->load_error));
@@ -879,12 +881,12 @@ int transaction_add_job_and_dependencies(
         }
 
         if (type != JOB_STOP && unit->load_state == UNIT_MASKED) {
-                dbus_set_error(e, BUS_ERROR_MASKED, "Unit %s is masked.", unit->id);
+                sd_bus_error_setf(e, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", unit->id);
                 return -EADDRNOTAVAIL;
         }
 
         if (!unit_job_is_applicable(unit, type)) {
-                dbus_set_error(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, "Job type %s is not applicable for unit %s.", job_type_to_string(type), unit->id);
+                sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, "Job type %s is not applicable for unit %s.", job_type_to_string(type), unit->id);
                 return -EBADR;
         }
 
@@ -916,10 +918,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_warning_unit(dep->id,
                                                          "Cannot add dependency job for unit %s, ignoring: %s",
-                                                         dep->id, bus_error(e, r));
+                                                         dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -935,7 +937,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -946,7 +948,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -955,10 +957,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
                                                       "Cannot add dependency job for unit %s, ignoring: %s",
-                                                      dep->id, bus_error(e, r));
+                                                      dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -967,10 +969,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
                                                       "Cannot add dependency job for unit %s, ignoring: %s",
-                                                      dep->id, bus_error(e, r));
+                                                      dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -981,7 +983,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -990,10 +992,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_full_unit(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_WARNING, dep->id,
                                                       "Cannot add dependency job for unit %s, ignoring: %s",
-                                                      dep->id, bus_error(e, r));
+                                                      dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1004,7 +1006,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1013,10 +1015,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_warning_unit(dep->id,
                                                          "Cannot add dependency job for unit %s, ignoring: %s",
-                                                         dep->id, bus_error(e, r));
+                                                         dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1031,7 +1033,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1042,7 +1044,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1053,7 +1055,7 @@ int transaction_add_job_and_dependencies(
                                                 goto fail;
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
 
@@ -1066,10 +1068,10 @@ int transaction_add_job_and_dependencies(
                                 if (r < 0) {
                                         log_warning_unit(dep->id,
                                                          "Cannot add dependency reload job for unit %s, ignoring: %s",
-                                                         dep->id, bus_error(e, r));
+                                                         dep->id, bus_error_message(e, r));
 
                                         if (e)
-                                                dbus_error_free(e);
+                                                sd_bus_error_free(e);
                                 }
                         }
                 }
index b6ee237ef8b1f42833da2d73561af9d77ecf2282..d949b21b8d42e63b4b13f5c45fa8e23893f813e2 100644 (file)
@@ -48,7 +48,7 @@ int transaction_add_job_and_dependencies(
                 bool conflicts,
                 bool ignore_requirements,
                 bool ignore_order,
-                DBusError *e);
-int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e);
+                sd_bus_error *e);
+int transaction_activate(Transaction *tr, Manager *m, JobMode mode, sd_bus_error *e);
 int transaction_add_isolate_jobs(Transaction *tr, Manager *m);
 void transaction_abort(Transaction *tr);
index 7f463f311ba5b189a1f27b363c66f5c04bcd9dce..1173f0b160c14b87fb150d059990096a4f5bd4c7 100644 (file)
@@ -29,8 +29,8 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
-#include "systemd/sd-id128.h"
-#include "systemd/sd-messages.h"
+#include "sd-id128.h"
+#include "sd-messages.h"
 #include "set.h"
 #include "unit.h"
 #include "macro.h"
@@ -48,6 +48,7 @@
 #include "label.h"
 #include "fileio-label.h"
 #include "bus-errors.h"
+#include "dbus.h"
 
 const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
         [UNIT_SERVICE] = &service_vtable,
@@ -326,7 +327,7 @@ void unit_add_to_dbus_queue(Unit *u) {
                 return;
 
         /* Shortcut things if nobody cares */
-        if (!bus_has_subscriber(u->manager)) {
+        if (set_isempty(u->manager->subscribed)) {
                 u->sent_dbus_new_signal = true;
                 return;
         }
@@ -1658,46 +1659,6 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
         unit_add_to_gc_queue(u);
 }
 
-int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w) {
-        struct epoll_event ev = {
-                .data.ptr = w,
-                .events = events,
-        };
-
-        assert(u);
-        assert(fd >= 0);
-        assert(w);
-        assert(w->type == WATCH_INVALID || (w->type == WATCH_FD && w->fd == fd && w->data.unit == u));
-
-        if (epoll_ctl(u->manager->epoll_fd,
-                      w->type == WATCH_INVALID ? EPOLL_CTL_ADD : EPOLL_CTL_MOD,
-                      fd,
-                      &ev) < 0)
-                return -errno;
-
-        w->fd = fd;
-        w->type = WATCH_FD;
-        w->data.unit = u;
-
-        return 0;
-}
-
-void unit_unwatch_fd(Unit *u, Watch *w) {
-        assert(u);
-        assert(w);
-
-        if (w->type == WATCH_INVALID)
-                return;
-
-        assert(w->type == WATCH_FD);
-        assert(w->data.unit == u);
-        assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
-
-        w->fd = -1;
-        w->type = WATCH_INVALID;
-        w->data.unit = NULL;
-}
-
 int unit_watch_pid(Unit *u, pid_t pid) {
         assert(u);
         assert(pid >= 1);
@@ -1715,90 +1676,6 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
         hashmap_remove_value(u->manager->watch_pids, LONG_TO_PTR(pid), u);
 }
 
-int unit_watch_timer(Unit *u, clockid_t clock_id, bool relative, usec_t usec, Watch *w) {
-        struct itimerspec its = {};
-        int flags, fd;
-        bool ours;
-
-        assert(u);
-        assert(w);
-        assert(w->type == WATCH_INVALID || (w->type == WATCH_UNIT_TIMER && w->data.unit == u));
-
-        /* This will try to reuse the old timer if there is one */
-
-        if (w->type == WATCH_UNIT_TIMER) {
-                assert(w->data.unit == u);
-                assert(w->fd >= 0);
-
-                ours = false;
-                fd = w->fd;
-        } else if (w->type == WATCH_INVALID) {
-
-                ours = true;
-                fd = timerfd_create(clock_id, TFD_NONBLOCK|TFD_CLOEXEC);
-                if (fd < 0)
-                        return -errno;
-        } else
-                assert_not_reached("Invalid watch type");
-
-        if (usec <= 0) {
-                /* Set absolute time in the past, but not 0, since we
-                 * don't want to disarm the timer */
-                its.it_value.tv_sec = 0;
-                its.it_value.tv_nsec = 1;
-
-                flags = TFD_TIMER_ABSTIME;
-        } else {
-                timespec_store(&its.it_value, usec);
-                flags = relative ? 0 : TFD_TIMER_ABSTIME;
-        }
-
-        /* This will also flush the elapse counter */
-        if (timerfd_settime(fd, flags, &its, NULL) < 0)
-                goto fail;
-
-        if (w->type == WATCH_INVALID) {
-                struct epoll_event ev = {
-                        .data.ptr = w,
-                        .events = EPOLLIN,
-                };
-
-                if (epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
-                        goto fail;
-        }
-
-        w->type = WATCH_UNIT_TIMER;
-        w->fd = fd;
-        w->data.unit = u;
-
-        return 0;
-
-fail:
-        if (ours)
-                close_nointr_nofail(fd);
-
-        return -errno;
-}
-
-void unit_unwatch_timer(Unit *u, Watch *w) {
-        assert(u);
-        assert(w);
-
-        if (w->type == WATCH_INVALID)
-                return;
-
-        assert(w->type == WATCH_UNIT_TIMER);
-        assert(w->data.unit == u);
-        assert(w->fd >= 0);
-
-        assert_se(epoll_ctl(u->manager->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
-        close_nointr_nofail(w->fd);
-
-        w->fd = -1;
-        w->type = WATCH_INVALID;
-        w->data.unit = NULL;
-}
-
 bool unit_job_is_applicable(Unit *u, JobType j) {
         assert(u);
         assert(j >= 0 && j < _JOB_TYPE_MAX);
@@ -2572,7 +2449,7 @@ bool unit_active_or_pending(Unit *u) {
         return false;
 }
 
-int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) {
+int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
         assert(u);
         assert(w >= 0 && w < _KILL_WHO_MAX);
         assert(signo > 0);
@@ -2618,23 +2495,23 @@ int unit_kill_common(
                 int signo,
                 pid_t main_pid,
                 pid_t control_pid,
-                DBusError *error) {
+                sd_bus_error *error) {
 
         int r = 0;
 
         if (who == KILL_MAIN && main_pid <= 0) {
                 if (main_pid < 0)
-                        dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
+                        sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
                 else
-                        dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
+                        sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill");
                 return -ESRCH;
         }
 
         if (who == KILL_CONTROL && control_pid <= 0) {
                 if (control_pid < 0)
-                        dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
+                        sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type));
                 else
-                        dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
+                        sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
                 return -ESRCH;
         }
 
@@ -2746,6 +2623,17 @@ ExecContext *unit_get_exec_context(Unit *u) {
         return (ExecContext*) ((uint8_t*) u + offset);
 }
 
+KillContext *unit_get_kill_context(Unit *u) {
+        size_t offset;
+        assert(u);
+
+        offset = UNIT_VTABLE(u)->kill_context_offset;
+        if (offset <= 0)
+                return NULL;
+
+        return (KillContext*) ((uint8_t*) u + offset);
+}
+
 CGroupContext *unit_get_cgroup_context(Unit *u) {
         size_t offset;
 
index 1a558423f7711f12c2aaa8a6ee0599d05039108d..c58202bf0f00cab81841114d1a8a2ffb7bc678bc 100644 (file)
@@ -32,6 +32,7 @@ typedef enum UnitDependency UnitDependency;
 typedef struct UnitRef UnitRef;
 typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
 
+#include "sd-event.h"
 #include "set.h"
 #include "util.h"
 #include "list.h"
@@ -295,6 +296,10 @@ struct UnitVTable {
          * CGroupContext is found, if the unit type has that */
         size_t cgroup_context_offset;
 
+        /* If greater than 0, the offset into the object where
+         * KillContext is found, if the unit type has that */
+        size_t kill_context_offset;
+
         /* The name of the configuration file section with the private settings of this unit*/
         const char *private_section;
 
@@ -327,7 +332,7 @@ struct UnitVTable {
         int (*stop)(Unit *u);
         int (*reload)(Unit *u);
 
-        int (*kill)(Unit *u, KillWho w, int signo, DBusError *error);
+        int (*kill)(Unit *u, KillWho w, int signo, sd_bus_error *error);
 
         bool (*can_reload)(Unit *u);
 
@@ -359,9 +364,8 @@ struct UnitVTable {
         /* Return true when this unit is suitable for snapshotting */
         bool (*check_snapshot)(Unit *u);
 
-        void (*fd_event)(Unit *u, int fd, uint32_t events, Watch *w);
+        /* Invoked on every child that died */
         void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
-        void (*timer_event)(Unit *u, uint64_t n_elapsed, Watch *w);
 
         /* Reset failed state if we are in failed state */
         void (*reset_failed)(Unit *u);
@@ -377,14 +381,8 @@ struct UnitVTable {
          * goes away. */
         void (*bus_name_owner_change)(Unit *u, const char *name, const char *old_owner, const char *new_owner);
 
-        /* Called whenever a bus PID lookup finishes */
-        void (*bus_query_pid_done)(Unit *u, const char *name, pid_t pid);
-
-        /* Called for each message received on the bus */
-        DBusHandlerResult (*bus_message_handler)(Unit *u, DBusConnection *c, DBusMessage *message);
-
         /* Called for each property that is being set */
-        int (*bus_set_property)(Unit *u, const char *name, DBusMessageIter *i, UnitSetPropertiesMode mode, DBusError *error);
+        int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitSetPropertiesMode mode, sd_bus_error *error);
 
         /* Called after at least one property got changed to apply the necessary change */
         int (*bus_commit_properties)(Unit *u);
@@ -412,14 +410,16 @@ struct UnitVTable {
         /* Type specific cleanups. */
         void (*shutdown)(Manager *m);
 
-        /* When sending out PropertiesChanged signal, which properties
-         * shall be invalidated? This is a NUL separated list of
-         * strings, to minimize relocations a little. */
-        const char *bus_invalidating_properties;
-
         /* The interface name */
         const char *bus_interface;
 
+        /* The bus vtable */
+        const sd_bus_vtable *bus_vtable;
+
+        /* strv list of changing properties */
+        const char * const * const bus_changing_properties;
+
+        /* The strings to print in status messages */
         UnitStatusMessageFormats status_message_formats;
 
         /* Can units of this type have multiple names? */
@@ -521,20 +521,14 @@ int unit_start(Unit *u);
 int unit_stop(Unit *u);
 int unit_reload(Unit *u);
 
-int unit_kill(Unit *u, KillWho w, int signo, DBusError *error);
-int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, DBusError *error);
+int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error);
+int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, sd_bus_error *error);
 
 void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
 
-int unit_watch_fd(Unit *u, int fd, uint32_t events, Watch *w);
-void unit_unwatch_fd(Unit *u, Watch *w);
-
 int unit_watch_pid(Unit *u, pid_t pid);
 void unit_unwatch_pid(Unit *u, pid_t pid);
 
-int unit_watch_timer(Unit *u, clockid_t, bool relative, usec_t usec, Watch *w);
-void unit_unwatch_timer(Unit *u, Watch *w);
-
 int unit_watch_bus_name(Unit *u, const char *name);
 void unit_unwatch_bus_name(Unit *u, const char *name);
 
@@ -590,6 +584,7 @@ void unit_ref_unset(UnitRef *ref);
 int unit_exec_context_defaults(Unit *u, ExecContext *c);
 
 ExecContext *unit_get_exec_context(Unit *u) _pure_;
+KillContext *unit_get_kill_context(Unit *u) _pure_;
 CGroupContext *unit_get_cgroup_context(Unit *u) _pure_;
 
 int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data);
index 5474c8c5ecf8d3a7f5360c1665a4d7dbe77c3a36..f442e953e008423d951cc29992aec824289f4c92 100644 (file)
@@ -21,6 +21,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <stdbool.h>
+
 #include "sd-bus.h"
 
 bool bus_error_is_dirty(sd_bus_error *e);
index faed183990ac77dc895f524f08bea9d3afc83a52..a1d60b113353cc79e4e765c9360faec8023a648a 100644 (file)
@@ -119,11 +119,12 @@ enum bus_state {
         BUS_AUTHENTICATING,
         BUS_HELLO,
         BUS_RUNNING,
+        BUS_CLOSING,
         BUS_CLOSED
 };
 
 static inline bool BUS_IS_OPEN(enum bus_state state) {
-        return state > BUS_UNSET && state < BUS_CLOSED;
+        return state > BUS_UNSET && state < BUS_CLOSING;
 }
 
 enum bus_auth {
@@ -155,7 +156,6 @@ struct sd_bus {
         bool anonymous_auth:1;
         bool prefer_readv:1;
         bool prefer_writev:1;
-        bool processing:1;
         bool match_callbacks_modified:1;
         bool filter_callbacks_modified:1;
         bool nodes_modified:1;
index 9a49e431c0a4e124aab47ee453cdb5d9aef5c03f..4c6031729ab1ae1eba164ed4f77a31b6f0dd6567 100644 (file)
@@ -111,13 +111,10 @@ static int introspect_write_arguments(struct introspect *i, const char *signatur
         }
 }
 
-int introspect_write_interface(struct introspect *i, const char *interface, const sd_bus_vtable *v) {
+int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) {
         assert(i);
-        assert(interface);
         assert(v);
 
-        fprintf(i->f, " <interface name=\"%s\">\n", interface);
-
         for (; v->type != _SD_BUS_VTABLE_END; v++) {
 
                 switch (v->type) {
@@ -155,7 +152,6 @@ int introspect_write_interface(struct introspect *i, const char *interface, cons
 
         }
 
-        fputs(" </interface>\n", i->f);
         return 0;
 }
 
index 48c3885d9459913aac3953afab6d6dc43e231811..0be12cffb9b5004c44ffd93777d7ef0248d427d1 100644 (file)
@@ -36,6 +36,6 @@ struct introspect {
 int introspect_begin(struct introspect *i);
 int introspect_write_default_interfaces(struct introspect *i, bool object_manager);
 int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix);
-int introspect_write_interface(struct introspect *i, const char *interface, const sd_bus_vtable *v);
+int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v);
 int introspect_finish(struct introspect *i, sd_bus *bus, sd_bus_message *m, sd_bus_message **reply);
 void introspect_free(struct introspect *i);
index 4f21db56e24f7b414193c9fa2140e841c0d23b86..666307cc6e652ba42abe7220d62a9623e8deb6cf 100644 (file)
@@ -3294,6 +3294,7 @@ _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) {
 
         return !isempty(c->signature);
 }
+
 static int message_read_ap(
                 sd_bus_message *m,
                 const char *types,
index 8369068bd0a78a6d1fd986378ec8a1338ca1c8c1..a6e8b2de867a38d5ea1e4a67026585a08bd83676 100644 (file)
@@ -728,6 +728,7 @@ static int process_introspect(
 
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         _cleanup_set_free_free_ Set *s = NULL;
+        const char *previous_interface = NULL;
         struct introspect intro;
         struct node_vtable *c;
         bool empty;
@@ -768,11 +769,24 @@ static int process_introspect(
 
                 empty = false;
 
-                r = introspect_write_interface(&intro, c->interface, c->vtable);
+                if (!streq_ptr(previous_interface, c->interface)) {
+
+                        if (previous_interface)
+                                fputs(" </interface>\n", intro.f);
+
+                        fprintf(intro.f, " <interface name=\"%s\">\n", c->interface);
+                }
+
+                r = introspect_write_interface(&intro, c->vtable);
                 if (r < 0)
                         goto finish;
+
+                previous_interface = c->interface;
         }
 
+        if (previous_interface)
+                fputs(" </interface>\n", intro.f);
+
         if (empty) {
                 /* Nothing?, let's see if we exist at all, and if not
                  * refuse to do anything */
@@ -806,51 +820,6 @@ finish:
         return r;
 }
 
-static int object_manager_serialize_vtable(
-                sd_bus *bus,
-                sd_bus_message *reply,
-                const char *path,
-                struct node_vtable *c,
-                sd_bus_error *error,
-                void *userdata) {
-
-        int r;
-
-        assert(bus);
-        assert(reply);
-        assert(path);
-        assert(c);
-        assert(error);
-
-        r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
-        if (r < 0)
-                return r;
-
-        r = sd_bus_message_append(reply, "s", c->interface);
-        if (r < 0)
-                return r;
-
-        r = sd_bus_message_open_container(reply, 'a', "{sv}");
-        if (r < 0)
-                return r;
-
-        r = vtable_append_all_properties(bus, reply, path, c, userdata, error);
-        if (r < 0)
-                return r;
-        if (bus->nodes_modified)
-                return 0;
-
-        r = sd_bus_message_close_container(reply);
-        if (r < 0)
-                return r;
-
-        r = sd_bus_message_close_container(reply);
-        if (r < 0)
-                return r;
-
-        return 0;
-}
-
 static int object_manager_serialize_path(
                 sd_bus *bus,
                 sd_bus_message *reply,
@@ -859,9 +828,10 @@ static int object_manager_serialize_path(
                 bool require_fallback,
                 sd_bus_error *error) {
 
+        const char *previous_interface = NULL;
+        bool found_something = false;
         struct node_vtable *i;
         struct node *n;
-        bool found_something = false;
         int r;
 
         assert(bus);
@@ -889,6 +859,9 @@ static int object_manager_serialize_path(
                         continue;
 
                 if (!found_something) {
+
+                        /* Open the object part */
+
                         r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}");
                         if (r < 0)
                                 return r;
@@ -904,13 +877,54 @@ static int object_manager_serialize_path(
                         found_something = true;
                 }
 
-                r = object_manager_serialize_vtable(bus, reply, path, i, error, u);
+                if (!streq_ptr(previous_interface, i->interface)) {
+
+                        /* Maybe close the previous interface part */
+
+                        if (previous_interface) {
+                                r = sd_bus_message_close_container(reply);
+                                if (r < 0)
+                                        return r;
+
+                                r = sd_bus_message_close_container(reply);
+                                if (r < 0)
+                                        return r;
+                        }
+
+                        /* Open the new interface part */
+
+                        r = sd_bus_message_open_container(reply, 'e', "sa{sv}");
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(reply, "s", i->interface);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_open_container(reply, 'a', "{sv}");
+                        if (r < 0)
+                                return r;
+                }
+
+                r = vtable_append_all_properties(bus, reply, path, i, u, error);
                 if (r < 0)
                         return r;
                 if (sd_bus_error_is_set(error))
                         return 0;
                 if (bus->nodes_modified)
                         return 0;
+
+                previous_interface = i->interface;
+        }
+
+        if (previous_interface) {
+                r = sd_bus_message_close_container(reply);
+                if (r < 0)
+                        return r;
+
+                r = sd_bus_message_close_container(reply);
+                if (r < 0)
+                        return r;
         }
 
         if (found_something) {
@@ -1503,7 +1517,7 @@ static int add_object_vtable_internal(
                 sd_bus_object_find_t find,
                 void *userdata) {
 
-        struct node_vtable *c = NULL, *i;
+        struct node_vtable *c = NULL, *i, *existing = NULL;
         const sd_bus_vtable *v;
         struct node *n;
         int r;
@@ -1515,6 +1529,10 @@ static int add_object_vtable_internal(
         assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL);
         assert_return(vtable[0].x.start.element_size == sizeof(struct sd_bus_vtable), -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
+        assert_return(!streq(interface, "org.freedesktop.DBus.Properties") &&
+                      !streq(interface, "org.freedesktop.DBus.Introspectable") &&
+                      !streq(interface, "org.freedesktop.DBus.Peer") &&
+                      !streq(interface, "org.freedesktop.DBus.ObjectManager"), -EINVAL);
 
         r = hashmap_ensure_allocated(&bus->vtable_methods, vtable_member_hash_func, vtable_member_compare_func);
         if (r < 0)
@@ -1529,15 +1547,20 @@ static int add_object_vtable_internal(
                 return -ENOMEM;
 
         LIST_FOREACH(vtables, i, n->vtables) {
-                if (streq(i->interface, interface)) {
-                        r = -EEXIST;
-                        goto fail;
-                }
-
                 if (i->is_fallback != fallback) {
                         r = -EPROTOTYPE;
                         goto fail;
                 }
+
+                if (streq(i->interface, interface)) {
+
+                        if (i->vtable == vtable) {
+                                r = -EEXIST;
+                                goto fail;
+                        }
+
+                        existing = i;
+                }
         }
 
         c = new0(struct node_vtable, 1);
@@ -1654,7 +1677,7 @@ static int add_object_vtable_internal(
                 }
         }
 
-        LIST_PREPEND(vtables, n->vtables, c);
+        LIST_INSERT_AFTER(vtables, n->vtables, existing, c);
         bus->nodes_modified = true;
 
         return 0;
@@ -1671,7 +1694,10 @@ static int remove_object_vtable_internal(
                 sd_bus *bus,
                 const char *path,
                 const char *interface,
-                bool fallback) {
+                const sd_bus_vtable *vtable,
+                bool fallback,
+                sd_bus_object_find_t find,
+                void *userdata) {
 
         struct node_vtable *c;
         struct node *n;
@@ -1686,7 +1712,11 @@ static int remove_object_vtable_internal(
                 return 0;
 
         LIST_FOREACH(vtables, c, n->vtables)
-                if (streq(c->interface, interface) && c->is_fallback == fallback)
+                if (streq(c->interface, interface) &&
+                    c->is_fallback == fallback &&
+                    c->vtable == vtable &&
+                    c->find == find &&
+                    c->userdata == userdata)
                         break;
 
         if (!c)
@@ -1715,9 +1745,11 @@ _public_ int sd_bus_add_object_vtable(
 _public_ int sd_bus_remove_object_vtable(
                 sd_bus *bus,
                 const char *path,
-                const char *interface) {
+                const char *interface,
+                const sd_bus_vtable *vtable,
+                void *userdata) {
 
-        return remove_object_vtable_internal(bus, path, interface, false);
+        return remove_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
 }
 
 _public_ int sd_bus_add_fallback_vtable(
@@ -1734,9 +1766,12 @@ _public_ int sd_bus_add_fallback_vtable(
 _public_ int sd_bus_remove_fallback_vtable(
                 sd_bus *bus,
                 const char *path,
-                const char *interface) {
+                const char *interface,
+                const sd_bus_vtable *vtable,
+                sd_bus_object_find_t find,
+                void *userdata) {
 
-        return remove_object_vtable_internal(bus, path, interface, true);
+        return remove_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
 }
 
 _public_ int sd_bus_add_node_enumerator(
@@ -1824,8 +1859,8 @@ static int emit_properties_changed_on_interface(
                 char **names) {
 
         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
-        bool has_invalidating = false;
-        struct vtable_member key;
+        bool has_invalidating = false, has_changing = false;
+        struct vtable_member key = {};
         struct node_vtable *c;
         struct node *n;
         char **property;
@@ -1841,23 +1876,6 @@ static int emit_properties_changed_on_interface(
         if (!n)
                 return 0;
 
-        LIST_FOREACH(vtables, c, n->vtables) {
-                if (require_fallback && !c->is_fallback)
-                        continue;
-
-                if (streq(c->interface, interface))
-                        break;
-        }
-
-        if (!c)
-                return 0;
-
-        r = node_vtable_get_userdata(bus, path, c, &u);
-        if (r <= 0)
-                return r;
-        if (bus->nodes_modified)
-                return 0;
-
         r = sd_bus_message_new_signal(bus, path, "org.freedesktop.DBus.Properties", "PropertiesChanged", &m);
         if (r < 0)
                 return r;
@@ -1873,52 +1891,78 @@ static int emit_properties_changed_on_interface(
         key.path = prefix;
         key.interface = interface;
 
-        STRV_FOREACH(property, names) {
-                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-                struct vtable_member *v;
-
-                assert_return(member_name_is_valid(*property), -EINVAL);
-
-                key.member = *property;
-                v = hashmap_get(bus->vtable_properties, &key);
-                if (!v)
-                        return -ENOENT;
-
-                assert(c == v->parent);
-                assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, -EDOM);
+        LIST_FOREACH(vtables, c, n->vtables) {
+                if (require_fallback && !c->is_fallback)
+                        continue;
 
-                if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
-                        has_invalidating = true;
+                if (!streq(c->interface, interface))
                         continue;
-                }
 
-                r = sd_bus_message_open_container(m, 'e', "sv");
+                r = node_vtable_get_userdata(bus, path, c, &u);
                 if (r < 0)
                         return r;
+                if (bus->nodes_modified)
+                        return 0;
+                if (r == 0)
+                        continue;
 
-                r = sd_bus_message_append(m, "s", *property);
-                if (r < 0)
-                        return r;
+                STRV_FOREACH(property, names) {
+                        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+                        struct vtable_member *v;
 
-                r = sd_bus_message_open_container(m, 'v', v->vtable->x.property.signature);
-                if (r < 0)
-                        return r;
+                        assert_return(member_name_is_valid(*property), -EINVAL);
 
-                r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u));
-                if (r < 0)
-                        return r;
-                if (bus->nodes_modified)
-                        return 0;
+                        key.member = *property;
+                        v = hashmap_get(bus->vtable_properties, &key);
+                        if (!v)
+                                return -ENOENT;
+
+                        /* If there are two vtables for the same
+                         * interface, let's handle this property when
+                         * we come to that vtable. */
+                        if (c != v->parent)
+                                continue;
 
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return r;
+                        assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, -EDOM);
 
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return r;
+                        if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) {
+                                has_invalidating = true;
+                                continue;
+                        }
+
+                        has_changing = true;
+
+                        r = sd_bus_message_open_container(m, 'e', "sv");
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_append(m, "s", *property);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_open_container(m, 'v', v->vtable->x.property.signature);
+                        if (r < 0)
+                                return r;
+
+                        r = invoke_property_get(bus, v->vtable, m->path, interface, *property, m, &error, vtable_property_convert_userdata(v->vtable, u));
+                        if (r < 0)
+                                return r;
+                        if (bus->nodes_modified)
+                                return 0;
+
+                        r = sd_bus_message_close_container(m);
+                        if (r < 0)
+                                return r;
+
+                        r = sd_bus_message_close_container(m);
+                        if (r < 0)
+                                return r;
+                }
         }
 
+        if (!has_invalidating && !has_changing)
+                return 0;
+
         r = sd_bus_message_close_container(m);
         if (r < 0)
                 return r;
@@ -1928,19 +1972,35 @@ static int emit_properties_changed_on_interface(
                 return r;
 
         if (has_invalidating) {
-                STRV_FOREACH(property, names) {
-                        struct vtable_member *v;
-
-                        key.member = *property;
-                        assert_se(v = hashmap_get(bus->vtable_properties, &key));
-                        assert(c == v->parent);
+                LIST_FOREACH(vtables, c, n->vtables) {
+                        if (require_fallback && !c->is_fallback)
+                                continue;
 
-                        if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY))
+                        if (!streq(c->interface, interface))
                                 continue;
 
-                        r = sd_bus_message_append(m, "s", *property);
+                        r = node_vtable_get_userdata(bus, path, c, &u);
                         if (r < 0)
                                 return r;
+                        if (bus->nodes_modified)
+                                return 0;
+                        if (r == 0)
+                                continue;
+
+                        STRV_FOREACH(property, names) {
+                                struct vtable_member *v;
+
+                                key.member = *property;
+                                assert_se(v = hashmap_get(bus->vtable_properties, &key));
+                                assert(c == v->parent);
+
+                                if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY))
+                                        continue;
+
+                                r = sd_bus_message_append(m, "s", *property);
+                                if (r < 0)
+                                        return r;
+                        }
                 }
         }
 
@@ -2028,6 +2088,7 @@ static int interfaces_added_append_one_prefix(
                 bool require_fallback) {
 
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        bool found_interface = false;
         struct node_vtable *c;
         struct node *n;
         void *u = NULL;
@@ -2047,38 +2108,43 @@ static int interfaces_added_append_one_prefix(
                 if (require_fallback && !c->is_fallback)
                         continue;
 
-                if (streq(c->interface, interface))
-                        break;
-        }
+                if (!streq(c->interface, interface))
+                        continue;
 
-        if (!c)
-                return 0;
+                r = node_vtable_get_userdata(bus, path, c, &u);
+                if (r < 0)
+                        return r;
+                if (bus->nodes_modified)
+                        return 0;
+                if (r == 0)
+                        continue;
 
-        r = node_vtable_get_userdata(bus, path, c, &u);
-        if (r <= 0)
-                return r;
-        if (bus->nodes_modified)
-                return 0;
+                if (!found_interface) {
+                        r = sd_bus_message_append_basic(m, 's', interface);
+                        if (r < 0)
+                                return r;
 
-        r = sd_bus_message_append_basic(m, 's', interface);
-        if (r < 0)
-                return r;
+                        r = sd_bus_message_open_container(m, 'a', "{sv}");
+                        if (r < 0)
+                                return r;
 
-        r = sd_bus_message_open_container(m, 'a', "{sv}");
-        if (r < 0)
-                return r;
+                        found_interface = true;
+                }
 
-        r = vtable_append_all_properties(bus, m,path, c, u, &error);
-        if (r < 0)
-                return r;
-        if (bus->nodes_modified)
-                return 0;
+                r = vtable_append_all_properties(bus, m, path, c, u, &error);
+                if (r < 0)
+                        return r;
+                if (bus->nodes_modified)
+                        return 0;
+        }
 
-        r = sd_bus_message_close_container(m);
-        if (r < 0)
-                return r;
+        if (found_interface) {
+                r = sd_bus_message_close_container(m);
+                if (r < 0)
+                        return r;
+        }
 
-        return 1;
+        return found_interface;
 }
 
 static int interfaces_added_append_one(
index 35c054baf62f7e397a9ff4e9c48176778148c2fd..1e5bf4821d9526da05478c92cfe2785acd611b08 100644 (file)
@@ -33,7 +33,10 @@ static int signature_element_length_internal(
 
         int r;
 
-        assert(s);
+        if (!s)
+                return -EINVAL;
+
+        assert(l);
 
         if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
                 *l = 1;
@@ -114,7 +117,8 @@ bool signature_is_single(const char *s, bool allow_dict_entry) {
         int r;
         size_t t;
 
-        assert(s);
+        if (!s)
+                return false;
 
         r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
         if (r < 0)
@@ -124,7 +128,9 @@ bool signature_is_single(const char *s, bool allow_dict_entry) {
 }
 
 bool signature_is_pair(const char *s) {
-        assert(s);
+
+        if (!s)
+                return false;
 
         if (!bus_type_is_basic(*s))
                 return false;
@@ -136,7 +142,8 @@ bool signature_is_valid(const char *s, bool allow_dict_entry) {
         const char *p;
         int r;
 
-        assert(s);
+        if (!s)
+                return false;
 
         p = s;
         while (*p) {
index ed6fdc473ae705c2ca56f639aefd3c7eb49b8af7..65323d008103b5a2db28177f71e82482e4433328 100644 (file)
@@ -383,7 +383,7 @@ void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
 #endif
 }
 
-static int bus_check_peercred(sd_bus *c) {
+int bus_check_peercred(sd_bus *c) {
         struct ucred ucred;
         socklen_t l;
         int fd;
@@ -1014,7 +1014,8 @@ int bus_property_get_bool(
         return sd_bus_message_append_basic(reply, 'b', &b);
 }
 
-int bus_property_get_uid(
+#if __SIZEOF_SIZE_T__ != 8
+int bus_property_get_size(
                 sd_bus *bus,
                 const char *path,
                 const char *interface,
@@ -1023,12 +1024,41 @@ int bus_property_get_uid(
                 sd_bus_error *error,
                 void *userdata) {
 
-        assert_cc(sizeof(uint32_t) == sizeof(uid_t));
-        assert_cc(sizeof(uint32_t) == sizeof(gid_t));
-        assert_cc(sizeof(uint32_t) == sizeof(pid_t));
+        uint64_t sz = *(size_t*) userdata;
 
-        return sd_bus_message_append_basic(reply, 'u', userdata);
+        return sd_bus_message_append_basic(reply, 't', &sz);
 }
+#endif
+
+#if __SIZEOF_LONG__ != 8
+int bus_property_get_long(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        int64_t l = *(long*) userdata;
+
+        return sd_bus_message_append_basic(reply, 'x', &l);
+}
+
+int bus_property_get_ulong(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        uint64_t ul = *(unsigned long*) userdata;
+
+        return sd_bus_message_append_basic(reply, 't', &ul);
+}
+#endif
 
 int bus_log_parse_error(int r) {
         log_error("Failed to parse message: %s", strerror(-r));
index 314c2f786775e766d506ab4c33810f4cefe4ae58..c8d5dd982e72e98b02780cae21e7d0cd5a23ad67 100644 (file)
@@ -55,7 +55,8 @@ int bus_map_all_properties(sd_bus *bus,
 int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name);
 
 int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout);
-int bus_property_get_tristate(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+
+int bus_check_peercred(sd_bus *c);
 
 int bus_verify_polkit(sd_bus *bus, sd_bus_message *m, const char *action, bool interactive, bool *_challenge, sd_bus_error *e);
 
@@ -71,11 +72,48 @@ int bus_open_transport_systemd(BusTransport transport, const char *host, bool us
 int bus_print_property(const char *name, sd_bus_message *property, bool all);
 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all);
 
+int bus_property_get_tristate(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
 int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
-int bus_property_get_uid(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
 
-#define bus_property_get_gid bus_property_get_uid
-#define bus_property_get_pid bus_property_get_uid
+#define bus_property_get_usec ((sd_bus_property_get_t) NULL)
+#define bus_property_set_usec ((sd_bus_property_set_t) NULL)
+
+assert_cc(sizeof(int) == sizeof(int32_t));
+#define bus_property_get_int ((sd_bus_property_get_t) NULL)
+
+assert_cc(sizeof(unsigned) == sizeof(unsigned));
+#define bus_property_get_unsigned ((sd_bus_property_get_t) NULL)
+
+/* On 64bit machines we can use the default serializer for size_t and
+ * friends, otherwise we need to cast this manually */
+#if __SIZEOF_SIZE_T__ == 8
+#define bus_property_get_size ((sd_bus_property_get_t) NULL)
+#else
+int bus_property_get_size(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+#endif
+
+#if __SIZEOF_LONG__ == 8
+#define bus_property_get_long ((sd_bus_property_get_t) NULL)
+#define bus_property_get_ulong ((sd_bus_property_get_t) NULL)
+#else
+int bus_property_get_long(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+int bus_property_get_ulong(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, sd_bus_error *error, void *userdata);
+#endif
+
+/* uid_t and friends on Linux 32 bit. This means we can just use the
+ * default serializer for 32bit unsigned, for serializing it, and map
+ * it to NULL here */
+assert_cc(sizeof(uid_t) == sizeof(uint32_t));
+#define bus_property_get_uid ((sd_bus_property_get_t) NULL)
+
+assert_cc(sizeof(gid_t) == sizeof(uint32_t));
+#define bus_property_get_gid ((sd_bus_property_get_t) NULL)
+
+assert_cc(sizeof(pid_t) == sizeof(uint32_t));
+#define bus_property_get_pid ((sd_bus_property_get_t) NULL)
+
+assert_cc(sizeof(mode_t) == sizeof(uint32_t));
+#define bus_property_get_mode ((sd_bus_property_get_t) NULL)
 
 int bus_log_parse_error(int r);
 int bus_log_create_error(int r);
@@ -129,22 +167,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
         }                                                               \
         struct __useless_struct_to_allow_trailing_semicolon__
 
-#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
-#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
-#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
-
-#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
-#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
-#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
-
-#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
-#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
-#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
-#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID"
-#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat"
-#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat"
-#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl"
-#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken"
-#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
-#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
-#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
+#define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \
+        SD_BUS_PROPERTY(name, "t", bus_property_get_usec, offset + offsetof(struct dual_timestamp, realtime), flags), \
+        SD_BUS_PROPERTY(name "Monotonic", "t", bus_property_get_usec, offset + offsetof(struct dual_timestamp, monotonic), flags)
index c8248e19aa074fa1235bef566ec6f44907b8ccec..bc88ac977c96f3c4903995485e0eb95f2b2a6a71 100644 (file)
@@ -1204,6 +1204,18 @@ _public_ void sd_bus_close(sd_bus *bus) {
          * freed. */
 }
 
+static void bus_enter_closing(sd_bus *bus) {
+        assert(bus);
+
+        if (bus->state != BUS_OPENING &&
+            bus->state != BUS_AUTHENTICATING &&
+            bus->state != BUS_HELLO &&
+            bus->state != BUS_RUNNING)
+                return;
+
+        bus->state = BUS_CLOSING;
+}
+
 _public_ sd_bus *sd_bus_ref(sd_bus *bus) {
         assert_return(bus, NULL);
 
@@ -1282,6 +1294,20 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
         return bus_message_seal(m, ++b->serial);
 }
 
+static int bus_write_message(sd_bus *bus, sd_bus_message *message, size_t *idx) {
+        int r;
+
+        assert(bus);
+        assert(message);
+
+        if (bus->is_kernel)
+                r = bus_kernel_write_message(bus, message);
+        else
+                r = bus_socket_write_message(bus, message, idx);
+
+        return r;
+}
+
 static int dispatch_wqueue(sd_bus *bus) {
         int r, ret = 0;
 
@@ -1290,15 +1316,10 @@ static int dispatch_wqueue(sd_bus *bus) {
 
         while (bus->wqueue_size > 0) {
 
-                if (bus->is_kernel)
-                        r = bus_kernel_write_message(bus, bus->wqueue[0]);
-                else
-                        r = bus_socket_write_message(bus, bus->wqueue[0], &bus->windex);
-
-                if (r < 0) {
-                        sd_bus_close(bus);
+                r = bus_write_message(bus, bus->wqueue[0], &bus->windex);
+                if (r < 0)
                         return r;
-                else if (r == 0)
+                else if (r == 0)
                         /* Didn't do anything this time */
                         return ret;
                 else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
@@ -1324,6 +1345,20 @@ static int dispatch_wqueue(sd_bus *bus) {
         return ret;
 }
 
+static int bus_read_message(sd_bus *bus, sd_bus_message **m) {
+        int r;
+
+        assert(bus);
+        assert(m);
+
+        if (bus->is_kernel)
+                r = bus_kernel_read_message(bus, m);
+        else
+                r = bus_socket_read_message(bus, m);
+
+        return r;
+}
+
 static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
         sd_bus_message *z = NULL;
         int r, ret = 0;
@@ -1343,15 +1378,9 @@ static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
 
         /* Try to read a new message */
         do {
-                if (bus->is_kernel)
-                        r = bus_kernel_read_message(bus, &z);
-                else
-                        r = bus_socket_read_message(bus, &z);
-
-                if (r < 0) {
-                        sd_bus_close(bus);
+                r = bus_read_message(bus, &z);
+                if (r < 0)
                         return r;
-                }
                 if (r == 0)
                         return ret;
 
@@ -1395,15 +1424,10 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
         if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
                 size_t idx = 0;
 
-                if (bus->is_kernel)
-                        r = bus_kernel_write_message(bus, m);
-                else
-                        r = bus_socket_write_message(bus, m, &idx);
-
-                if (r < 0) {
-                        sd_bus_close(bus);
+                r = bus_write_message(bus, m, &idx);
+                if (r < 0)
                         return r;
-                else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m))  {
+                else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m))  {
                         /* Wasn't fully written. So let's remember how
                          * much was written. Note that the first entry
                          * of the wqueue array is always allocated so
@@ -1573,7 +1597,7 @@ int bus_ensure_running(sd_bus *bus) {
 
         assert(bus);
 
-        if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED)
+        if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED || bus->state == BUS_CLOSING)
                 return -ENOTCONN;
         if (bus->state == BUS_RUNNING)
                 return 1;
@@ -1644,12 +1668,10 @@ _public_ int sd_bus_call(
                         room = true;
                 }
 
-                if (bus->is_kernel)
-                        r = bus_kernel_read_message(bus, &incoming);
-                else
-                        r = bus_socket_read_message(bus, &incoming);
+                r = bus_read_message(bus, &incoming);
                 if (r < 0)
                         return r;
+
                 if (incoming) {
 
                         if (incoming->reply_serial == serial) {
@@ -1731,7 +1753,6 @@ _public_ int sd_bus_call(
 _public_ int sd_bus_get_fd(sd_bus *bus) {
 
         assert_return(bus, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
         assert_return(bus->input_fd == bus->output_fd, -EPERM);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
@@ -1742,7 +1763,7 @@ _public_ int sd_bus_get_events(sd_bus *bus) {
         int flags = 0;
 
         assert_return(bus, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+        assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         if (bus->state == BUS_OPENING)
@@ -1769,9 +1790,14 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
 
         assert_return(bus, -EINVAL);
         assert_return(timeout_usec, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+        assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
+        if (bus->state == BUS_CLOSING) {
+                *timeout_usec = 0;
+                return 1;
+        }
+
         if (bus->state == BUS_AUTHENTICATING) {
                 *timeout_usec = bus->auth_timeout;
                 return 1;
@@ -1821,12 +1847,21 @@ static int process_timeout(sd_bus *bus) {
         if (r < 0)
                 return r;
 
+        r = bus_seal_message(bus, m);
+        if (r < 0)
+                return r;
+
         assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
         hashmap_remove(bus->reply_callbacks, &c->serial);
 
+        bus->current = m;
+        bus->iteration_counter ++;
+
         r = c->callback(bus, m, c->userdata);
         free(c);
 
+        bus->current = NULL;
+
         return r < 0 ? r : 1;
 }
 
@@ -1877,7 +1912,7 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
         r = c->callback(bus, m, c->userdata);
         free(c);
 
-        return r;
+        return r < 0 ? r : 1;
 }
 
 static int process_filter(sd_bus *bus, sd_bus_message *m) {
@@ -2078,6 +2113,85 @@ null_message:
         return r;
 }
 
+static int process_closing(sd_bus *bus, sd_bus_message **ret) {
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        struct reply_callback *c;
+        int r;
+
+        assert(bus);
+        assert(bus->state == BUS_CLOSING);
+
+        c = hashmap_first(bus->reply_callbacks);
+        if (c) {
+                /* First, fail all outstanding method calls */
+                r = bus_message_new_synthetic_error(
+                                bus,
+                                c->serial,
+                                &SD_BUS_ERROR_MAKE(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
+                                &m);
+                if (r < 0)
+                        return r;
+
+                r = bus_seal_message(bus, m);
+                if (r < 0)
+                        return r;
+
+                if (c->timeout != 0)
+                        prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+
+                hashmap_remove(bus->reply_callbacks, &c->serial);
+
+                bus->current = m;
+                bus->iteration_counter++;
+
+                r = c->callback(bus, m, c->userdata);
+                free(c);
+
+                if (r >= 0)
+                        r = 1;
+
+                goto finish;
+        }
+
+        /* Then, synthesize a Disconnected message */
+        r = sd_bus_message_new_signal(
+                        bus,
+                        "/org/freedesktop/DBus/Local",
+                        "org.freedesktop.DBus.Local",
+                        "Disconnected",
+                        &m);
+        if (r < 0)
+                return r;
+
+        r = bus_seal_message(bus, m);
+        if (r < 0)
+                return r;
+
+        sd_bus_close(bus);
+
+        bus->current = m;
+        bus->iteration_counter++;
+
+        r = process_filter(bus, m);
+        if (r != 0)
+                goto finish;
+
+        r = process_match(bus, m);
+        if (r != 0)
+                goto finish;
+
+        if (ret) {
+                *ret = m;
+                m = NULL;
+        }
+
+        r = 1;
+
+finish:
+        bus->current = NULL;
+        return r;
+}
+
 _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
         BUS_DONT_DESTROY(bus);
         int r;
@@ -2091,7 +2205,7 @@ _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         /* We don't allow recursively invoking sd_bus_process(). */
-        assert_return(!bus->processing, -EBUSY);
+        assert_return(!bus->current, -EBUSY);
 
         switch (bus->state) {
 
@@ -2101,29 +2215,43 @@ _public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
 
         case BUS_OPENING:
                 r = bus_socket_process_opening(bus);
-                if (r < 0)
+                if (r == -ECONNRESET || r == -EPIPE) {
+                        bus_enter_closing(bus);
+                        r = 1;
+                } else if (r < 0)
                         return r;
                 if (ret)
                         *ret = NULL;
                 return r;
 
         case BUS_AUTHENTICATING:
-
                 r = bus_socket_process_authenticating(bus);
-                if (r < 0)
+                if (r == -ECONNRESET || r == -EPIPE) {
+                        bus_enter_closing(bus);
+                        r = 1;
+                } else if (r < 0)
                         return r;
+
                 if (ret)
                         *ret = NULL;
+
                 return r;
 
         case BUS_RUNNING:
         case BUS_HELLO:
-
-                bus->processing = true;
                 r = process_running(bus, ret);
-                bus->processing = false;
+                if (r == -ECONNRESET || r == -EPIPE) {
+                        bus_enter_closing(bus);
+                        r = 1;
+
+                        if (ret)
+                                *ret = NULL;
+                }
 
                 return r;
+
+        case BUS_CLOSING:
+                return process_closing(bus, ret);
         }
 
         assert_not_reached("Unknown state");
@@ -2136,6 +2264,10 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
         usec_t m = (usec_t) -1;
 
         assert(bus);
+
+        if (bus->state == BUS_CLOSING)
+                return 1;
+
         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
 
         e = sd_bus_get_events(bus);
@@ -2186,9 +2318,13 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
 _public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
 
         assert_return(bus, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
+        if (bus->state == BUS_CLOSING)
+                return 0;
+
+        assert_return(BUS_IS_OPEN(bus->state) , -ENOTCONN);
+
         if (bus->rqueue_size > 0)
                 return 0;
 
@@ -2199,9 +2335,13 @@ _public_ int sd_bus_flush(sd_bus *bus) {
         int r;
 
         assert_return(bus, -EINVAL);
-        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
+        if (bus->state == BUS_CLOSING)
+                return 0;
+
+        assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
+
         r = bus_ensure_running(bus);
         if (r < 0)
                 return r;
index d01e82d94560695764f41a356fb5eef85ebd9681..5cb3bccc5aecc08e392f9b6221cbc19369b36a43 100644 (file)
@@ -51,7 +51,7 @@ struct sd_event_source {
 
         sd_event *event;
         void *userdata;
-        sd_prepare_handler_t prepare;
+        sd_event_handler_t prepare;
 
         EventSourceType type:4;
         int enabled:3;
@@ -65,34 +65,34 @@ struct sd_event_source {
 
         union {
                 struct {
-                        sd_io_handler_t callback;
+                        sd_event_io_handler_t callback;
                         int fd;
                         uint32_t events;
                         uint32_t revents;
                         bool registered:1;
                 } io;
                 struct {
-                        sd_time_handler_t callback;
+                        sd_event_time_handler_t callback;
                         usec_t next, accuracy;
                         unsigned earliest_index;
                         unsigned latest_index;
                 } time;
                 struct {
-                        sd_signal_handler_t callback;
+                        sd_event_signal_handler_t callback;
                         struct signalfd_siginfo siginfo;
                         int sig;
                 } signal;
                 struct {
-                        sd_child_handler_t callback;
+                        sd_event_child_handler_t callback;
                         siginfo_t siginfo;
                         pid_t pid;
                         int options;
                 } child;
                 struct {
-                        sd_defer_handler_t callback;
+                        sd_event_handler_t callback;
                 } defer;
                 struct {
-                        sd_quit_handler_t callback;
+                        sd_event_handler_t callback;
                         unsigned prioq_index;
                 } quit;
         };
@@ -567,7 +567,7 @@ _public_ int sd_event_add_io(
                 sd_event *e,
                 int fd,
                 uint32_t events,
-                sd_io_handler_t callback,
+                sd_event_io_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -655,7 +655,7 @@ static int event_add_time_internal(
                 Prioq **latest,
                 uint64_t usec,
                 uint64_t accuracy,
-                sd_time_handler_t callback,
+                sd_event_time_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -722,7 +722,7 @@ fail:
 _public_ int sd_event_add_monotonic(sd_event *e,
                                     uint64_t usec,
                                     uint64_t accuracy,
-                                    sd_time_handler_t callback,
+                                    sd_event_time_handler_t callback,
                                     void *userdata,
                                     sd_event_source **ret) {
 
@@ -732,7 +732,7 @@ _public_ int sd_event_add_monotonic(sd_event *e,
 _public_ int sd_event_add_realtime(sd_event *e,
                                    uint64_t usec,
                                    uint64_t accuracy,
-                                   sd_time_handler_t callback,
+                                   sd_event_time_handler_t callback,
                                    void *userdata,
                                    sd_event_source **ret) {
 
@@ -774,7 +774,7 @@ static int event_update_signal_fd(sd_event *e) {
 _public_ int sd_event_add_signal(
                 sd_event *e,
                 int sig,
-                sd_signal_handler_t callback,
+                sd_event_signal_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -824,7 +824,7 @@ _public_ int sd_event_add_child(
                 sd_event *e,
                 pid_t pid,
                 int options,
-                sd_child_handler_t callback,
+                sd_event_child_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -883,7 +883,7 @@ _public_ int sd_event_add_child(
 
 _public_ int sd_event_add_defer(
                 sd_event *e,
-                sd_defer_handler_t callback,
+                sd_event_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -916,7 +916,7 @@ _public_ int sd_event_add_defer(
 
 _public_ int sd_event_add_quit(
                 sd_event *e,
-                sd_quit_handler_t callback,
+                sd_event_handler_t callback,
                 void *userdata,
                 sd_event_source **ret) {
 
@@ -1297,7 +1297,7 @@ _public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) {
         return 0;
 }
 
-_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_prepare_handler_t callback) {
+_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) {
         int r;
 
         assert_return(s, -EINVAL);
index ae41618647c536c2c495e993ea8e0d5397586755..b9865349ac2784c3d2b0d6093cc82bdbd942cd41 100644 (file)
@@ -52,7 +52,9 @@ int main(int argc, char *argv[]) {
 
         assert_se(introspect_begin(&intro) >= 0);
 
-        assert_se(introspect_write_interface(&intro, "org.foo", vtable) >= 0);
+        fprintf(intro.f, " <interface name=\"org.foo\">\n");
+        assert_se(introspect_write_interface(&intro, vtable) >= 0);
+        fputs(" </interface>\n", intro.f);
 
         fflush(intro.f);
         fputs(intro.introspection, stdout);
index cbf5e1a0faa481eef2fe678e920d44857aa7978b..b7606d7708dca920cb2fdecde029f2e85647bbe7 100644 (file)
@@ -28,7 +28,7 @@
 #endif
 
 #ifdef HAVE_DBUS
-#include <dbus.h>
+#include <dbus/dbus.h>
 #endif
 
 #include "log.h"
index 0f25e2306fffdcccc5ada046cf948488c1994a9c..7e6f6109dc878a3f748945de0ded51379b4aa513 100644 (file)
@@ -40,6 +40,7 @@
 #include "bus-util.h"
 #include "bus-error.h"
 #include "logind.h"
+#include "bus-errors.h"
 
 static int property_get_idle_hint(
                 sd_bus *bus,
@@ -184,7 +185,7 @@ static int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void
 
         p = session_bus_path(session);
         if (!p)
-                return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
+                return sd_bus_reply_method_errno(bus, message, ENOMEM, NULL);
 
         return sd_bus_reply_method_return(bus, message, "o", p);
 }
index 26cce8d7fcdd3defe57729421a6aa7de340a78e3..1b6f1362b3fbfb34dc2dee5731cfb570297fd907 100644 (file)
@@ -304,7 +304,7 @@ int inhibitor_create_fifo(Inhibitor *i) {
                 if (r < 0)
                         return r;
 
-                r = sd_event_source_set_priority(i->event_source, SD_PRIORITY_IDLE);
+                r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE);
                 if (r < 0)
                         return r;
         }
index c59dfd93388bc4b9d908cd0210ec20717513bd5d..53141a892eb64fa9de8703658e6de16bc4603720 100644 (file)
@@ -25,6 +25,7 @@
 #include "util.h"
 #include "bus-util.h"
 #include "strv.h"
+#include "bus-errors.h"
 #include "logind.h"
 #include "logind-seat.h"
 
index fa9c0039f4748d3131e4a2d08791d57b1c6f2e1b..4995391443fe13ec6cf2b41ca8d95145ec70d74a 100644 (file)
@@ -25,6 +25,7 @@
 #include "util.h"
 #include "strv.h"
 #include "bus-util.h"
+#include "bus-errors.h"
 
 #include "logind.h"
 #include "logind-session.h"
index 65cc6f30947b674466390f4ca22fc2c481080d90..d3433731e56c48a57e9ade7e72be24351f668674 100644 (file)
@@ -864,7 +864,7 @@ int session_create_fifo(Session *s) {
                 if (r < 0)
                         return r;
 
-                r = sd_event_source_set_priority(s->fifo_event_source, SD_PRIORITY_IDLE);
+                r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_IDLE);
                 if (r < 0)
                         return r;
         }
index 1d16eaa7b8f801201ae9884b85a38983c5d0812c..47b306b6194df13e42c0ce097edc28f6982a8aeb 100644 (file)
@@ -958,7 +958,7 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us
                         return r;
                 }
 
-                r = sd_event_source_set_priority(m->idle_action_event_source, SD_PRIORITY_IDLE+10);
+                r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10);
                 if (r < 0) {
                         log_error("Failed to set idle event source priority: %s", strerror(-r));
                         return r;
index 2b25f075253fa0d9801f7599380e603707f65c2c..be0dbe00979093c1892a2aeb1a43312543b40085 100644 (file)
@@ -36,6 +36,7 @@
 #include "utf8.h"
 #include "unit-name.h"
 #include "bus-util.h"
+#include "bus-errors.h"
 #include "time-util.h"
 #include "cgroup-util.h"
 #include "machined.h"
diff --git a/src/shared/bus-errors.h b/src/shared/bus-errors.h
new file mode 100644 (file)
index 0000000..e9ab731
--- /dev/null
@@ -0,0 +1,57 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 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/>.
+***/
+
+#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
+#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID"
+#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"
+#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob"
+#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed"
+#define BUS_ERROR_ALREADY_SUBSCRIBED "org.freedesktop.systemd1.AlreadySubscribed"
+#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency"
+#define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting"
+#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic"
+#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
+#define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked"
+#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
+#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
+#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown"
+
+#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
+#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
+#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
+
+#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
+#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
+#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser"
+#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID"
+#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat"
+#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat"
+#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl"
+#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken"
+#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken"
+#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
+#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
+
+#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess"
diff --git a/src/shared/dbus-common.c b/src/shared/dbus-common.c
deleted file mode 100644 (file)
index 3ba2d87..0000000
+++ /dev/null
@@ -1,1430 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2010 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 <assert.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <dbus/dbus.h>
-#include <string.h>
-#include <sys/epoll.h>
-
-#include "log.h"
-#include "dbus-common.h"
-#include "util.h"
-#include "missing.h"
-#include "def.h"
-#include "strv.h"
-
-int bus_check_peercred(DBusConnection *c) {
-        int fd;
-        struct ucred ucred;
-        socklen_t l;
-
-        assert(c);
-
-        assert_se(dbus_connection_get_unix_fd(c, &fd));
-
-        l = sizeof(struct ucred);
-        if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
-                log_error("SO_PEERCRED failed: %m");
-                return -errno;
-        }
-
-        if (l != sizeof(struct ucred)) {
-                log_error("SO_PEERCRED returned wrong size.");
-                return -E2BIG;
-        }
-
-        if (ucred.uid != 0 && ucred.uid != geteuid())
-                return -EPERM;
-
-        return 1;
-}
-
-static int sync_auth(DBusConnection *bus, DBusError *error) {
-        usec_t begin, tstamp;
-
-        assert(bus);
-
-        /* This complexity should probably move into D-Bus itself:
-         *
-         * https://bugs.freedesktop.org/show_bug.cgi?id=35189 */
-
-        begin = tstamp = now(CLOCK_MONOTONIC);
-        for (;;) {
-
-                if (tstamp > begin + DEFAULT_TIMEOUT_USEC)
-                        break;
-
-                if (dbus_connection_get_is_authenticated(bus))
-                        break;
-
-                if (!dbus_connection_read_write_dispatch(bus, ((begin + DEFAULT_TIMEOUT_USEC - tstamp) + USEC_PER_MSEC - 1) / USEC_PER_MSEC))
-                        break;
-
-                tstamp = now(CLOCK_MONOTONIC);
-        }
-
-        if (!dbus_connection_get_is_connected(bus)) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_SERVER, "Connection terminated during authentication.");
-                return -ECONNREFUSED;
-        }
-
-        if (!dbus_connection_get_is_authenticated(bus)) {
-                dbus_set_error_const(error, DBUS_ERROR_TIMEOUT, "Failed to authenticate in time.");
-                return -EACCES;
-        }
-
-        return 0;
-}
-
-int bus_connect(DBusBusType t, DBusConnection **_bus, bool *_private, DBusError *error) {
-        DBusConnection *bus = NULL;
-        int r;
-        bool private = true;
-
-        assert(_bus);
-
-        if (geteuid() == 0 && t == DBUS_BUS_SYSTEM) {
-                /* If we are root, then let's talk directly to the
-                 * system instance, instead of going via the bus */
-
-                bus = dbus_connection_open_private("unix:path=/run/systemd/private", error);
-                if (!bus)
-                        return -EIO;
-
-        } else {
-                if (t == DBUS_BUS_SESSION) {
-                        const char *e;
-
-                        /* If we are supposed to talk to the instance,
-                         * try via XDG_RUNTIME_DIR first, then
-                         * fallback to normal bus access */
-
-                        e = secure_getenv("XDG_RUNTIME_DIR");
-                        if (e) {
-                                char *p;
-
-                                if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
-                                        return -ENOMEM;
-
-                                bus = dbus_connection_open_private(p, NULL);
-                                free(p);
-                        }
-                }
-
-                if (!bus) {
-                        bus = dbus_bus_get_private(t, error);
-                        if (!bus)
-                                return -EIO;
-
-                        private = false;
-                }
-        }
-
-        dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
-        if (private) {
-                if (bus_check_peercred(bus) < 0) {
-                        dbus_connection_close(bus);
-                        dbus_connection_unref(bus);
-
-                        dbus_set_error_const(error, DBUS_ERROR_ACCESS_DENIED, "Failed to verify owner of bus.");
-                        return -EACCES;
-                }
-        }
-
-        r = sync_auth(bus, error);
-        if (r < 0) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        if (_private)
-                *_private = private;
-
-        *_bus = bus;
-        return 0;
-}
-
-int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error) {
-        DBusConnection *bus;
-        char *p = NULL;
-        int r;
-
-        assert(_bus);
-        assert(user || host);
-
-        if (user && host)
-                asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s%%40%s,argv3=systemd-stdio-bridge", user, host);
-        else if (user)
-                asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s%%40localhost,argv3=systemd-stdio-bridge", user);
-        else if (host)
-                asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host);
-
-        if (!p) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return -ENOMEM;
-        }
-
-        bus = dbus_connection_open_private(p, error);
-        free(p);
-
-        if (!bus)
-                return -EIO;
-
-        dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
-        if ((r = sync_auth(bus, error)) < 0) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        if (!dbus_bus_register(bus, error)) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        *_bus = bus;
-        return 0;
-}
-
-int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error) {
-        DBusConnection *bus;
-        int r;
-
-        assert(_bus);
-
-        /* Don't bother with PolicyKit if we are root */
-        if (geteuid() == 0)
-                return bus_connect(DBUS_BUS_SYSTEM, _bus, NULL, error);
-
-        bus = dbus_connection_open_private("unixexec:path=pkexec,argv1=" SYSTEMD_STDIO_BRIDGE_BINARY_PATH, error);
-        if (!bus)
-                return -EIO;
-
-        dbus_connection_set_exit_on_disconnect(bus, FALSE);
-
-        r = sync_auth(bus, error);
-        if (r < 0) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        if (!dbus_bus_register(bus, error)) {
-                dbus_connection_close(bus);
-                dbus_connection_unref(bus);
-                return r;
-        }
-
-        *_bus = bus;
-        return 0;
-}
-
-const char *bus_error_message(const DBusError *error) {
-        if (!error)
-                return NULL;
-
-        /* Sometimes the D-Bus server is a little bit too verbose with
-         * its error messages, so let's override them here */
-        if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED))
-                return "Access denied";
-
-        return error->message;
-}
-
-const char *bus_error(const DBusError *error, int err) {
-        if (error && dbus_error_is_set(error))
-                return bus_error_message(error);
-
-        return strerror(err < 0 ? -err : err);
-}
-
-DBusHandlerResult bus_default_message_handler(
-                DBusConnection *c,
-                DBusMessage *message,
-                const char *introspection,
-                const char *interfaces,
-                const BusBoundProperties *bound_properties) {
-
-        DBusError error;
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        int r;
-
-        assert(c);
-        assert(message);
-
-        dbus_error_init(&error);
-
-        if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") && introspection) {
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && bound_properties) {
-                const char *interface, *property;
-                const BusBoundProperties *bp;
-                const BusProperty *p;
-                void *data;
-                DBusMessageIter iter, sub;
-
-                if (!dbus_message_get_args(
-                            message,
-                            &error,
-                            DBUS_TYPE_STRING, &interface,
-                            DBUS_TYPE_STRING, &property,
-                            DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-
-                for (bp = bound_properties; bp->interface; bp++) {
-                        if (!streq(bp->interface, interface))
-                                continue;
-
-                        for (p = bp->properties; p->property; p++)
-                                if (streq(p->property, property))
-                                        goto get_prop;
-                }
-
-                /* no match */
-                if (!nulstr_contains(interfaces, interface))
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
-                else
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
-
-                return bus_send_error_reply(c, message, &error, -EINVAL);
-
-get_prop:
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                dbus_message_iter_init_append(reply, &iter);
-
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub))
-                        goto oom;
-
-                data = (char*)bp->base + p->offset;
-                if (p->indirect)
-                        data = *(void**)data;
-
-                r = p->append(&sub, property, data);
-                if (r == -ENOMEM)
-                        goto oom;
-                if (r < 0)
-                        return bus_send_error_reply(c, message, NULL, r);
-
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && bound_properties) {
-                const char *interface;
-                const BusBoundProperties *bp;
-                const BusProperty *p;
-                DBusMessageIter iter, sub, sub2, sub3;
-
-                if (!dbus_message_get_args(
-                            message,
-                            &error,
-                            DBUS_TYPE_STRING, &interface,
-                            DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-
-                if (interface[0] && !nulstr_contains(interfaces, interface)) {
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-                }
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                dbus_message_iter_init_append(reply, &iter);
-
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub))
-                        goto oom;
-
-                for (bp = bound_properties; bp->interface; bp++) {
-                        if (interface[0] && !streq(bp->interface, interface))
-                                continue;
-
-                        for (p = bp->properties; p->property; p++) {
-                                void *data;
-
-                                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) ||
-                                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) ||
-                                    !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3))
-                                        goto oom;
-
-                                data = (char*)bp->base + p->offset;
-                                if (p->indirect)
-                                        data = *(void**)data;
-                                r = p->append(&sub3, p->property, data);
-                                if (r == -ENOMEM)
-                                        goto oom;
-                                if (r < 0)
-                                        return bus_send_error_reply(c, message, NULL, r);
-
-                                if (!dbus_message_iter_close_container(&sub2, &sub3) ||
-                                    !dbus_message_iter_close_container(&sub, &sub2))
-                                        goto oom;
-                        }
-                }
-
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && bound_properties) {
-                const char *interface, *property;
-                DBusMessageIter iter;
-                const BusBoundProperties *bp;
-                const BusProperty *p;
-                DBusMessageIter sub;
-                char *sig;
-                void *data;
-                DBusMessage *changed;
-
-                if (!dbus_message_iter_init(message, &iter) ||
-                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-                        return bus_send_error_reply(c, message, NULL, -EINVAL);
-
-                dbus_message_iter_get_basic(&iter, &interface);
-
-                if (!dbus_message_iter_next(&iter) ||
-                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-                        return bus_send_error_reply(c, message, NULL, -EINVAL);
-
-                dbus_message_iter_get_basic(&iter, &property);
-
-                if (!dbus_message_iter_next(&iter) ||
-                    dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
-                    dbus_message_iter_has_next(&iter))
-                        return bus_send_error_reply(c, message, NULL, -EINVAL);
-
-                for (bp = bound_properties; bp->interface; bp++) {
-                        if (!streq(bp->interface, interface))
-                                continue;
-
-                        for (p = bp->properties; p->property; p++)
-                                if (streq(p->property, property))
-                                        goto set_prop;
-                }
-
-                /* no match */
-                if (!nulstr_contains(interfaces, interface))
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
-                else
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
-
-                return bus_send_error_reply(c, message, &error, -EINVAL);
-
-set_prop:
-                if (!p->set) {
-                        dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-                }
-
-                dbus_message_iter_recurse(&iter, &sub);
-
-                sig = dbus_message_iter_get_signature(&sub);
-                if (!sig)
-                        goto oom;
-
-                if (!streq(sig, p->signature)) {
-                        dbus_free(sig);
-                        return bus_send_error_reply(c, message, NULL, -EINVAL);
-                }
-                dbus_free(sig);
-
-                data = (uint8_t*) bp->base + p->offset;
-                if (p->indirect)
-                        data = *(void**)data;
-
-                r = p->set(&sub, property, data);
-                if (r == -ENOMEM)
-                        goto oom;
-                else if (r < 0)
-                        return bus_send_error_reply(c, message, NULL, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                /* Send out a signal about this, but it doesn't really
-                 * matter if this fails, so eat all errors */
-                changed = bus_properties_changed_one_new(
-                                dbus_message_get_path(message),
-                                interface,
-                                property);
-                if (changed) {
-                        dbus_connection_send(c, changed, NULL);
-                        dbus_message_unref(changed);
-                }
-
-
-        } else {
-                const char *interface = dbus_message_get_interface(message);
-
-                if (!interface || !nulstr_contains(interfaces, interface)) {
-                        dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
-                        return bus_send_error_reply(c, message, &error, -EINVAL);
-                }
-        }
-
-        if (reply) {
-                if (!bus_maybe_send_reply(c, message, reply))
-                        goto oom;
-
-                return DBUS_HANDLER_RESULT_HANDLED;
-        }
-
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-oom:
-        dbus_error_free(&error);
-
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-int bus_property_append_string(DBusMessageIter *i, const char *property, void *data) {
-        const char *t = data;
-
-        assert(i);
-        assert(property);
-
-        if (!t)
-                t = "";
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data) {
-        char **t = data;
-
-        assert(i);
-        assert(property);
-
-        return bus_append_strv_iter(i, t);
-}
-
-int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data) {
-        bool *b = data;
-        dbus_bool_t db;
-
-        assert(i);
-        assert(property);
-        assert(b);
-
-        db = *b;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data) {
-        int *b = data;
-        dbus_bool_t db;
-
-        assert(i);
-        assert(property);
-        assert(b);
-
-        db = *b > 0;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data) {
-        assert(i);
-        assert(property);
-        assert(data);
-
-        /* Let's ensure that usec_t is actually 64bit, and hence this
-         * function can be used for usec_t */
-        assert_cc(sizeof(uint64_t) == sizeof(usec_t));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, data))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data) {
-        assert(i);
-        assert(property);
-        assert(data);
-
-        /* Let's ensure that pid_t, mode_t, uid_t, gid_t are actually
-         * 32bit, and hence this function can be used for
-         * pid_t/mode_t/uid_t/gid_t */
-        assert_cc(sizeof(uint32_t) == sizeof(pid_t));
-        assert_cc(sizeof(uint32_t) == sizeof(mode_t));
-        assert_cc(sizeof(uint32_t) == sizeof(unsigned));
-        assert_cc(sizeof(uint32_t) == sizeof(uid_t));
-        assert_cc(sizeof(uint32_t) == sizeof(gid_t));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, data))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data) {
-        assert(i);
-        assert(property);
-        assert(data);
-
-        assert_cc(sizeof(int32_t) == sizeof(int));
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, data))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_size(DBusMessageIter *i, const char *property, void *data) {
-        uint64_t u;
-
-        assert(i);
-        assert(property);
-        assert(data);
-
-        u = (uint64_t) *(size_t*) data;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data) {
-        uint64_t u;
-
-        assert(i);
-        assert(property);
-        assert(data);
-
-        u = (uint64_t) *(unsigned long*) data;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_append_long(DBusMessageIter *i, const char *property, void *data) {
-        int64_t l;
-
-        assert(i);
-        assert(property);
-        assert(data);
-
-        l = (int64_t) *(long*) data;
-
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT64, &l))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data) {
-        uint64_t *t = data;
-
-        assert(i);
-        assert(property);
-
-        dbus_message_iter_get_basic(i, t);
-        return 0;
-}
-
-const char *bus_errno_to_dbus(int error) {
-
-        switch(error) {
-
-        case -EINVAL:
-                return DBUS_ERROR_INVALID_ARGS;
-
-        case -ENOMEM:
-                return DBUS_ERROR_NO_MEMORY;
-
-        case -EPERM:
-        case -EACCES:
-                return DBUS_ERROR_ACCESS_DENIED;
-
-        case -ESRCH:
-                return DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN;
-
-        case -ENOENT:
-                return DBUS_ERROR_FILE_NOT_FOUND;
-
-        case -EEXIST:
-                return DBUS_ERROR_FILE_EXISTS;
-
-        case -ETIMEDOUT:
-        case -ETIME:
-                return DBUS_ERROR_TIMEOUT;
-
-        case -EIO:
-                return DBUS_ERROR_IO_ERROR;
-
-        case -ENETRESET:
-        case -ECONNABORTED:
-        case -ECONNRESET:
-                return DBUS_ERROR_DISCONNECTED;
-        }
-
-        return DBUS_ERROR_FAILED;
-}
-
-dbus_bool_t bus_maybe_send_reply (DBusConnection   *c,
-                                  DBusMessage *message,
-                                  DBusMessage *reply)
-{
-        /* Some parts of systemd "reply" to signals, which of course
-         * have the no-reply flag set.  We will be defensive here and
-         * still send out a reply if we're passed a signal.
-         */
-        if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL &&
-            dbus_message_get_no_reply(message))
-                return TRUE;
-        return dbus_connection_send(c, reply, NULL);
-}
-
-DBusHandlerResult bus_send_error_reply(DBusConnection *c, DBusMessage *message, DBusError *berror, int error) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        const char *name, *text;
-
-        if (berror && dbus_error_is_set(berror)) {
-                name = berror->name;
-                text = berror->message;
-        } else {
-                name = bus_errno_to_dbus(error);
-                text = strerror(-error);
-        }
-
-        reply = dbus_message_new_error(message, name, text);
-        if (!reply)
-                goto oom;
-
-        if (!bus_maybe_send_reply(c, message, reply))
-                goto oom;
-
-        if (berror)
-                dbus_error_free(berror);
-
-        return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
-        if (reply)
-                dbus_message_unref(reply);
-
-        if (berror)
-                dbus_error_free(berror);
-
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
-}
-
-DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties) {
-        DBusMessage *m;
-        DBusMessageIter iter, sub;
-        const char *i;
-
-        assert(interface);
-        assert(properties);
-
-        m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
-        if (!m)
-                goto oom;
-
-        dbus_message_iter_init_append(m, &iter);
-
-        /* We won't send any property values, since they might be
-         * large and sometimes not cheap to generated */
-
-        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
-            !dbus_message_iter_close_container(&iter, &sub) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
-                goto oom;
-
-        NULSTR_FOREACH(i, properties)
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &i))
-                        goto oom;
-
-        if (!dbus_message_iter_close_container(&iter, &sub))
-                goto oom;
-
-        return m;
-
-oom:
-        if (m)
-                dbus_message_unref(m);
-
-        return NULL;
-}
-
-DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property) {
-        DBusMessage *m;
-        DBusMessageIter iter, sub;
-
-        assert(interface);
-        assert(property);
-
-        m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
-        if (!m)
-                goto oom;
-
-        dbus_message_iter_init_append(m, &iter);
-
-        /* We won't send any property values, since they might be
-         * large and sometimes not cheap to generated */
-
-        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
-            !dbus_message_iter_close_container(&iter, &sub) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
-                goto oom;
-
-        if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &property))
-                goto oom;
-
-        if (!dbus_message_iter_close_container(&iter, &sub))
-                goto oom;
-
-        return m;
-
-oom:
-        if (m)
-                dbus_message_unref(m);
-
-        return NULL;
-}
-
-uint32_t bus_flags_to_events(DBusWatch *bus_watch) {
-        unsigned flags;
-        uint32_t events = 0;
-
-        assert(bus_watch);
-
-        /* no watch flags for disabled watches */
-        if (!dbus_watch_get_enabled(bus_watch))
-                return 0;
-
-        flags = dbus_watch_get_flags(bus_watch);
-
-        if (flags & DBUS_WATCH_READABLE)
-                events |= EPOLLIN;
-        if (flags & DBUS_WATCH_WRITABLE)
-                events |= EPOLLOUT;
-
-        return events | EPOLLHUP | EPOLLERR;
-}
-
-unsigned bus_events_to_flags(uint32_t events) {
-        unsigned flags = 0;
-
-        if (events & EPOLLIN)
-                flags |= DBUS_WATCH_READABLE;
-        if (events & EPOLLOUT)
-                flags |= DBUS_WATCH_WRITABLE;
-        if (events & EPOLLHUP)
-                flags |= DBUS_WATCH_HANGUP;
-        if (events & EPOLLERR)
-                flags |= DBUS_WATCH_ERROR;
-
-        return flags;
-}
-
-int bus_parse_strv(DBusMessage *m, char ***_l) {
-        DBusMessageIter iter;
-
-        assert(m);
-        assert(_l);
-
-        if (!dbus_message_iter_init(m, &iter))
-                return -EINVAL;
-
-        return bus_parse_strv_iter(&iter, _l);
-}
-
-int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l) {
-        DBusMessageIter sub;
-        unsigned n = 0, i = 0;
-        char **l;
-
-        assert(iter);
-        assert(_l);
-
-        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
-            dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRING)
-            return -EINVAL;
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                n++;
-                dbus_message_iter_next(&sub);
-        }
-
-        l = new(char*, n+1);
-        if (!l)
-                return -ENOMEM;
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                const char *s;
-
-                assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
-                dbus_message_iter_get_basic(&sub, &s);
-
-                if (!(l[i++] = strdup(s))) {
-                        strv_free(l);
-                        return -ENOMEM;
-                }
-
-                dbus_message_iter_next(&sub);
-        }
-
-        assert(i == n);
-        l[i] = NULL;
-
-        if (_l)
-                *_l = l;
-
-        return 0;
-}
-
-int bus_parse_strv_pairs_iter(DBusMessageIter *iter, char ***_l) {
-        DBusMessageIter sub, sub2;
-        unsigned n = 0, i = 0;
-        _cleanup_strv_free_ char **l = NULL;
-
-        assert(iter);
-        assert(_l);
-
-        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
-            dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRUCT)
-            return -EINVAL;
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                n++;
-                dbus_message_iter_next(&sub);
-        }
-
-        l = new(char*, n*2+1);
-        if (!l)
-                return -ENOMEM;
-        l[0] = NULL; /* make sure that l is properly terminated at all times */
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                const char *a, *b;
-
-                assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
-
-                dbus_message_iter_recurse(&sub, &sub2);
-
-                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &a, true) < 0 ||
-                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &b, false) < 0)
-                        return -EINVAL;
-
-                l[i] = strdup(a);
-                if (!l[i])
-                        return -ENOMEM;
-                i++;
-
-                l[i] = strdup(b);
-                if (!l[i])
-                        return -ENOMEM;
-                i++;
-
-                dbus_message_iter_next(&sub);
-        }
-
-        assert(i == n*2);
-        l[i] = NULL;
-
-        if (_l) {
-                *_l = l;
-                l = NULL; /* avoid freeing */
-        }
-
-        return 0;
-}
-
-int bus_parse_unit_info(DBusMessageIter *iter, struct unit_info *u) {
-        DBusMessageIter sub;
-
-        assert(iter);
-        assert(u);
-
-        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRUCT)
-                return -EINVAL;
-
-        dbus_message_iter_recurse(iter, &sub);
-
-        if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->id, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->description, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->following, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
-            bus_iter_get_basic_and_next(&sub, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
-                log_error("Failed to parse reply.");
-                return -EIO;
-        }
-
-        return 0;
-}
-
-int bus_append_strv_iter(DBusMessageIter *iter, char **l) {
-        DBusMessageIter sub;
-
-        assert(iter);
-
-        if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "s", &sub))
-                return -ENOMEM;
-
-        STRV_FOREACH(l, l)
-                if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, l))
-                        return -ENOMEM;
-
-        if (!dbus_message_iter_close_container(iter, &sub))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next) {
-
-        assert(iter);
-        assert(data);
-
-        if (dbus_message_iter_get_arg_type(iter) != type)
-                return -EIO;
-
-        dbus_message_iter_get_basic(iter, data);
-
-        if (!dbus_message_iter_next(iter) != !next)
-                return -EIO;
-
-        return 0;
-}
-
-int generic_print_property(const char *name, DBusMessageIter *iter, bool all) {
-        assert(name);
-        assert(iter);
-
-        switch (dbus_message_iter_get_arg_type(iter)) {
-
-        case DBUS_TYPE_STRING: {
-                const char *s;
-                dbus_message_iter_get_basic(iter, &s);
-
-                if (all || !isempty(s))
-                        printf("%s=%s\n", name, s);
-
-                return 1;
-        }
-
-        case DBUS_TYPE_BOOLEAN: {
-                dbus_bool_t b;
-
-                dbus_message_iter_get_basic(iter, &b);
-                printf("%s=%s\n", name, yes_no(b));
-
-                return 1;
-        }
-
-        case DBUS_TYPE_UINT64: {
-                uint64_t u;
-                dbus_message_iter_get_basic(iter, &u);
-
-                /* Yes, heuristics! But we can change this check
-                 * should it turn out to not be sufficient */
-
-                if (endswith(name, "Timestamp")) {
-                        char timestamp[FORMAT_TIMESTAMP_MAX], *t;
-
-                        t = format_timestamp(timestamp, sizeof(timestamp), u);
-                        if (t || all)
-                                printf("%s=%s\n", name, strempty(t));
-
-                } else if (strstr(name, "USec")) {
-                        char timespan[FORMAT_TIMESPAN_MAX];
-
-                        printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
-                } else
-                        printf("%s=%llu\n", name, (unsigned long long) u);
-
-                return 1;
-        }
-
-        case DBUS_TYPE_UINT32: {
-                uint32_t u;
-                dbus_message_iter_get_basic(iter, &u);
-
-                if (strstr(name, "UMask") || strstr(name, "Mode"))
-                        printf("%s=%04o\n", name, u);
-                else
-                        printf("%s=%u\n", name, (unsigned) u);
-
-                return 1;
-        }
-
-        case DBUS_TYPE_INT32: {
-                int32_t i;
-                dbus_message_iter_get_basic(iter, &i);
-
-                printf("%s=%i\n", name, (int) i);
-                return 1;
-        }
-
-        case DBUS_TYPE_DOUBLE: {
-                double d;
-                dbus_message_iter_get_basic(iter, &d);
-
-                printf("%s=%g\n", name, d);
-                return 1;
-        }
-
-        case DBUS_TYPE_ARRAY:
-
-                if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
-                        DBusMessageIter sub;
-                        bool space = false;
-
-                        dbus_message_iter_recurse(iter, &sub);
-                        if (all ||
-                            dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                printf("%s=", name);
-
-                                while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                        const char *s;
-
-                                        assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
-                                        dbus_message_iter_get_basic(&sub, &s);
-                                        printf("%s%s", space ? " " : "", s);
-
-                                        space = true;
-                                        dbus_message_iter_next(&sub);
-                                }
-
-                                puts("");
-                        }
-
-                        return 1;
-
-                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_BYTE) {
-                        DBusMessageIter sub;
-
-                        dbus_message_iter_recurse(iter, &sub);
-                        if (all ||
-                            dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                printf("%s=", name);
-
-                                while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                        uint8_t u;
-
-                                        assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_BYTE);
-                                        dbus_message_iter_get_basic(&sub, &u);
-                                        printf("%02x", u);
-
-                                        dbus_message_iter_next(&sub);
-                                }
-
-                                puts("");
-                        }
-
-                        return 1;
-
-                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_UINT32) {
-                        DBusMessageIter sub;
-
-                        dbus_message_iter_recurse(iter, &sub);
-                        if (all ||
-                            dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                printf("%s=", name);
-
-                                while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                                        uint32_t u;
-
-                                        assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32);
-                                        dbus_message_iter_get_basic(&sub, &u);
-                                        printf("%08x", u);
-
-                                        dbus_message_iter_next(&sub);
-                                }
-
-                                puts("");
-                        }
-
-                        return 1;
-                }
-
-                break;
-        }
-
-        return 0;
-}
-
-static void release_name_pending_cb(DBusPendingCall *pending, void *userdata) {
-        DBusMessage *reply;
-        DBusConnection *bus = userdata;
-
-        assert_se(reply = dbus_pending_call_steal_reply(pending));
-        dbus_message_unref(reply);
-
-        dbus_connection_close(bus);
-}
-
-void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) {
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
-        DBusPendingCall *pending = NULL;
-
-        assert(bus);
-
-        /* We unregister the name here, but we continue to process
-         * requests, until we get the response for it, so that all
-         * requests are guaranteed to be processed. */
-
-        m = dbus_message_new_method_call(
-                        DBUS_SERVICE_DBUS,
-                        DBUS_PATH_DBUS,
-                        DBUS_INTERFACE_DBUS,
-                        "ReleaseName");
-        if (!m)
-                goto oom;
-
-        if (!dbus_message_append_args(
-                            m,
-                            DBUS_TYPE_STRING,
-                            &name,
-                            DBUS_TYPE_INVALID))
-                goto oom;
-
-        if (!dbus_connection_send_with_reply(bus, m, &pending, -1))
-                goto oom;
-
-        if (!dbus_pending_call_set_notify(pending, release_name_pending_cb, bus, NULL))
-                goto oom;
-
-        dbus_pending_call_unref(pending);
-
-        return;
-
-oom:
-        log_oom();
-
-        if (pending) {
-                dbus_pending_call_cancel(pending);
-                dbus_pending_call_unref(pending);
-        }
-}
-
-DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata) {
-        usec_t *remain_until = userdata;
-
-        assert(bus);
-        assert(m);
-        assert(remain_until);
-
-        /* Every time we get a new message we reset out timeout */
-        *remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
-
-        if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected"))
-                dbus_connection_close(bus);
-
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-/* This mimics dbus_bus_get_unix_user() */
-pid_t bus_get_unix_process_id(
-                DBusConnection *connection,
-                const char *name,
-                DBusError *error) {
-
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
-        uint32_t pid = 0;
-
-        m = dbus_message_new_method_call(
-                        DBUS_SERVICE_DBUS,
-                        DBUS_PATH_DBUS,
-                        DBUS_INTERFACE_DBUS,
-                        "GetConnectionUnixProcessID");
-        if (!m) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return 0;
-        }
-
-        if (!dbus_message_append_args(
-                            m,
-                            DBUS_TYPE_STRING, &name,
-                            DBUS_TYPE_INVALID)) {
-                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
-                return 0;
-        }
-
-        reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
-        if (!reply)
-                return 0;
-
-        if (dbus_set_error_from_message(error, reply))
-                return 0;
-
-        if (!dbus_message_get_args(
-                            reply, error,
-                            DBUS_TYPE_UINT32, &pid,
-                            DBUS_TYPE_INVALID))
-                return 0;
-
-        return (pid_t) pid;
-}
-
-bool bus_error_is_no_service(const DBusError *error) {
-        assert(error);
-
-        if (!dbus_error_is_set(error))
-                return false;
-
-        if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
-                return true;
-
-        if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
-                return true;
-
-        return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
-}
-
-int bus_method_call_with_reply(
-                DBusConnection *bus,
-                const char *destination,
-                const char *path,
-                const char *interface,
-                const char *method,
-                DBusMessage **return_reply,
-                DBusError *return_error,
-                int first_arg_type, ...) {
-
-        DBusError error;
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
-        DBusMessage *reply;
-        va_list ap;
-        int r = 0;
-
-        dbus_error_init(&error);
-        assert(bus);
-
-        m = dbus_message_new_method_call(destination, path, interface, method);
-        if (!m) {
-                r = log_oom();
-                goto finish;
-        }
-
-        va_start(ap, first_arg_type);
-        if (!dbus_message_append_args_valist(m, first_arg_type, ap)) {
-                va_end(ap);
-                r = log_oom();
-                goto finish;
-        }
-        va_end(ap);
-
-        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
-        if (!reply) {
-                if (!return_error)
-                        log_error("Failed to issue method call: %s", bus_error_message(&error));
-
-                if (bus_error_is_no_service(&error))
-                        r = -ENOENT;
-                else if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED))
-                        r = -EACCES;
-                else if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY))
-                        r = -ETIMEDOUT;
-                else if (dbus_error_has_name(&error, DBUS_ERROR_DISCONNECTED))
-                        r = -ECONNRESET;
-                else
-                        r = -EIO;
-                goto finish;
-        }
-
-        if (return_reply)
-                *return_reply = reply;
-        else
-                dbus_message_unref(reply);
-
-finish:
-        if (return_error)
-                *return_error = error;
-        else
-                dbus_error_free(&error);
-
-        return r;
-}
-
-void bus_message_unrefp(DBusMessage **reply) {
-        if (!reply)
-                return;
-
-        if (!*reply)
-                return;
-
-        dbus_message_unref(*reply);
-}
-
-const char *bus_message_get_sender_with_fallback(DBusMessage *m) {
-        const char *s;
-
-        assert(m);
-
-        s = dbus_message_get_sender(m);
-        if (s)
-                return s;
-
-        /* When the message came in from a direct connection the
-         * message will have no sender. We fix that here. */
-
-        return ":no-sender";
-}
diff --git a/src/shared/dbus-common.h b/src/shared/dbus-common.h
deleted file mode 100644 (file)
index 9752f08..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
-  This file is part of systemd.
-
-  Copyright 2010 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 <dbus/dbus.h>
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include "macro.h"
-
-#ifndef DBUS_ERROR_UNKNOWN_OBJECT
-#define DBUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject"
-#endif
-
-#ifndef DBUS_ERROR_UNKNOWN_INTERFACE
-#define DBUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface"
-#endif
-
-#ifndef DBUS_ERROR_UNKNOWN_PROPERTY
-#define DBUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty"
-#endif
-
-#ifndef DBUS_ERROR_PROPERTY_READ_ONLY
-#define DBUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly"
-#endif
-
-#define BUS_PROPERTIES_INTERFACE                                        \
-        " <interface name=\"org.freedesktop.DBus.Properties\">\n"       \
-        "  <method name=\"Get\">\n"                                     \
-        "   <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"    \
-        "   <arg name=\"property\" direction=\"in\" type=\"s\"/>\n"     \
-        "   <arg name=\"value\" direction=\"out\" type=\"v\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetAll\">\n"                                  \
-        "   <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"    \
-        "   <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"Set\">\n"                                     \
-        "   <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n"    \
-        "   <arg name=\"property\" direction=\"in\" type=\"s\"/>\n"     \
-        "   <arg name=\"value\" direction=\"in\" type=\"v\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <signal name=\"PropertiesChanged\">\n"                       \
-        "   <arg type=\"s\" name=\"interface\"/>\n"                     \
-        "   <arg type=\"a{sv}\" name=\"changed_properties\"/>\n"        \
-        "   <arg type=\"as\" name=\"invalidated_properties\"/>\n"       \
-        "  </signal>\n"                                                 \
-        " </interface>\n"
-
-#define BUS_INTROSPECTABLE_INTERFACE                                    \
-        " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"   \
-        "  <method name=\"Introspect\">\n"                              \
-        "   <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        " </interface>\n"
-
-#define BUS_PEER_INTERFACE                                              \
-        "<interface name=\"org.freedesktop.DBus.Peer\">\n"              \
-        " <method name=\"Ping\"/>\n"                                    \
-        " <method name=\"GetMachineId\">\n"                             \
-        "  <arg type=\"s\" name=\"machine_uuid\" direction=\"out\"/>\n" \
-        " </method>\n"                                                  \
-        "</interface>\n"
-
-#define BUS_GENERIC_INTERFACES_LIST             \
-        "org.freedesktop.DBus.Properties\0"     \
-        "org.freedesktop.DBus.Introspectable\0" \
-        "org.freedesktop.DBus.Peer\0"
-
-int bus_check_peercred(DBusConnection *c);
-
-int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private_bus, DBusError *error);
-
-int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error);
-int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error);
-
-const char *bus_error_message(const DBusError *error);
-const char *bus_error(const DBusError *e, int r);
-
-typedef int (*BusPropertyCallback)(DBusMessageIter *iter, const char *property, void *data);
-typedef int (*BusPropertySetCallback)(DBusMessageIter *iter, const char *property, void *data);
-
-typedef struct BusProperty {
-        const char *property;            /* name of the property */
-        BusPropertyCallback append;      /* Function that is called to serialize this property */
-        const char *signature;
-        const uint16_t offset;           /* Offset from BusBoundProperties::base address to the property data.
-                                          * uint16_t is sufficient, because we have no structs too big.
-                                          * -Werror=overflow will catch it if this does not hold. */
-        bool indirect;                   /* data is indirect, ie. not base+offset, but *(base+offset) */
-        BusPropertySetCallback set;      /* Optional: Function that is called to set this property */
-} BusProperty;
-
-typedef struct BusBoundProperties {
-        const char *interface;           /* interface of the properties */
-        const BusProperty *properties;   /* array of properties, ended by a NULL-filled element */
-        const void *const base;          /* base pointer to which the offset must be added to reach data */
-} BusBoundProperties;
-
-dbus_bool_t bus_maybe_send_reply (DBusConnection   *c,
-                                  DBusMessage *message,
-                                  DBusMessage *reply);
-
-DBusHandlerResult bus_send_error_reply(
-                DBusConnection *c,
-                DBusMessage *message,
-                DBusError *bus_error,
-                int error);
-
-DBusHandlerResult bus_default_message_handler(
-                DBusConnection *c,
-                DBusMessage *message,
-                const char *introspection,
-                const char *interfaces,
-                const BusBoundProperties *bound_properties);
-
-int bus_property_append_string(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_size(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data);
-int bus_property_append_long(DBusMessageIter *i, const char *property, void *data);
-
-#define bus_property_append_int bus_property_append_int32
-#define bus_property_append_pid bus_property_append_uint32
-#define bus_property_append_uid bus_property_append_uint32
-#define bus_property_append_gid bus_property_append_uint32
-#define bus_property_append_mode bus_property_append_uint32
-#define bus_property_append_unsigned bus_property_append_uint32
-#define bus_property_append_usec bus_property_append_uint64
-
-int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data);
-#define bus_property_set_usec bus_property_set_uint64
-
-#define DEFINE_BUS_PROPERTY_APPEND_ENUM(function,name,type)             \
-        int function(DBusMessageIter *i, const char *property, void *data) { \
-                const char *value;                                      \
-                type *field = data;                                     \
-                                                                        \
-                assert(i);                                              \
-                assert(property);                                       \
-                                                                        \
-                value = strempty(name##_to_string(*field));             \
-                                                                        \
-                if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &value)) \
-                        return -ENOMEM;                                 \
-                                                                        \
-                return 0;                                               \
-        }
-
-#define DEFINE_BUS_PROPERTY_SET_ENUM(function,name,type)                \
-        int function(DBusMessageIter *i, const char *property, void *data) { \
-                const char *value;                                      \
-                type f, *field = data;                                  \
-                                                                        \
-                assert(i);                                              \
-                assert(property);                                       \
-                                                                        \
-                dbus_message_iter_get_basic(i, &value);                 \
-                                                                        \
-                f = name##_from_string(value);                          \
-                if (f < 0)                                              \
-                        return f;                                       \
-                                                                        \
-                *field = f;                                             \
-                return 0;                                               \
-        }
-
-const char *bus_errno_to_dbus(int error) _const_;
-
-DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties);
-DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property);
-
-uint32_t bus_flags_to_events(DBusWatch *bus_watch) _pure_;
-unsigned bus_events_to_flags(uint32_t events) _const_;
-
-int bus_parse_strv(DBusMessage *m, char ***_l);
-int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l);
-int bus_parse_strv_pairs_iter(DBusMessageIter *iter, char ***_l);
-
-struct unit_info {
-        const char *id;
-        const char *description;
-        const char *load_state;
-        const char *active_state;
-        const char *sub_state;
-        const char *following;
-        const char *unit_path;
-        uint32_t job_id;
-        const char *job_type;
-        const char *job_path;
-};
-
-int bus_parse_unit_info(DBusMessageIter *iter, struct unit_info *u);
-
-int bus_append_strv_iter(DBusMessageIter *iter, char **l);
-
-int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next);
-
-int generic_print_property(const char *name, DBusMessageIter *iter, bool all);
-
-void bus_async_unregister_and_exit(DBusConnection *bus, const char *name);
-
-DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata);
-
-pid_t bus_get_unix_process_id(DBusConnection *connection, const char *name, DBusError *error);
-
-bool bus_error_is_no_service(const DBusError *error);
-int bus_method_call_with_reply(DBusConnection *bus,
-                               const char *destination,
-                               const char *path,
-                               const char *interface,
-                               const char *method,
-                               DBusMessage **return_reply,
-                               DBusError *return_error,
-                               int first_arg_type, ...);
-
-const char *bus_message_get_sender_with_fallback(DBusMessage *m);
-
-void bus_message_unrefp(DBusMessage **reply);
-
-#define _cleanup_dbus_message_unref_ __attribute__((cleanup(bus_message_unrefp)))
-#define _cleanup_dbus_error_free_ __attribute__((cleanup(dbus_error_free)))
index 2c119e2dcad2b8697cf741c92aa6cdb9568640d6..16504eef0fe7aee6c4306de9a8dbc7e5c7c80ef8 100644 (file)
@@ -1562,6 +1562,7 @@ int unit_file_set_default(
                 UnitFileScope scope,
                 const char *root_dir,
                 const char *file,
+                bool force,
                 UnitFileChange **changes,
                 unsigned *n_changes) {
 
@@ -1599,7 +1600,7 @@ int unit_file_set_default(
 
         path = strappenda(config_path, "/" SPECIAL_DEFAULT_TARGET);
 
-        r = create_symlink(i->path, path, true, changes, n_changes);
+        r = create_symlink(i->path, path, force, changes, n_changes);
         if (r < 0)
                 return r;
 
index 3c2e16285273d1dc8b78c3a0cc065d4f57d6bfd0..e87c57e48af849d62e3cc653cea6bf356be47daf 100644 (file)
@@ -80,7 +80,7 @@ int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char
 int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
-int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, UnitFileChange **changes, unsigned *n_changes);
+int unit_file_set_default(UnitFileScope scope, const char *root_dir, const char *file, bool force, UnitFileChange **changes, unsigned *n_changes);
 int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name);
 
 UnitFileState unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename);
index 537befc623a1554bd4b57bb115ca223bacddbbb4..8af4c51c2f751336e2822a44a1c12e2257960761 100644 (file)
@@ -295,8 +295,8 @@ unsigned prioq_size(Prioq *q) {
                 return 0;
 
         return q->n_items;
-
 }
+
 bool prioq_isempty(Prioq *q) {
 
         if (!q)
index 2e1863675f7f3ce3b58ebdb17bd5a0f02f3885bc..84826a3829d829983c7d41497cc04cc0fea6a52b 100644 (file)
@@ -70,6 +70,7 @@
 #include "bus-util.h"
 #include "bus-message.h"
 #include "bus-error.h"
+#include "bus-errors.h"
 
 static char **arg_types = NULL;
 static char **arg_states = NULL;
@@ -194,7 +195,7 @@ static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error)
                 return EXIT_NOTINSTALLED;
 
         if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
-            sd_bus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
+            sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
                 return EXIT_NOTIMPLEMENTED;
 
         if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
@@ -1400,6 +1401,100 @@ static int get_default(sd_bus *bus, char **args) {
         return 0;
 }
 
+static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
+        unsigned i;
+
+        assert(changes || n_changes == 0);
+
+        for (i = 0; i < n_changes; i++) {
+                if (changes[i].type == UNIT_FILE_SYMLINK)
+                        log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
+                else
+                        log_info("rm '%s'", changes[i].path);
+        }
+}
+
+static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
+        const char *type, *path, *source;
+        int r;
+
+        r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
+                if (!arg_quiet) {
+                        if (streq(type, "symlink"))
+                                log_info("ln -s '%s' '%s'", source, path);
+                        else
+                                log_info("rm '%s'", path);
+                }
+        }
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        r = sd_bus_message_exit_container(m);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        return 0;
+}
+
+static int set_default(sd_bus *bus, char **args) {
+        _cleanup_free_ char *unit = NULL;
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        int r;
+
+        unit = unit_name_mangle_with_suffix(args[1], ".target");
+        if (!unit)
+                return log_oom();
+
+        if (!bus || avoid_bus()) {
+                r = unit_file_set_default(arg_scope, arg_root, unit, arg_force, &changes, &n_changes);
+                if (r < 0) {
+                        log_error("Failed to set default target: %s", strerror(-r));
+                        return r;
+                }
+
+                if (!arg_quiet)
+                        dump_unit_file_changes(changes, n_changes);
+
+                r = 0;
+        } else {
+                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.systemd1",
+                                "/org/freedesktop/systemd1",
+                                "org.freedesktop.systemd1.Manager",
+                                "SetDefaultTarget",
+                                &error,
+                                &reply,
+                                "sb", unit, arg_force);
+                if (r < 0) {
+                        log_error("Failed to set default target: %s", bus_error_message(&error, -r));
+                        return r;
+                }
+
+                r = deserialize_and_dump_unit_file_changes(reply);
+                if (r < 0)
+                        return r;
+
+                /* Try to reload if enabeld */
+                if (!arg_no_reload)
+                        r = daemon_reload(bus, args);
+                else
+                        r = 0;
+        }
+
+        unit_file_changes_free(changes, n_changes);
+
+        return r;
+}
+
 struct job_info {
         uint32_t id;
         const char *name, *type, *state;
@@ -4331,12 +4426,10 @@ static int mangle_names(char **original_names, char ***mangled_names) {
 }
 
 static int enable_unit(sd_bus *bus, char **args) {
-        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
-        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_strv_free_ char **mangled_names = NULL;
         const char *verb = args[0];
         UnitFileChange *changes = NULL;
-        unsigned n_changes = 0, i;
+        unsigned n_changes = 0;
         int carries_install_info = -1;
         int r;
 
@@ -4369,8 +4462,6 @@ static int enable_unit(sd_bus *bus, char **args) {
                         r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
                 else if (streq(verb, "unmask"))
                         r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
-                else if (streq(verb, "set-default"))
-                        r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
                 else
                         assert_not_reached("Unknown verb");
 
@@ -4379,20 +4470,16 @@ static int enable_unit(sd_bus *bus, char **args) {
                         goto finish;
                 }
 
-                if (!arg_quiet) {
-                        for (i = 0; i < n_changes; i++) {
-                                if (changes[i].type == UNIT_FILE_SYMLINK)
-                                        log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
-                                else
-                                        log_info("rm '%s'", changes[i].path);
-                        }
-                }
+                if (!arg_quiet)
+                        dump_unit_file_changes(changes, n_changes);
 
                 r = 0;
         } else {
-                const char *method, *type, *path, *source;
+                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 int expect_carries_install_info = false;
                 bool send_force = true;
+                const char *method;
 
                 if (streq(verb, "enable")) {
                         method = "EnableUnitFiles";
@@ -4413,8 +4500,6 @@ static int enable_unit(sd_bus *bus, char **args) {
                 else if (streq(verb, "unmask")) {
                         method = "UnmaskUnitFiles";
                         send_force = false;
-                } else if (streq(verb, "set-default")) {
-                        method = "SetDefaultTarget";
                 } else
                         assert_not_reached("Unknown verb");
 
@@ -4454,24 +4539,9 @@ static int enable_unit(sd_bus *bus, char **args) {
                                 return bus_log_parse_error(r);
                 }
 
-                r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(sss)");
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                while ((r = sd_bus_message_read(reply, "(sss)", &type, &path, &source)) > 0) {
-                        if (!arg_quiet) {
-                                if (streq(type, "symlink"))
-                                        log_info("ln -s '%s' '%s'", source, path);
-                                else
-                                        log_info("rm '%s'", path);
-                        }
-                }
-                if (r < 0)
-                        return bus_log_parse_error(r);
-
-                r = sd_bus_message_exit_container(reply);
+                r = deserialize_and_dump_unit_file_changes(m);
                 if (r < 0)
-                        return bus_log_parse_error(r);
+                        return r;
 
                 /* Try to reload if enabeld */
                 if (!arg_no_reload)
@@ -5649,8 +5719,8 @@ static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
                 { "link",                  MORE,  2, enable_unit       },
                 { "switch-root",           MORE,  2, switch_root       },
                 { "list-dependencies",     LESS,  2, list_dependencies },
-                { "set-default",           EQUAL, 2, enable_unit       },
-                { "get-default",           LESS,  1, get_default       },
+                { "set-default",           EQUAL, 2, set_default       },
+                { "get-default",           EQUAL, 1, get_default       },
                 { "set-property",          MORE,  3, set_property      },
         };
 
index 072b54fa3afe90417ad273d6927a0bd23d40402f..a09b39f278f764b41d35916e488be916898bf6c6 100644 (file)
@@ -125,10 +125,10 @@ int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_
 int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
 
 int sd_bus_add_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
-int sd_bus_remove_object_vtable(sd_bus *bus, const char *path, const char *interface);
+int sd_bus_remove_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
 
 int sd_bus_add_fallback_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata);
-int sd_bus_remove_fallback_vtable(sd_bus *bus, const char *path, const char *interface);
+int sd_bus_remove_fallback_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata);
 
 int sd_bus_add_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
 int sd_bus_remove_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
index 919b661d61189dd43a6bbe47e223c9cbbbfe7b00..e7b6c9ec9bca74d01f0851d0940e9ce9061d0fa0 100644 (file)
@@ -59,18 +59,16 @@ enum {
 
 enum {
         /* And everything inbetween and outside is good too */
-        SD_PRIORITY_IMPORTANT = -100,
-        SD_PRIORITY_NORMAL = 0,
-        SD_PRIORITY_IDLE = 100
+        SD_EVENT_PRIORITY_IMPORTANT = -100,
+        SD_EVENT_PRIORITY_NORMAL = 0,
+        SD_EVENT_PRIORITY_IDLE = 100
 };
 
-typedef int (*sd_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
-typedef int (*sd_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
-typedef int (*sd_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
-typedef int (*sd_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
-typedef int (*sd_defer_handler_t)(sd_event_source *s, void *userdata);
-typedef int (*sd_prepare_handler_t)(sd_event_source *s, void *userdata);
-typedef int (*sd_quit_handler_t)(sd_event_source *s, void *userdata);
+typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata);
+typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata);
+typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata);
+typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
+typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata);
 
 int sd_event_default(sd_event **e);
 
@@ -78,13 +76,13 @@ int sd_event_new(sd_event **e);
 sd_event* sd_event_ref(sd_event *e);
 sd_event* sd_event_unref(sd_event *e);
 
-int sd_event_add_io(sd_event *e, int fd, uint32_t events, sd_io_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_monotonic(sd_event *e, uint64_t usec, uint64_t accuracy, sd_time_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_realtime(sd_event *e, uint64_t usec, uint64_t accuracy, sd_time_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_signal(sd_event *e, int sig, sd_signal_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_child(sd_event *e, pid_t pid, int options, sd_child_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_defer(sd_event *e, sd_defer_handler_t callback, void *userdata, sd_event_source **s);
-int sd_event_add_quit(sd_event *e, sd_quit_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_io(sd_event *e, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_monotonic(sd_event *e, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_realtime(sd_event *e, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_signal(sd_event *e, int sig, sd_event_signal_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_child(sd_event *e, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_defer(sd_event *e, sd_event_handler_t callback, void *userdata, sd_event_source **s);
+int sd_event_add_quit(sd_event *e, sd_event_handler_t callback, void *userdata, sd_event_source **s);
 
 int sd_event_run(sd_event *e, uint64_t timeout);
 int sd_event_loop(sd_event *e);
@@ -101,7 +99,7 @@ sd_event_source* sd_event_source_unref(sd_event_source *s);
 
 sd_event *sd_event_get(sd_event_source *s);
 
-int sd_event_source_set_prepare(sd_event_source *s, sd_prepare_handler_t callback);
+int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback);
 int sd_event_source_get_pending(sd_event_source *s);
 int sd_event_source_get_priority(sd_event_source *s, int *priority);
 int sd_event_source_set_priority(sd_event_source *s, int priority);