summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/automount.c53
-rw-r--r--src/core/automount.h2
-rw-r--r--src/core/dbus-automount.c62
-rw-r--r--src/core/dbus-automount.h10
-rw-r--r--src/core/dbus-cgroup.c347
-rw-r--r--src/core/dbus-cgroup.h24
-rw-r--r--src/core/dbus-client-track.c250
-rw-r--r--src/core/dbus-client-track.h42
-rw-r--r--src/core/dbus-device.c52
-rw-r--r--src/core/dbus-device.h9
-rw-r--r--src/core/dbus-execute.c596
-rw-r--r--src/core/dbus-execute.h93
-rw-r--r--src/core/dbus-job.c394
-rw-r--r--src/core/dbus-job.h9
-rw-r--r--src/core/dbus-kill.c55
-rw-r--r--src/core/dbus-kill.h17
-rw-r--r--src/core/dbus-manager.c2816
-rw-r--r--src/core/dbus-manager.h10
-rw-r--r--src/core/dbus-mount.c188
-rw-r--r--src/core/dbus-mount.h11
-rw-r--r--src/core/dbus-path.c135
-rw-r--r--src/core/dbus-path.h10
-rw-r--r--src/core/dbus-scope.c127
-rw-r--r--src/core/dbus-scope.h10
-rw-r--r--src/core/dbus-service.c266
-rw-r--r--src/core/dbus-service.h11
-rw-r--r--src/core/dbus-slice.c58
-rw-r--r--src/core/dbus-slice.h9
-rw-r--r--src/core/dbus-snapshot.c73
-rw-r--r--src/core/dbus-snapshot.h8
-rw-r--r--src/core/dbus-socket.c252
-rw-r--r--src/core/dbus-socket.h11
-rw-r--r--src/core/dbus-swap.c140
-rw-r--r--src/core/dbus-swap.h11
-rw-r--r--src/core/dbus-target.c40
-rw-r--r--src/core/dbus-target.h8
-rw-r--r--src/core/dbus-timer.c223
-rw-r--r--src/core/dbus-timer.h10
-rw-r--r--src/core/dbus-unit.c1308
-rw-r--r--src/core/dbus-unit.h134
-rw-r--r--src/core/dbus.c1896
-rw-r--r--src/core/dbus.h26
-rw-r--r--src/core/device.c148
-rw-r--r--src/core/device.h2
-rw-r--r--src/core/job.c195
-rw-r--r--src/core/job.h17
-rw-r--r--src/core/load-fragment-gperf.gperf.m42
-rw-r--r--src/core/load-fragment.c19
-rw-r--r--src/core/main.c50
-rw-r--r--src/core/manager.c652
-rw-r--r--src/core/manager.h93
-rw-r--r--src/core/mount.c141
-rw-r--r--src/core/mount.h2
-rw-r--r--src/core/path.c71
-rw-r--r--src/core/path.h8
-rw-r--r--src/core/scope.c70
-rw-r--r--src/core/scope.h2
-rw-r--r--src/core/selinux-access.c225
-rw-r--r--src/core/selinux-access.h38
-rw-r--r--src/core/service.c257
-rw-r--r--src/core/service.h4
-rw-r--r--src/core/slice.c8
-rw-r--r--src/core/snapshot.c24
-rw-r--r--src/core/snapshot.h2
-rw-r--r--src/core/socket.c256
-rw-r--r--src/core/socket.h8
-rw-r--r--src/core/swap.c113
-rw-r--r--src/core/swap.h5
-rw-r--r--src/core/target.c3
-rw-r--r--src/core/timer.c78
-rw-r--r--src/core/timer.h4
-rw-r--r--src/core/transaction.c82
-rw-r--r--src/core/transaction.h4
-rw-r--r--src/core/unit.c154
-rw-r--r--src/core/unit.h41
75 files changed, 5389 insertions, 7195 deletions
diff --git a/src/core/automount.c b/src/core/automount.c
index d1379e0913..49a64b124f 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -35,13 +35,13 @@
#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,
diff --git a/src/core/automount.h b/src/core/automount.h
index a7a25d34e0..60f5522389 100644
--- a/src/core/automount.h
+++ b/src/core/automount.h
@@ -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;
diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c
index 720f9ba6d1..420cfaa331 100644
--- a/src/core/dbus-automount.c
+++ b/src/core/dbus-automount.c
@@ -19,57 +19,23 @@
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
+};
diff --git a/src/core/dbus-automount.h b/src/core/dbus-automount.h
index b338e25fc1..0b9618368e 100644
--- a/src/core/dbus-automount.h
+++ b/src/core/dbus-automount.h
@@ -21,11 +21,7 @@
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[];
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index f198357637..4dbb83a769 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -19,147 +19,159 @@
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) {
diff --git a/src/core/dbus-cgroup.h b/src/core/dbus-cgroup.h
index e5ac4c3af7..c2a3910f3d 100644
--- a/src/core/dbus-cgroup.h
+++ b/src/core/dbus-cgroup.h
@@ -21,25 +21,9 @@
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
index 0000000000..ce514b577c
--- /dev/null
+++ b/src/core/dbus-client-track.c
@@ -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
index 0000000000..01676479b0
--- /dev/null
+++ b/src/core/dbus-client-track.h
@@ -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);
diff --git a/src/core/dbus-device.c b/src/core/dbus-device.c
index ef484a86b7..621bab0426 100644
--- a/src/core/dbus-device.c
+++ b/src/core/dbus-device.c
@@ -19,50 +19,18 @@
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
+};
diff --git a/src/core/dbus-device.h b/src/core/dbus-device.h
index 311e0685d1..f248c28db3 100644
--- a/src/core/dbus-device.h
+++ b/src/core/dbus-device.h
@@ -21,11 +21,8 @@
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[];
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 2402e8c34d..ca7ee5c10b 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -19,59 +19,102 @@
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 },
- {}
-};
diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h
index 79bf30838a..957742beee 100644
--- a/src/core/dbus-execute.h
+++ b/src/core/dbus-execute.h
@@ -21,87 +21,20 @@
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);
diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
index e1d7504e85..e774383793 100644
--- a/src/core/dbus-job.c
+++ b/src/core/dbus-job.c
@@ -19,303 +19,145 @@
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;
}
diff --git a/src/core/dbus-job.h b/src/core/dbus-job.h
index a1b928fb16..d1d0f6ddf0 100644
--- a/src/core/dbus-job.h
+++ b/src/core/dbus-job.h
@@ -21,13 +21,10 @@
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[];
diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c
index 811adb1b5a..42488b1f54 100644
--- a/src/core/dbus-kill.c
+++ b/src/core/dbus-kill.c
@@ -19,43 +19,44 @@
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));
diff --git a/src/core/dbus-kill.h b/src/core/dbus-kill.h
index 7676d98e91..7c15f3a90b 100644
--- a/src/core/dbus-kill.h
+++ b/src/core/dbus-kill.h
@@ -21,17 +21,10 @@
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);
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 747bcfcb91..2e4de2e431 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -22,320 +22,88 @@
#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));
+}
diff --git a/src/core/dbus-manager.h b/src/core/dbus-manager.h
index f0dce5a2e9..ad451eb6fd 100644
--- a/src/core/dbus-manager.h
+++ b/src/core/dbus-manager.h
@@ -21,8 +21,12 @@
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);
diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c
index 70b2d48330..2056eab11e 100644
--- a/src/core/dbus-mount.c
+++ b/src/core/dbus-mount.c
@@ -19,67 +19,29 @@
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) {
diff --git a/src/core/dbus-mount.h b/src/core/dbus-mount.h
index f4ec8b1625..4bb5d2ddee 100644
--- a/src/core/dbus-mount.h
+++ b/src/core/dbus-mount.h
@@ -21,14 +21,11 @@
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[];
diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c
index a523b81446..a206f49020 100644
--- a/src/core/dbus-path.c
+++ b/src/core/dbus-path.c
@@ -19,104 +19,75 @@
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
+};
diff --git a/src/core/dbus-path.h b/src/core/dbus-path.h
index c945f7d588..e9558f81b5 100644
--- a/src/core/dbus-path.h
+++ b/src/core/dbus-path.h
@@ -21,12 +21,8 @@
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[];
diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c
index c790d26cfe..13ff49d62f 100644
--- a/src/core/dbus-scope.c
+++ b/src/core/dbus-scope.c
@@ -19,95 +19,54 @@
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;
}
diff --git a/src/core/dbus-scope.h b/src/core/dbus-scope.h
index e6836f13f0..30c5e1e0a7 100644
--- a/src/core/dbus-scope.h
+++ b/src/core/dbus-scope.h
@@ -21,13 +21,11 @@
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[];
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index c888570c4b..c4bfa2c38f 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -19,176 +19,92 @@
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;
}
diff --git a/src/core/dbus-service.h b/src/core/dbus-service.h
index 9b9f13701c..5fa9b2f139 100644
--- a/src/core/dbus-service.h
+++ b/src/core/dbus-service.h
@@ -21,14 +21,11 @@
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[];
diff --git a/src/core/dbus-slice.c b/src/core/dbus-slice.c
index eeefcdbcd6..2a48ea455e 100644
--- a/src/core/dbus-slice.c
+++ b/src/core/dbus-slice.c
@@ -19,70 +19,30 @@
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) {
diff --git a/src/core/dbus-slice.h b/src/core/dbus-slice.h
index c5ac473763..eadc3b1a9c 100644
--- a/src/core/dbus-slice.h
+++ b/src/core/dbus-slice.h
@@ -21,13 +21,10 @@
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[];
diff --git a/src/core/dbus-snapshot.c b/src/core/dbus-snapshot.c
index 9978df6022..a4ba588a1d 100644
--- a/src/core/dbus-snapshot.c
+++ b/src/core/dbus-snapshot.c
@@ -19,66 +19,29 @@
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
+};
diff --git a/src/core/dbus-snapshot.h b/src/core/dbus-snapshot.h
index 1208aafff6..f6f432240d 100644
--- a/src/core/dbus-snapshot.h
+++ b/src/core/dbus-snapshot.h
@@ -21,10 +21,8 @@
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);
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c
index 60a8d0501c..e9fa24d1a3 100644
--- a/src/core/dbus-socket.c
+++ b/src/core/dbus-socket.c
@@ -19,122 +19,50 @@
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) {
diff --git a/src/core/dbus-socket.h b/src/core/dbus-socket.h
index eb035c1a94..8808fa2355 100644
--- a/src/core/dbus-socket.h
+++ b/src/core/dbus-socket.h
@@ -21,14 +21,11 @@
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[];
diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c
index 0da86bd6fa..15292cd192 100644
--- a/src/core/dbus-swap.c
+++ b/src/core/dbus-swap.c
@@ -20,125 +20,77 @@
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) {
diff --git a/src/core/dbus-swap.h b/src/core/dbus-swap.h
index 9b586a1ad2..5d357377cd 100644
--- a/src/core/dbus-swap.h
+++ b/src/core/dbus-swap.h
@@ -22,14 +22,11 @@
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[];
diff --git a/src/core/dbus-target.c b/src/core/dbus-target.c
index f143d897fa..205d1c4a88 100644
--- a/src/core/dbus-target.c
+++ b/src/core/dbus-target.c
@@ -19,40 +19,12 @@
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
+};
diff --git a/src/core/dbus-target.h b/src/core/dbus-target.h
index a8a0304c75..6be9c9f708 100644
--- a/src/core/dbus-target.h
+++ b/src/core/dbus-target.h
@@ -21,10 +21,6 @@
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[];
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index c6f1dd9b7f..113c63faa0 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -19,173 +19,136 @@
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
+};
diff --git a/src/core/dbus-timer.h b/src/core/dbus-timer.h
index 9ac30501d1..ddd311c626 100644
--- a/src/core/dbus-timer.h
+++ b/src/core/dbus-timer.h
@@ -21,11 +21,7 @@
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[];
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 032915d14e..49054781c0 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -19,609 +19,645 @@
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 },
- {}
-};
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index 3064cd552a..859de102b6 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -21,133 +21,19 @@
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);
diff --git a/src/core/dbus.c b/src/core/dbus.c
index b0ae3e1ae7..35d185a601 100644
--- a/src/core/dbus.c
+++ b/src/core/dbus.c
@@ -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"
@@ -33,1034 +32,851 @@
#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;
+ }
- dbus_timeout_handle(w->data.bus_timeout);
+ 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;
+ }
+
+ 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;
+static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
+ int r;
- dbus_message_unref(message);
- dbus_pending_call_unref(pending);
+ assert(m);
+ assert(bus);
- /* We simple ask for the name and don't wait for it. Sooner or
- * later we'll have it. */
+ r = sd_bus_add_match(
+ bus,
+ "type='signal',"
+ "path='/org/freedesktop/DBus/Local',"
+ "interface='org.freedesktop.DBus.Local',"
+ "member='Disconnected'",
+ signal_disconnected, m);
- return 0;
-
-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);
-
- 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("ListNames() failed: %s", bus_error_message(&error));
- break;
-
- case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
- int r;
- char **l;
-
- if ((r = bus_parse_strv(reply, &l)) < 0)
- log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
- else {
- char **t;
-
- 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);
-
- strv_free(l);
- }
-
- break;
+ nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+ if (nfd < 0) {
+ log_warning("Failed to accept private connection, ignoring: %m");
+ return 0;
}
- default:
- assert_not_reached("Invalid reply message");
+ if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
+ log_warning("Too many concurrent connections, refusing");
+ return 0;
}
- dbus_message_unref(reply);
- dbus_error_free(&error);
-}
-
-static int query_name_list(Manager *m) {
- DBusMessage *message = NULL;
- DBusPendingCall *pending = NULL;
+ r = set_ensure_allocated(&m->private_buses, trivial_hash_func, trivial_compare_func);
+ if (r < 0) {
+ log_oom();
+ return 0;
+ }
- /* Asks for the currently installed bus names */
+ r = sd_bus_new(&bus);
+ if (r < 0) {
+ log_warning("Failed to allocate new private 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;
+ 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;
+ }
- if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
- goto oom;
+ nfd = -1;
- if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
- goto oom;
+ r = bus_check_peercred(bus);
+ if (r < 0) {
+ log_warning("Incoming private connection from unprivileged client, refusing: %s", strerror(-r));
+ return 0;
+ }
- dbus_message_unref(message);
- dbus_pending_call_unref(pending);
+ assert_se(sd_id128_randomize(&id) >= 0);
- /* We simple ask for the list and don't wait for it. Sooner or
- * later we'll get it. */
+ 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;
+ }
- return 0;
+ r = sd_bus_start(bus);
+ if (r < 0) {
+ log_warning("Failed to start new connection bus: %s", strerror(-r));
+ return 0;
+ }
-oom:
- if (pending) {
- dbus_pending_call_cancel(pending);
- dbus_pending_call_unref(pending);
+ 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;
}
- if (message)
- dbus_message_unref(message);
+ 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;
+ }
+ }
- return -ENOMEM;
-}
+ r = bus_setup_disconnected_match(m, bus);
+ if (r < 0)
+ return 0;
-static int bus_setup_loop(Manager *m, DBusConnection *bus) {
- assert(m);
- assert(bus);
+ 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;
+ }
- dbus_connection_set_exit_on_disconnect(bus, FALSE);
+ 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 (!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();
+ bus = NULL;
- if (set_put(m->bus_connections_for_dispatch, bus) < 0)
- return log_oom();
+ log_debug("Accepted new private connection.");
- 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;
+
+ /* 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);
- return connection;
+ if (r < 0)
+ log_warning("Failed to register Released match on system bus: %s", strerror(-r));
-fail:
- dbus_error_free(&error);
- return NULL;
+ 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;
+
+ mkdir_parents_label(sa.un.sun_path, 0755);
+ }
+
+ unlink(sa.un.sun_path);
- m->private_bus = dbus_server_listen(p, &error);
- free(p);
+ 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 (!m->private_bus) {
- log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
- r = -EIO;
- goto fail;
+ r = bind(fd, &sa.sa, salen);
+ if (r < 0) {
+ log_error("Failed to bind 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 = listen(fd, SOMAXCONN);
+ if (r < 0) {
+ log_error("Failed to make private socket listening: %m");
+ return -errno;
}
- dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
+ 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;
+ }
+
+ m->private_listen_fd = fd;
+ m->private_listen_event_source = s;
+ fd = -1;
log_debug("Successfully created private D-Bus server.");
return 0;
-
-fail:
- bus_done_private(m);
- dbus_error_free(&error);
-
- return r;
}
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;
-
- if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) {
- set_free(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 */
- 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);
}
diff --git a/src/core/dbus.h b/src/core/dbus.h
index 6500cd7455..a3bef47d5d 100644
--- a/src/core/dbus.h
+++ b/src/core/dbus.h
@@ -21,36 +21,14 @@
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[];
diff --git a/src/core/device.c b/src/core/device.c
index 6fc4c95ea0..91e37e09db 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -31,12 +31,15 @@
#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,
diff --git a/src/core/device.h b/src/core/device.h
index 41e8de9703..bb7ae07834 100644
--- a/src/core/device.h
+++ b/src/core/device.h
@@ -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_;
diff --git a/src/core/job.c b/src/core/job.c
index 0dd161c1c5..f053d57349 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -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"
@@ -37,20 +37,7 @@
#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) {
diff --git a/src/core/job.h b/src/core/job.h
index be9d278b0c..60bb87d75a 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -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);
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index b64fdc9dcb..22dc536ee1 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -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
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 72c46371e4..de612f05cb 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -45,12 +45,13 @@
#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;
}
diff --git a/src/core/main.c b/src/core/main.c
index c89c12343e..f342cdd289 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -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>
@@ -34,13 +32,15 @@
#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"
@@ -54,20 +54,21 @@
#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) {
diff --git a/src/core/manager.c b/src/core/manager.c
index c99a022cd5..86de0e3fbf 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -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"
@@ -58,12 +58,9 @@
#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"
@@ -72,6 +69,13 @@
#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)
@@ -86,6 +90,12 @@
#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;
-}
diff --git a/src/core/manager.h b/src/core/manager.h
index b043970340..9eddef20dc 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -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);
diff --git a/src/core/mount.c b/src/core/mount.c
index 0c15b99f94..99e7cedc45 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -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,
diff --git a/src/core/mount.h b/src/core/mount.h
index a9550697e5..2edb75eb54 100644
--- a/src/core/mount.h
+++ b/src/core/mount.h
@@ -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;
diff --git a/src/core/path.c b/src/core/path.c
index 10df80f695..51e8d1dbcc 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -31,9 +31,10 @@
#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
};
diff --git a/src/core/path.h b/src/core/path.h
index dec3df7035..d2e91d7d71 100644
--- a/src/core/path.h
+++ b/src/core/path.h
@@ -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);
diff --git a/src/core/scope.c b/src/core/scope.c
index 41da3b9378..a3c94794b1 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -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,
diff --git a/src/core/scope.h b/src/core/scope.h
index 2a3dcb73d7..4d8a1714bc 100644
--- a/src/core/scope.h
+++ b/src/core/scope.h
@@ -57,7 +57,7 @@ struct Scope {
Set *pids;
- Watch timer_watch;
+ sd_event_source *timer_event_source;
};
extern const UnitVTable scope_vtable;
diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c
index c7e951cde6..0ecbdf0be6 100644
--- a/src/core/selinux-access.c
+++ b/src/core/selinux-access.c
@@ -32,12 +32,11 @@
#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;
}
diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h
index 2d7ac64c8f..0926a5eb09 100644
--- a/src/core/selinux-access.h
+++ b/src/core/selinux-access.h
@@ -21,42 +21,42 @@
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
diff --git a/src/core/service.c b/src/core/service.c
index c0ee1140a8..d9e525e485 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -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...",
diff --git a/src/core/service.h b/src/core/service.h
index 37fa6ff0fa..5c53791753 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -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;
diff --git a/src/core/slice.c b/src/core/slice.c
index 40d416e35e..1e42df2b8b 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -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,
diff --git a/src/core/snapshot.c b/src/core/snapshot.c
index d11239dff3..21e89ac996 100644
--- a/src/core/snapshot.c
+++ b/src/core/snapshot.c
@@ -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
};
diff --git a/src/core/snapshot.h b/src/core/snapshot.h
index 2675b1b242..e6dc661060 100644
--- a/src/core/snapshot.h
+++ b/src/core/snapshot.h
@@ -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_;
diff --git a/src/core/socket.c b/src/core/socket.c
index 751f20bdca..eae9465788 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -27,14 +27,15 @@
#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"
@@ -46,11 +47,12 @@
#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,
diff --git a/src/core/socket.h b/src/core/socket.h
index 3d7eadc9fe..db0796c4a3 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -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;
diff --git a/src/core/swap.c b/src/core/swap.c
index c48c0bd5f9..a798eca3f1 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -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,
diff --git a/src/core/swap.h b/src/core/swap.h
index dd89535895..c51c55f839 100644
--- a/src/core/swap.h
+++ b/src/core/swap.h
@@ -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_;
diff --git a/src/core/target.c b/src/core/target.c
index 3fffa0d2f5..68be22b38d 100644
--- a/src/core/target.c
+++ b/src/core/target.c
@@ -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 = {
diff --git a/src/core/timer.c b/src/core/timer.c
index b90c85f823..5bc01a26ff 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -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,
};
diff --git a/src/core/timer.h b/src/core/timer.h
index 4168553e9d..b3722f0028 100644
--- a/src/core/timer.h
+++ b/src/core/timer.h
@@ -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;
diff --git a/src/core/transaction.c b/src/core/transaction.c
index ba7d8d9828..e2ff0bd1e5 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -22,9 +22,10 @@
#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);
}
}
}
diff --git a/src/core/transaction.h b/src/core/transaction.h
index b6ee237ef8..d949b21b8d 100644
--- a/src/core/transaction.h
+++ b/src/core/transaction.h
@@ -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);
diff --git a/src/core/unit.c b/src/core/unit.c
index 7f463f311b..1173f0b160 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -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;
diff --git a/src/core/unit.h b/src/core/unit.h
index 1a558423f7..c58202bf0f 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -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);